Skip to content

Commit

Permalink
added error handling for emulate prepare with output parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
yukiwongky committed Apr 21, 2017
1 parent 2aec3b4 commit 6d7cddf
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 3 deletions.
12 changes: 11 additions & 1 deletion source/pdo_sqlsrv/pdo_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ int conn_string_parser::discard_trailing_white_spaces( const char* str, int len
}

// Discard white spaces.
bool conn_string_parser::discard_white_spaces()
bool string_parser::discard_white_spaces()
{
if( this->is_eos() ) {

Expand Down Expand Up @@ -477,13 +477,23 @@ void sql_string_parser::parse_sql_string( TSRMLS_D ) {
next();
}
add_key_value_pair( &( this->orig_str[start_pos] ), this->pos - start_pos TSRMLS_CC );
discard_white_spaces();
// if an '=' is right after a placeholder, it means the placeholder is for output parameters
// and emulate prepare does not support output parameters
if (this->orig_str[pos] == '=') {
THROW_PDO_ERROR(this->ctx, PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED);
}
this->current_key++;
}
// if '?', don't need to parse anymore since the position of the bound_param is already stored in the bound_params ht
else if ( sym == '?' ) {
next();
// add dummy value to placeholders ht to keep count of the number of placeholders
add_key_int_value_pair( this->current_key );
discard_white_spaces();
if (this->orig_str[pos] == '=') {
THROW_PDO_ERROR(this->ctx, PDO_SQLSRV_ERROR_EMULATE_INOUT_UNSUPPORTED);
}
this->current_key++;
}
}
Expand Down
2 changes: 1 addition & 1 deletion source/pdo_sqlsrv/php_pdo_sqlsrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ class string_parser
inline bool next(void);
inline bool is_eos(void);
inline bool is_white_space(char c);
bool discard_white_spaces(void);
void add_key_value_pair(const char* value, int len TSRMLS_DC);
};

Expand All @@ -161,7 +162,6 @@ class conn_string_parser : private string_parser

private:
const char* current_key_name;
bool discard_white_spaces(void);
int discard_trailing_white_spaces(const char* str, int len);
void validate_key(const char *key, int key_len TSRMLS_DC);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
--TEST--
uses an input/output parameter with emulate prepare
Tests error returned when binding input/output parameter with emulate prepare
--SKIPIF--
--FILE--
<?php
Expand Down
52 changes: 52 additions & 0 deletions test/pdo_sqlsrv/pdoStatement_bindParam_output_emulate_prepare.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--TEST--
Tests error returned when binding output parameter with emulate prepare
--SKIPIF--
--FILE--
<?php
require_once("autonomous_setup.php");

$database = "tempdb";
$dsn = "sqlsrv:Server=$serverName ; Database = $database";
try {
$conn = new PDO($dsn, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$count = 0;

$query = "select ? = count(* ) from cd_info";
$stmt = $conn->prepare($query, array(PDO::ATTR_EMULATE_PREPARES => true));
$stmt->bindParam( 1, $count, PDO::PARAM_STR, 10 );
$stmt->execute();
echo "Result: ".$count."\n";

$query = "select bigint_type, int_type, money_type from [test_types] where int_type < 0";
$stmt1 = $conn->prepare($query);
$stmt1->execute();
$row = $stmt1->fetch( PDO::FETCH_ASSOC );
print_r($row);

$int = 0;
$bigint = 100;
$query = "select ? = bigint_type, ? = int_type, ? = money_type from [test_types] where int_type < 0";
$stmt2 = $conn->prepare($query, array(PDO::ATTR_EMULATE_PREPARES => true));
$stmt2->bindparam( 1, $bigint, PDO::PARAM_STR, 256 );
$stmt2->bindParam( 2, $int, PDO::PARAM_INT, 4 );
$stmt2->bindParam( 3, $money, PDO::PARAM_STR, 1024 );
$stmt2->execute();
echo "Big integer: ".$bigint."\n";
echo "Integer: ".$int."\n";
echo "Money: ".$money."\n";

//free the statement and connection
$stmt = null;
$stmt1 = null;
$stmt2 = null;
$conn = null;

}
catch(PDOException $e) {
print("Error: " . $e->getMessage() . "\n");
}
?>
--EXPECT--
Error: SQLSTATE[IMSSP]: Statement with emulate prepare on does not support output or input_output parameters.

0 comments on commit 6d7cddf

Please sign in to comment.