Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored SQLSRV tests to test AE with various data types #575

Merged
merged 9 commits into from
Oct 31, 2017
Merged

Refactored SQLSRV tests to test AE with various data types #575

merged 9 commits into from
Oct 31, 2017

Conversation

yitam
Copy link
Contributor

@yitam yitam commented Oct 24, 2017

Mainly the tests using a test table with 28 data types


This change is Reviewable

@coveralls
Copy link

Coverage Status

Coverage increased (+0.02%) to 73.221% when pulling c55ad3e on yitam:Refactor2 into b59fa30 on Microsoft:dev.

@codecov-io
Copy link

codecov-io commented Oct 24, 2017

Codecov Report

Merging #575 into dev will increase coverage by 2.88%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##              dev     #575      +/-   ##
==========================================
+ Coverage   72.01%   74.89%   +2.88%     
==========================================
  Files         125       50      -75     
  Lines       38990    14915   -24075     
==========================================
- Hits        28079    11171   -16908     
+ Misses      10911     3744    -7167
Impacted Files Coverage Δ
...php-7.0.25-src/ext/pdo_sqlsrv/shared/core_stmt.cpp 66.18% <0%> (-1.24%) ⬇️
...x86/php-7.0.25-src/ext/sqlsrv/shared/core_stmt.cpp 78.87% <0%> (-1.16%) ⬇️
...x86/php-7.0.25-src/ext/sqlsrv/shared/core_conn.cpp 70.18% <0%> (-0.22%) ⬇️
...x86/php-7.1.10-src/ext/sqlsrv/shared/core_stmt.cpp
...x64/php-7.0.25-src/ext/sqlsrv/shared/core_conn.cpp
...x86/php-7.0.24-src/ext/sqlsrv/shared/core_stmt.cpp
...php-7.0.25-src/ext/pdo_sqlsrv/shared/core_sqlsrv.h
...php-7.0.24-src/ext/pdo_sqlsrv/shared/core_init.cpp
...x86/php-7.1.10-src/ext/sqlsrv/shared/core_util.cpp
...6/php-7.1.10-src/ext/sqlsrv/shared/core_stream.cpp
... and 120 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b59fa30...4ac4245. Read the comment docs.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.02%) to 73.221% when pulling 63d7a99 on yitam:Refactor2 into b59fa30 on Microsoft:dev.

@yitam yitam requested a review from yukiwongky October 24, 2017 23:18
function createProc($conn, $procName, $procArgs, $procCode)
{
dropProc($conn, $procName);
$stmt = sqlsrv_query($conn, "CREATE PROC [$procName] ($procArgs) AS BEGIN $procCode END");
if ($stmt === false) {
fatalError("Failed to create test procedure");
fatalError("Failed to create test procedure", true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default is already true, no need to put this in

@@ -509,7 +376,7 @@ function callProcEx($conn, $procName, $procPrefix, $procArgs, $procValues)
{
$stmt = sqlsrv_query($conn, "{ $procPrefix CALL [$procName] ($procArgs)}", $procValues);
if ($stmt === false) {
fatalError("Failed to call test procedure");
fatalError("Failed to call test procedure", true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as line 355

!strcasecmp($this->dataType, "hierarchyid") ||
!strcasecmp($this->dataType, "geography") ||
!strcasecmp($this->dataType, "geometry") ||
!strcasecmp($this->dataType, "alias")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

money and smallmoney are also not supported, why comment out?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also it would look nicer to put all the unsupported types in an array and there an array_in function that you can use in php to find a match

Copy link
Contributor Author

@yitam yitam Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when we do not encrypt money or smallmoney one of the AE tests with money types fail...
that's why I changed the ColumnMeta to take an optional parameter to not to encrypt a particular column instead

$this->dataType = $dataType;
$this->options = $options;

// first asssumes the column is not encryptable
$this->encryptable = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not put this in an else block instead of assuming?

*/
protected function checkIfUnsupported()
{
$this->encryptable = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, you can put this into an else block

@@ -325,6 +377,7 @@ function connect($options = array(), $disableCE = false)
* @param object $conn : sqlsrv connection object
* @param string $tbname : name of the table to be created
* @param array $columnMetaArr : array of ColumnMeta objects, which contain metadata for one column
* @return object sqlsrv statement
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe sqlsrv statement is a resource not an object, same with sqlsrv connection

$r = sqlsrv_execute($stmt);
if ($stmt) {
$r = sqlsrv_execute($stmt);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you're going to check $stmt, maybe output the error as well

@@ -370,32 +425,106 @@ function insertRow($conn, $tbname, $inputs, &$r = null, $api = INSERT_QUERY)
$params = array();
foreach ($inputs as $key => $input) {
if (is_object($input)) {
array_push($params, $input->bindParamArr($inputs[$key]));
array_push($params, $input->bindParamArr($input->value));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is very strange looking. If you're calling a member function from $input, the function will have access to everything in $input. Passing in $input->value is not necessary. Please change bindParamArr function accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reverted the change now. Thanks!

*/
function executeQuery($conn, $sql, $conds = null, $values = null)
{
// when AE is enabled, use sqlsrv_prepare() to handle fields with unlimited size
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how can you tell if a field has unlimited size from here? If AE is enabled, does it always use sqlsrv_prepare?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I'll modify the comments accordingly

* all deterministic if AE is enabled
* @param resource $conn : connection resource
* @param string $tbname : name of the table to create
* @return object sqlsrv statement
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sqlsrv statement is a resoure

* @param resource $conn : connection resource
* @param string $tbname : name of the table to create
* @param int $index : the index of a certain row of test data
* @return object sqlsrv statement upon success or false otherwise
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resource


$result = null;
if (isColEncrypted()) {
$stmt = insertRow($conn, $tbname, $inputArray, $result, INSERT_PREPARE_PARAMS);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

INSERT_PREPARE_PARAMS is redundant since in insertRow, isColEncrypted() and INSERT_PREPARE_PARAMS go to the same path (line 435)

* literal or a BindParamOption object
* @param bool $r : true if the row was successfully inserted, otherwise false. Default value is null to make this parameter optional.
* $param string $api : SQLSRV API used for executing the insert query
* accepted values: INSERT_QUERY, INSERT_PREPARE, INSERT_QUERY_PARAMS, INSERT_PREPARE_PARAMS
* accepted values: INSERT_QUERY, INSERT_PREPARE, INSERT_QUERY_PARAMS, INSERT_PREPARE_PARAMS
Copy link
Contributor

@yukiwongky yukiwongky Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since you've already defined these constants, they are no longer string, use long

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to int

// this might be an input to a decimal, a numeric or a binary field
if (isBinary($col)) {
$value = "0x" . $value; // annotate the input string as a hex string
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't you call insertRow after you've modified the binary data?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no I can't because binary data needs special handling which the generic function insertRow not supposed to know

// get array of input values
$inputArray = getInsertArray($rowIndex);
if (empty($inputArray)) {
fatalError("getInsertData: failed to retrieve data at row $rowIndex and column $colIndex.\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get rid of "and column $colIndex" since the error comes from only $rowIndex

@@ -449,7 +773,7 @@ function getSqlType($k)
return ("udt");
}

function getDriverType($k, $dataSize)
function getDriverType($k, $dataSize = 512)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does 512 come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was for convenience, but I only need it for one test, so I'll move this constant to that test instead.

insertRows($conn1, $tableName, $noRows);
// Insert a couple of random rows
AE\createTestTable($conn1, $tableName);
AE\insertTestRows($conn1, $tableName, 2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why change $noRows from 5 to 2?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just thought the essence of the test is not really the data. Anyway, I've reverted the change.

$conn2 = connect();
$stmt2 = selectFromTable($conn2, $tableName);
$conn2 = AE\connect();
$stmt2 = sqlsrv_query($conn2, "SELECT * FROM [$tableName]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why can't you call selectFromTable?


trace("Executing SELECT query on $tableName ...");
$stmt1 = selectFromTable($conn1, $tableName);
$stmt1 = sqlsrv_query($conn1, "SELECT * FROM $tableName");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use createTable and selectFromTable?


createTable($conn1, $tableName);
// just create an empty table
$stmt1 = sqlsrv_query($conn1, "CREATE TABLE $tableName (dummyColumn int)");

trace("Executing SELECT query on $tableName ...");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were going to get rid of trace

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind keeping them around. Some tests have useful trace statements.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we never turn tracemode on.. If you think the output is useful, then use echo or print

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally do when I need to debug what goes wrong. If I use echo/print if will affect the expected output, which is often unnecessary.

$rows = rowCount($stmt1);
;
sqlsrv_free_stmt($stmt1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please dropTable at the end of the test

$cond = "(c1_int = $keyValue)";

$stmt3 = selectFromTableEx($conn1, $tableName, $cond);
$cond = "(c1_int = ?)";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it a good idea to change the test to use a placeholder completely? Now even if isColEnc() is false, the test still uses sqlsrv_prepare with placeholder to run the query, whereas before is used to use sqlsrv_query on a direct query. When refactoring tests, we want to keep the behavior of the original test as intact as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to put the logic in AE\executeQuery() instead so that each placeholder will be replaced with literal value if not encrypted

createTableEx($conn1, $tableName, $dataType);

$columns = array(new AE\ColumnMeta('int', 'c1'),
new AE\ColumnMeta('int', 'c2'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is createTable?

} else { // should check data even if $fld is null
$data = getInsertData($startRow + $i, $col, $skipCount);
if (!CheckData($col, $fld, $data)) {
$data = AE\getInsertData($startRow + $i, $col);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how come you getInsertData before checking if $col isUpdatable?

Can you also explain what $skipCount does and why you got rid of it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the timestamp column (column 27) is updatable, and the original way to look for insert data is to skip this column. I'll explain more if this is unclear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I'm beginning to understand what $skipCount is for now. But I still don't understand why you have getInsertData in line 47. There is an identical line in line 50, and $data is only used inside the isUpdatable if block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it was an oversight. Thanks!

if (sqlsrv_next_result($stmt1) ||
sqlsrv_next_result($stmt2)) {
if ($r1 = sqlsrv_next_result($stmt1) ||
$r2 = sqlsrv_next_result($stmt2)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need to introduce $r1 and $r2?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was for debugging when I thought I discovered a bug... forgot to remove them afterwards ;)

AE\insertRow($conn1,
$tableName,
array("c1"=>$k, "c2"=>array($data, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), $phpDriverType)),
$res,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you just put null here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried to be faithful to the original test, in which it called a function insertRowEx() that does the following:
$stmt = sqlsrv_query($conn, "INSERT INTO [$tableName] ($dataCols) VALUES ($dataValues)", $dataOptions);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?? I was talking about $res

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope... I will get the error Fatal error: Uncaught Error: Cannot pass parameter 4 by reference


sqlsrv_close($conn1);

endTest($testName);
}

function CreateQueryTable($conn, $table, $dataType, $dataCols, $dataValues, $dataOptions, $execMode)
function insertQueryTable($conn, $tableName, $params, $execMode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you not use insertRow for this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no because it's specific to this test, in which they set the option SendStreamParamsAtExec on and off for testing

break;
}
if ($data != null) {
$sqlType = GetSqlType($k);
$sqlType = getSqlType($k);
$driverType = getDriverType($k);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the name of this function is very misleading. I thought getDriverType gets the PHP zend type... can you change the name of this to getSqlsrvSqltype() or something more clear?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's confusing, but that was one of the common functions originally in MsCommon... I'll see how many tests are affected by the renaming.

@@ -74,40 +74,50 @@ function ProcQuery($minType, $maxType)
endTest($testName);
}

function ExecProcQuery($conn, $procName, $dataType, $inData1, $inData2, $outData)
function execprocQuery($conn, $procName, $type, $dataType, $inData1, $inData2, $outData)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

execProcQuery

{
include 'MsSetup.inc';
// include 'MsSetup.inc';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete this line

$s = sqlsrv_query($conn1, "DROP TABLE test_bq");
$s = sqlsrv_query($conn1, "CREATE TABLE test_bq (id INT IDENTITY NOT NULL, test_varchar_max varchar(max))");
$tableName = "test_bq";
dropTable($conn1, $tableName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think createTable already drop the table before creating the table, so this line is not necessary.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) to 73.21% when pulling 4d364e1 on yitam:Refactor2 into b59fa30 on Microsoft:dev.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.02%) to 73.221% when pulling 786bd50 on yitam:Refactor2 into b59fa30 on Microsoft:dev.

$this->dataType = $dataType;
$this->options = $options;

// first asssumes the column is not encryptable
// $this->encryptable = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please get rid of comments

// when AE is enabled, use sqlsrv_prepare() to handle fields with unlimited size
if (!isColEncrypted() && (is_null($conds) || empty($values))) {
if (!isColEncrypted()) {
if (!empty($values)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a comment saying this if block is for replacing '?' placeholders with values

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.2%) to 73.043% when pulling 83a378b on yitam:Refactor2 into b59fa30 on Microsoft:dev.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.2%) to 73.043% when pulling 4ac4245 on yitam:Refactor2 into b59fa30 on Microsoft:dev.

@yitam yitam merged commit bd001a5 into microsoft:dev Oct 31, 2017
@yitam yitam deleted the Refactor2 branch October 31, 2017 22:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants