diff --git a/README.md b/README.md
index 46a992b6..9e1cc788 100644
--- a/README.md
+++ b/README.md
@@ -37,8 +37,6 @@ Thank you for taking time to take our February survey. Let us know how we are do
## Announcements
-**March 7, 2017**: We are thrilled to announce that the early technical preview for SQLSRV and PDO_SQLSRV drivers is now available, both drivers have been built and tested on El Capitan (OS X 10.11). For complete list of changes please visit [4.1.7-preview release notes](https://github.com/Microsoft/msphpsql/releases/tag/v4.1.7-preview).
-
Please visit the [blog][blog] for more announcements.
diff --git a/source/pdo_sqlsrv/config.m4 b/source/pdo_sqlsrv/config.m4
index 2b310f92..328bbe6b 100644
--- a/source/pdo_sqlsrv/config.m4
+++ b/source/pdo_sqlsrv/config.m4
@@ -66,3 +66,7 @@ if test "$PHP_PDO_SQLSRV" != "no"; then
PHP_ADD_BUILD_DIR([$ext_builddir/shared], 1)
fi
+#if (defined __APPLE__ && defined __MACH__) \
+ MACOSX_DEPLOYMENT_TARGET=`sw_vers -productVersion` \
+#endif
+
diff --git a/source/pdo_sqlsrv/config.w32 b/source/pdo_sqlsrv/config.w32
index 1538dcae..f197d1cb 100644
--- a/source/pdo_sqlsrv/config.w32
+++ b/source/pdo_sqlsrv/config.w32
@@ -3,7 +3,7 @@
//
// Contents: JScript build configuration used by buildconf.bat
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/pdo_sqlsrv/pdo_dbh.cpp b/source/pdo_sqlsrv/pdo_dbh.cpp
index 10cc9b7c..b0ce8712 100644
--- a/source/pdo_sqlsrv/pdo_dbh.cpp
+++ b/source/pdo_sqlsrv/pdo_dbh.cpp
@@ -3,7 +3,7 @@
//
// Contents: Implements the PDO object for PDO_SQLSRV
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@@ -57,6 +57,7 @@ const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
const char TrustServerCertificate[] = "TrustServerCertificate";
const char TransactionIsolation[] = "TransactionIsolation";
+const char TransparentNetworkIPResolution[] = "TransparentNetworkIPResolution";
const char WSID[] = "WSID";
}
@@ -338,6 +339,15 @@ const connection_option PDO_CONN_OPTS[] = {
CONN_ATTR_BOOL,
pdo_bool_conn_str_func::func
},
+ {
+ PDOConnOptionNames::TransparentNetworkIPResolution,
+ sizeof(PDOConnOptionNames::TransparentNetworkIPResolution),
+ SQLSRV_CONN_OPTION_TRANSPARANT_NETWORK_IP_RESOLUTION,
+ ODBCConnOptions::TransparentNetworkIPResolution,
+ sizeof(ODBCConnOptions::TransparentNetworkIPResolution),
+ CONN_ATTR_STRING,
+ conn_str_append_func::func
+ },
{
PDOConnOptionNames::WSID,
sizeof( PDOConnOptionNames::WSID ),
diff --git a/source/pdo_sqlsrv/pdo_init.cpp b/source/pdo_sqlsrv/pdo_init.cpp
index 5be8480c..7799ed1f 100644
--- a/source/pdo_sqlsrv/pdo_init.cpp
+++ b/source/pdo_sqlsrv/pdo_init.cpp
@@ -3,7 +3,7 @@
//
// Contents: initialization routines for PDO_SQLSRV
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/pdo_sqlsrv/pdo_parser.cpp b/source/pdo_sqlsrv/pdo_parser.cpp
index 1b726a07..3cc8f3b2 100644
--- a/source/pdo_sqlsrv/pdo_parser.cpp
+++ b/source/pdo_sqlsrv/pdo_parser.cpp
@@ -5,7 +5,7 @@
//
// Copyright Microsoft Corporation
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/pdo_sqlsrv/pdo_stmt.cpp b/source/pdo_sqlsrv/pdo_stmt.cpp
index 1421bc85..d5f98a07 100644
--- a/source/pdo_sqlsrv/pdo_stmt.cpp
+++ b/source/pdo_sqlsrv/pdo_stmt.cpp
@@ -3,7 +3,7 @@
//
// Contents: Implements the PDOStatement object for the PDO_SQLSRV
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/pdo_sqlsrv/pdo_util.cpp b/source/pdo_sqlsrv/pdo_util.cpp
index 63fabfb4..46e69868 100644
--- a/source/pdo_sqlsrv/pdo_util.cpp
+++ b/source/pdo_sqlsrv/pdo_util.cpp
@@ -3,7 +3,7 @@
//
// Contents: Utility functions used by both connection or statement functions
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/pdo_sqlsrv/php_pdo_sqlsrv.h b/source/pdo_sqlsrv/php_pdo_sqlsrv.h
index 22edd00a..6fc96e26 100644
--- a/source/pdo_sqlsrv/php_pdo_sqlsrv.h
+++ b/source/pdo_sqlsrv/php_pdo_sqlsrv.h
@@ -6,7 +6,7 @@
//
// Contents: Declarations for the extension
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/pdo_sqlsrv/template.rc b/source/pdo_sqlsrv/template.rc
index ec61efa6..63326055 100644
--- a/source/pdo_sqlsrv/template.rc
+++ b/source/pdo_sqlsrv/template.rc
@@ -3,7 +3,7 @@
//
// Contents: Version resource
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/FormattedPrint.cpp b/source/shared/FormattedPrint.cpp
index 5b0c5aef..ba5520bd 100644
--- a/source/shared/FormattedPrint.cpp
+++ b/source/shared/FormattedPrint.cpp
@@ -6,7 +6,7 @@
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/FormattedPrint.h b/source/shared/FormattedPrint.h
index d1ee9708..d789afa7 100644
--- a/source/shared/FormattedPrint.h
+++ b/source/shared/FormattedPrint.h
@@ -4,7 +4,7 @@
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/StringFunctions.cpp b/source/shared/StringFunctions.cpp
index 68016c14..ca2ec89b 100644
--- a/source/shared/StringFunctions.cpp
+++ b/source/shared/StringFunctions.cpp
@@ -3,7 +3,7 @@
//
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/StringFunctions.h b/source/shared/StringFunctions.h
index fdec4291..323d308a 100644
--- a/source/shared/StringFunctions.h
+++ b/source/shared/StringFunctions.h
@@ -3,7 +3,7 @@
//
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/core_conn.cpp b/source/shared/core_conn.cpp
index a459c16d..a2d92aa0 100644
--- a/source/shared/core_conn.cpp
+++ b/source/shared/core_conn.cpp
@@ -3,7 +3,7 @@
//
// Contents: Core routines that use connection handles shared between sqlsrv and pdo_sqlsrv
//
-// Microsoft Drivers 4.1 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/core_init.cpp b/source/shared/core_init.cpp
index 4bf80167..01d54468 100644
--- a/source/shared/core_init.cpp
+++ b/source/shared/core_init.cpp
@@ -3,7 +3,7 @@
//
// Contents: common initialization routines shared by PDO and sqlsrv
//
-// Microsoft Drivers 4.1 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/core_results.cpp b/source/shared/core_results.cpp
index 7c2b1bfd..73299952 100644
--- a/source/shared/core_results.cpp
+++ b/source/shared/core_results.cpp
@@ -3,7 +3,7 @@
//
// Contents: Result sets
//
-// Microsoft Drivers 4.1 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/core_sqlsrv.h b/source/shared/core_sqlsrv.h
index dd3c3bbc..7ddcfa34 100644
--- a/source/shared/core_sqlsrv.h
+++ b/source/shared/core_sqlsrv.h
@@ -6,7 +6,7 @@
//
// Contents: Core routines and constants shared by the Microsoft Drivers for PHP for SQL Server
//
-// Microsoft Drivers 4.1 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@@ -1100,6 +1100,7 @@ const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
const char TrustServerCertificate[] = "TrustServerCertificate";
const char TransactionIsolation[] = "TransactionIsolation";
+const char TransparentNetworkIPResolution[] = "TransparentNetworkIPResolution";
const char WSID[] = "WSID";
const char UID[] = "UID";
const char PWD[] = "PWD";
@@ -1128,6 +1129,7 @@ enum SQLSRV_CONN_OPTIONS {
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
SQLSRV_CONN_OPTION_AUTHENTICATION,
+ SQLSRV_CONN_OPTION_TRANSPARANT_NETWORK_IP_RESOLUTION,
#ifdef _WIN32
SQLSRV_CONN_OPTION_CONN_RETRY_COUNT,
SQLSRV_CONN_OPTION_CONN_RETRY_INTERVAL,
diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp
index 1ef36ac4..49114d92 100644
--- a/source/shared/core_stmt.cpp
+++ b/source/shared/core_stmt.cpp
@@ -3,7 +3,7 @@
//
// Contents: Core routines that use statement handles shared between sqlsrv and pdo_sqlsrv
//
-// Microsoft Drivers 4.1 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/core_stream.cpp b/source/shared/core_stream.cpp
index ad915ad7..a29ec086 100644
--- a/source/shared/core_stream.cpp
+++ b/source/shared/core_stream.cpp
@@ -3,7 +3,7 @@
//
// Contents: Implementation of PHP streams for reading SQL Server data
//
-// Microsoft Drivers 4.1 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/core_util.cpp b/source/shared/core_util.cpp
index 4eeeb6d0..202e23fb 100644
--- a/source/shared/core_util.cpp
+++ b/source/shared/core_util.cpp
@@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
-// Microsoft Drivers 4.1 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/globalization.h b/source/shared/globalization.h
index 60177028..cd8b744f 100644
--- a/source/shared/globalization.h
+++ b/source/shared/globalization.h
@@ -4,7 +4,7 @@
// Contents: Contains functions for handling Windows format strings
// and UTF-16 on non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/interlockedatomic.h b/source/shared/interlockedatomic.h
index fdeae014..30941ee0 100644
--- a/source/shared/interlockedatomic.h
+++ b/source/shared/interlockedatomic.h
@@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, atomic
// operations on int32_t and pointer types.
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/interlockedatomic_gcc.h b/source/shared/interlockedatomic_gcc.h
index 99160fb2..e4e4205b 100644
--- a/source/shared/interlockedatomic_gcc.h
+++ b/source/shared/interlockedatomic_gcc.h
@@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, atomic
// operations on int32_t and pointer types.
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/interlockedslist.h b/source/shared/interlockedslist.h
index 2c6ef47f..0a262aeb 100644
--- a/source/shared/interlockedslist.h
+++ b/source/shared/interlockedslist.h
@@ -4,7 +4,7 @@
// Contents: Contains a portable abstraction for interlocked, singly
// linked list.
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/localization.hpp b/source/shared/localization.hpp
index 34384599..a5310650 100644
--- a/source/shared/localization.hpp
+++ b/source/shared/localization.hpp
@@ -3,7 +3,7 @@
//
// Contents: Contains portable classes for localization
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/localizationimpl.cpp b/source/shared/localizationimpl.cpp
index 058029c1..381b9cc5 100644
--- a/source/shared/localizationimpl.cpp
+++ b/source/shared/localizationimpl.cpp
@@ -5,7 +5,7 @@
// Must be included in one c/cpp file per binary
// A build error will occur if this inclusion policy is not followed
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/msodbcsql.h b/source/shared/msodbcsql.h
index b853b9ad..e2a4bf0d 100644
--- a/source/shared/msodbcsql.h
+++ b/source/shared/msodbcsql.h
@@ -4,7 +4,7 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: msodbcsql.h
//
-// Contents: Routines that use statement handles
+// Contents: Routines that use statement handles. This is a subset of the header file msodbcsql.h in the ODBC Driver.
//
// Contents: This SDK is not supported under any Microsoft standard support
// program or service. The information is provided AS IS without
@@ -20,7 +20,7 @@
// pecuniary loss) arising out of the use of or inability to use
// this SDK, even if Microsoft has been advised of the possibility
// of such damages.
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@@ -36,7 +36,7 @@
#if !defined(SQLODBC_VER)
-#define SQLODBC_VER 1100
+#define SQLODBC_VER 1300
#endif
#if SQLODBC_VER >= 1300
@@ -46,7 +46,7 @@
#define SQLODBC_PRODUCT_NAME_SHORT_VER_ANSI "ODBC Driver 13 for SQL Server"
#define SQLODBC_PRODUCT_NAME_SHORT_ANSI "ODBC Driver for SQL Server"
-#endif /* SQLODBC_VER >= 1300 */
+#endif // SQLODBC_VER >= 1300
#define SQLODBC_PRODUCT_NAME_FULL_VER SQLODBC_PRODUCT_NAME_FULL_VER_ANSI
#define SQLODBC_PRODUCT_NAME_FULL SQLODBC_PRODUCT_NAME_FULL_ANSI
@@ -55,147 +55,145 @@
#define SQLODBC_DRIVER_NAME SQLODBC_PRODUCT_NAME_SHORT_VER
-/* max SQL Server identifier length */
+// max SQL Server identifier length
#define SQL_MAX_SQLSERVERNAME 128
-/*
- * SQLSetConnectAttr driver specific defines.
- * Microsoft has 1200 thru 1249 reserved for Microsoft ODBC Driver for SQL Server usage.
- * Connection attributes
- */
+
+// SQLSetConnectAttr driver specific defines.
+// Microsoft has 1200 thru 1249 reserved for Microsoft ODBC Driver for SQL Server usage.
+// Connection attributes
+
#define SQL_COPT_SS_BASE 1200
-#define SQL_COPT_SS_INTEGRATED_SECURITY (SQL_COPT_SS_BASE+3) /* Force integrated security on login */
-#define SQL_COPT_SS_TRANSLATE (SQL_COPT_SS_BASE+20) /* Perform code page translation */
-#define SQL_COPT_SS_ENCRYPT (SQL_COPT_SS_BASE+23) /* Allow strong encryption for data */
-#define SQL_COPT_SS_MARS_ENABLED (SQL_COPT_SS_BASE+24) /* Multiple active result set per connection */
-#define SQL_COPT_SS_TXN_ISOLATION (SQL_COPT_SS_BASE+27) /* Used to set/get any driver-specific or ODBC-defined TXN iso level */
-#define SQL_COPT_SS_TRUST_SERVER_CERTIFICATE (SQL_COPT_SS_BASE+28) /* Trust server certificate */
-/*
- * SQLSetStmtAttr Microsoft ODBC Driver for SQL Server specific defines.
- * Statement attributes
- */
+#define SQL_COPT_SS_INTEGRATED_SECURITY (SQL_COPT_SS_BASE+3) // Force integrated security on login
+#define SQL_COPT_SS_TRANSLATE (SQL_COPT_SS_BASE+20) // Perform code page translation
+#define SQL_COPT_SS_ENCRYPT (SQL_COPT_SS_BASE+23) // Allow strong encryption for data
+#define SQL_COPT_SS_MARS_ENABLED (SQL_COPT_SS_BASE+24) // Multiple active result set per connection
+#define SQL_COPT_SS_TXN_ISOLATION (SQL_COPT_SS_BASE+27) // Used to set/get any driver-specific or ODBC-defined TXN iso level
+#define SQL_COPT_SS_TRUST_SERVER_CERTIFICATE (SQL_COPT_SS_BASE+28) // Trust server certificate
+
+// SQLSetStmtAttr Microsoft ODBC Driver for SQL Server specific defines.
+// Statement attributes
+
#define SQL_SOPT_SS_BASE 1225
-#define SQL_SOPT_SS_TEXTPTR_LOGGING (SQL_SOPT_SS_BASE+0) /* Text pointer logging */
-#define SQL_SOPT_SS_NOBROWSETABLE (SQL_SOPT_SS_BASE+3) /* Set NOBROWSETABLE option */
-#define SQL_SOPT_SS_COLUMN_ENCRYPTION (SQL_SOPT_SS_BASE+13)/* Sets the column encryption mode */
-/* Define old names */
+#define SQL_SOPT_SS_TEXTPTR_LOGGING (SQL_SOPT_SS_BASE+0) // Text pointer logging
+#define SQL_SOPT_SS_NOBROWSETABLE (SQL_SOPT_SS_BASE+3) // Set NOBROWSETABLE option
+#define SQL_SOPT_SS_COLUMN_ENCRYPTION (SQL_SOPT_SS_BASE+13)// Sets the column encryption mode
+// Define old names
#define SQL_TEXTPTR_LOGGING SQL_SOPT_SS_TEXTPTR_LOGGING
#define SQL_COPT_SS_BASE_EX 1240
-#define SQL_COPT_SS_WARN_ON_CP_ERROR (SQL_COPT_SS_BASE_EX+3) /* Issues warning when data from the server had a loss during code page conversion. */
-#define SQL_COPT_SS_CONNECTION_DEAD (SQL_COPT_SS_BASE_EX+4) /* dbdead SQLGetConnectOption only. It will try to ping the server. Expensive connection check */
-#define SQL_COPT_SS_APPLICATION_INTENT (SQL_COPT_SS_BASE_EX+7) /* Application Intent */
-#define SQL_COPT_SS_MULTISUBNET_FAILOVER (SQL_COPT_SS_BASE_EX+8) /* Multi-subnet Failover */
-#define SQL_COPT_SS_TNIR (SQL_COPT_SS_BASE_EX+9) /* Transparent Network IP Resolution */
-#define SQL_COPT_SS_COLUMN_ENCRYPTION (SQL_COPT_SS_BASE_EX+10) /* Always Encrypted Enabled or Disabled */
-#define SQL_COPT_SS_AEKEYSTOREPROVIDER (SQL_COPT_SS_BASE_EX+11) /* Load a keystore provider or read the list of loaded keystore providers */
-#define SQL_COPT_SS_AEKEYSTOREDATA (SQL_COPT_SS_BASE_EX+12) /* Communicate with a loaded keystore provider */
-#define SQL_COPT_SS_AETRUSTEDCMKPATHS (SQL_COPT_SS_BASE_EX+13) /* List of trusted CMK paths */
-#define SQL_COPT_SS_AECEKCACHETTL (SQL_COPT_SS_BASE_EX+14) /* Symmetric Key Cache TTL */
-#define SQL_COPT_SS_AUTHENTICATION (SQL_COPT_SS_BASE_EX+15) /* The authentication method used for the connection */
+#define SQL_COPT_SS_WARN_ON_CP_ERROR (SQL_COPT_SS_BASE_EX+3) // Issues warning when data from the server had a loss during code page conversion.
+#define SQL_COPT_SS_CONNECTION_DEAD (SQL_COPT_SS_BASE_EX+4) // dbdead SQLGetConnectOption only. It will try to ping the server. Expensive connection check
+#define SQL_COPT_SS_APPLICATION_INTENT (SQL_COPT_SS_BASE_EX+7) // Application Intent
+#define SQL_COPT_SS_MULTISUBNET_FAILOVER (SQL_COPT_SS_BASE_EX+8) // Multi-subnet Failover
+#define SQL_COPT_SS_TNIR (SQL_COPT_SS_BASE_EX+9) // Transparent Network IP Resolution
+#define SQL_COPT_SS_COLUMN_ENCRYPTION (SQL_COPT_SS_BASE_EX+10)// Column Encryption Enabled or Disabled
+#define SQL_COPT_SS_CEKEYSTOREPROVIDER (SQL_COPT_SS_BASE_EX+11)// Load a keystore provider or read the list of loaded keystore providers
+#define SQL_COPT_SS_CEKEYSTOREDATA (SQL_COPT_SS_BASE_EX+12)// Communicate with loaded keystore providers
+#define SQL_COPT_SS_TRUSTEDCMKPATHS (SQL_COPT_SS_BASE_EX+13)// List of trusted CMK paths
+#define SQL_COPT_SS_CEKCACHETTL (SQL_COPT_SS_BASE_EX+14)// Symmetric Key Cache TTL
+#define SQL_COPT_SS_AUTHENTICATION (SQL_COPT_SS_BASE_EX+15)// The authentication method used for the connection
-/*
- * SQLColAttributes driver specific defines.
- * SQLSetDescField/SQLGetDescField driver specific defines.
- * Microsoft has 1200 thru 1249 reserved for Microsoft ODBC Driver for SQL Server usage.
- */
+// SQLColAttributes driver specific defines.
+// SQLSetDescField/SQLGetDescField driver specific defines.
+// Microsoft has 1200 thru 1249 reserved for Microsoft ODBC Driver for SQL Server usage.
+
#define SQL_CA_SS_BASE 1200
-#define SQL_CA_SS_COLUMN_SSTYPE (SQL_CA_SS_BASE+0) /* dbcoltype/dbalttype */
-#define SQL_CA_SS_COLUMN_UTYPE (SQL_CA_SS_BASE+1) /* dbcolutype/dbaltutype */
-#define SQL_CA_SS_NUM_ORDERS (SQL_CA_SS_BASE+2) /* dbnumorders */
-#define SQL_CA_SS_COLUMN_ORDER (SQL_CA_SS_BASE+3) /* dbordercol */
-#define SQL_CA_SS_COLUMN_VARYLEN (SQL_CA_SS_BASE+4) /* dbvarylen */
-#define SQL_CA_SS_NUM_COMPUTES (SQL_CA_SS_BASE+5) /* dbnumcompute */
-#define SQL_CA_SS_COMPUTE_ID (SQL_CA_SS_BASE+6) /* dbnextrow status return */
-#define SQL_CA_SS_COMPUTE_BYLIST (SQL_CA_SS_BASE+7) /* dbbylist */
-#define SQL_CA_SS_COLUMN_ID (SQL_CA_SS_BASE+8) /* dbaltcolid */
-#define SQL_CA_SS_COLUMN_OP (SQL_CA_SS_BASE+9) /* dbaltop */
-#define SQL_CA_SS_COLUMN_SIZE (SQL_CA_SS_BASE+10) /* dbcollen */
-#define SQL_CA_SS_COLUMN_HIDDEN (SQL_CA_SS_BASE+11) /* Column is hidden (FOR BROWSE) */
-#define SQL_CA_SS_COLUMN_KEY (SQL_CA_SS_BASE+12) /* Column is key column (FOR BROWSE) */
-#define SQL_CA_SS_COLUMN_COLLATION (SQL_CA_SS_BASE+14) /* Column collation (only for chars) */
+#define SQL_CA_SS_COLUMN_SSTYPE (SQL_CA_SS_BASE+0) // dbcoltype/dbalttype
+#define SQL_CA_SS_COLUMN_UTYPE (SQL_CA_SS_BASE+1) // dbcolutype/dbaltutype
+#define SQL_CA_SS_NUM_ORDERS (SQL_CA_SS_BASE+2) // dbnumorders
+#define SQL_CA_SS_COLUMN_ORDER (SQL_CA_SS_BASE+3) // dbordercol
+#define SQL_CA_SS_COLUMN_VARYLEN (SQL_CA_SS_BASE+4) // dbvarylen
+#define SQL_CA_SS_NUM_COMPUTES (SQL_CA_SS_BASE+5) // dbnumcompute
+#define SQL_CA_SS_COMPUTE_ID (SQL_CA_SS_BASE+6) // dbnextrow status return
+#define SQL_CA_SS_COMPUTE_BYLIST (SQL_CA_SS_BASE+7) // dbbylist
+#define SQL_CA_SS_COLUMN_ID (SQL_CA_SS_BASE+8) // dbaltcolid
+#define SQL_CA_SS_COLUMN_OP (SQL_CA_SS_BASE+9) // dbaltop
+#define SQL_CA_SS_COLUMN_SIZE (SQL_CA_SS_BASE+10) // dbcollen
+#define SQL_CA_SS_COLUMN_HIDDEN (SQL_CA_SS_BASE+11) // Column is hidden (FOR BROWSE)
+#define SQL_CA_SS_COLUMN_KEY (SQL_CA_SS_BASE+12) // Column is key column (FOR BROWSE)
+#define SQL_CA_SS_COLUMN_COLLATION (SQL_CA_SS_BASE+14) // Column collation (only for chars)
#define SQL_CA_SS_VARIANT_TYPE (SQL_CA_SS_BASE+15)
#define SQL_CA_SS_VARIANT_SQL_TYPE (SQL_CA_SS_BASE+16)
#define SQL_CA_SS_VARIANT_SERVER_TYPE (SQL_CA_SS_BASE+17)
-/* XML, CLR UDT, and table valued parameter related metadata */
-#define SQL_CA_SS_UDT_CATALOG_NAME (SQL_CA_SS_BASE+18) /* UDT catalog name */
-#define SQL_CA_SS_UDT_SCHEMA_NAME (SQL_CA_SS_BASE+19) /* UDT schema name */
-#define SQL_CA_SS_UDT_TYPE_NAME (SQL_CA_SS_BASE+20) /* UDT type name */
-#define SQL_CA_SS_XML_SCHEMACOLLECTION_CATALOG_NAME (SQL_CA_SS_BASE+22) /* Name of the catalog that contains XML Schema collection */
-#define SQL_CA_SS_XML_SCHEMACOLLECTION_SCHEMA_NAME (SQL_CA_SS_BASE+23) /* Name of the schema that contains XML Schema collection */
-#define SQL_CA_SS_XML_SCHEMACOLLECTION_NAME (SQL_CA_SS_BASE+24) /* Name of the XML Schema collection */
-#define SQL_CA_SS_CATALOG_NAME (SQL_CA_SS_BASE+25) /* Catalog name */
-#define SQL_CA_SS_SCHEMA_NAME (SQL_CA_SS_BASE+26) /* Schema name */
-#define SQL_CA_SS_TYPE_NAME (SQL_CA_SS_BASE+27) /* Type name */
+// XML, CLR UDT, and table valued parameter related metadata
+#define SQL_CA_SS_UDT_CATALOG_NAME (SQL_CA_SS_BASE+18) // UDT catalog name
+#define SQL_CA_SS_UDT_SCHEMA_NAME (SQL_CA_SS_BASE+19) // UDT schema name
+#define SQL_CA_SS_UDT_TYPE_NAME (SQL_CA_SS_BASE+20) // UDT type name
+#define SQL_CA_SS_XML_SCHEMACOLLECTION_CATALOG_NAME (SQL_CA_SS_BASE+22) // Name of the catalog that contains XML Schema collection
+#define SQL_CA_SS_XML_SCHEMACOLLECTION_SCHEMA_NAME (SQL_CA_SS_BASE+23) // Name of the schema that contains XML Schema collection
+#define SQL_CA_SS_XML_SCHEMACOLLECTION_NAME (SQL_CA_SS_BASE+24) // Name of the XML Schema collection
+#define SQL_CA_SS_CATALOG_NAME (SQL_CA_SS_BASE+25) // Catalog name
+#define SQL_CA_SS_SCHEMA_NAME (SQL_CA_SS_BASE+26) // Schema name
+#define SQL_CA_SS_TYPE_NAME (SQL_CA_SS_BASE+27) // Type name
-/* table valued parameter related metadata */
-#define SQL_CA_SS_COLUMN_COMPUTED (SQL_CA_SS_BASE+29) /* column is computed */
-#define SQL_CA_SS_COLUMN_IN_UNIQUE_KEY (SQL_CA_SS_BASE+30) /* column is part of a unique key */
-#define SQL_CA_SS_COLUMN_SORT_ORDER (SQL_CA_SS_BASE+31) /* column sort order */
-#define SQL_CA_SS_COLUMN_SORT_ORDINAL (SQL_CA_SS_BASE+32) /* column sort ordinal */
-#define SQL_CA_SS_COLUMN_HAS_DEFAULT_VALUE (SQL_CA_SS_BASE+33) /* column has default value for all rows of the table valued parameter */
+// table valued parameter related metadata
+#define SQL_CA_SS_COLUMN_COMPUTED (SQL_CA_SS_BASE+29) // column is computed
+#define SQL_CA_SS_COLUMN_IN_UNIQUE_KEY (SQL_CA_SS_BASE+30) // column is part of a unique key
+#define SQL_CA_SS_COLUMN_SORT_ORDER (SQL_CA_SS_BASE+31) // column sort order
+#define SQL_CA_SS_COLUMN_SORT_ORDINAL (SQL_CA_SS_BASE+32) // column sort ordinal
+#define SQL_CA_SS_COLUMN_HAS_DEFAULT_VALUE (SQL_CA_SS_BASE+33) // column has default value for all rows of the table valued parameter
-/* sparse column related metadata */
-#define SQL_CA_SS_IS_COLUMN_SET (SQL_CA_SS_BASE+34) /* column is a column-set column for sparse columns */
+// sparse column related metadata
+#define SQL_CA_SS_IS_COLUMN_SET (SQL_CA_SS_BASE+34) // column is a column-set column for sparse columns
-/* Legacy datetime related metadata */
-#define SQL_CA_SS_SERVER_TYPE (SQL_CA_SS_BASE+35) /* column type to send on the wire for datetime types */
+// Legacy datetime related metadata
+#define SQL_CA_SS_SERVER_TYPE (SQL_CA_SS_BASE+35) // column type to send on the wire for datetime types
-/* force column encryption */
-#define SQL_CA_SS_FORCE_ENCRYPT (SQL_CA_SS_BASE+36) /* indicate mandatory encryption for this parameter */
+// force column encryption
+#define SQL_CA_SS_FORCE_ENCRYPT (SQL_CA_SS_BASE+36) // indicate mandatory encryption for this parameter
-/* Defines for use with SQL_COPT_SS_INTEGRATED_SECURITY - Pre-Connect Option only */
-#define SQL_IS_OFF 0L /* Integrated security isn't used */
-#define SQL_IS_ON 1L /* Integrated security is used */
+#define SQL_CA_SS_MAX_USED (SQL_CA_SS_BASE+37)
+// Defines for use with SQL_COPT_SS_INTEGRATED_SECURITY - Pre-Connect Option only
+#define SQL_IS_OFF 0L // Integrated security isn't used
+#define SQL_IS_ON 1L // Integrated security is used
#define SQL_IS_DEFAULT SQL_IS_OFF
-/* Defines for use with SQL_COPT_SS_TRANSLATE */
-#define SQL_XL_OFF 0L /* Code page translation is not performed */
-#define SQL_XL_ON 1L /* Code page translation is performed */
+// Defines for use with SQL_COPT_SS_TRANSLATE
+#define SQL_XL_OFF 0L // Code page translation is not performed
+#define SQL_XL_ON 1L // Code page translation is performed
#define SQL_XL_DEFAULT SQL_XL_ON
-/* Defines for use with SQL_SOPT_SS_TEXTPTR_LOGGING */
-#define SQL_TL_OFF 0L /* No logging on text pointer ops */
-#define SQL_TL_ON 1L /* Logging occurs on text pointer ops */
+// Defines for use with SQL_SOPT_SS_TEXTPTR_LOGGING
+#define SQL_TL_OFF 0L // No logging on text pointer ops
+#define SQL_TL_ON 1L // Logging occurs on text pointer ops
#define SQL_TL_DEFAULT SQL_TL_ON
-/* Defines for use with SQL_SOPT_SS_NOBROWSETABLE */
-#define SQL_NB_OFF 0L /* NO_BROWSETABLE is off */
-#define SQL_NB_ON 1L /* NO_BROWSETABLE is on */
+// Defines for use with SQL_SOPT_SS_NOBROWSETABLE
+#define SQL_NB_OFF 0L // NO_BROWSETABLE is off
+#define SQL_NB_ON 1L // NO_BROWSETABLE is on
#define SQL_NB_DEFAULT SQL_NB_OFF
-/* Defines for use with SQL_SOPT_SS_COLUMN_ENCRYPTION */
-#define SQL_CE_DISABLED 0L /* Disabled */
-#define SQL_CE_RESULTSETONLY 1L /* Decryption Only (resultsets and return values) */
-#define SQL_CE_ENABLED 3L /* Enabled (both encryption and decryption) */
-
-/* SQL_COPT_SS_ENCRYPT */
+// Defines for use with SQL_SOPT_SS_COLUMN_ENCRYPTION
+#define SQL_CE_DISABLED 0L // Disabled
+#define SQL_CE_RESULTSETONLY 1L // Decryption Only (resultsets and return values)
+#define SQL_CE_ENABLED 3L // Enabled (both encryption and decryption)
+ // Defines for use with SQL_COPT_SS_COLUMN_ENCRYPTION
+#define SQL_COLUMN_ENCRYPTION_DISABLE 0L
+#define SQL_COLUMN_ENCRYPTION_ENABLE 1L
+#define SQL_COLUMN_ENCRYPTION_DEFAULT SQL_COLUMN_ENCRYPTION_DISABLE
+ // Defines for use with SQL_COPT_SS_CEKCACHETTL
+#define SQL_CEKCACHETTL_DEFAULT 7200L // TTL value in seconds (2 hours)
+// SQL_COPT_SS_ENCRYPT
#define SQL_EN_OFF 0L
#define SQL_EN_ON 1L
-/* SQL_COPT_SS_TRUST_SERVER_CERTIFICATE */
+// SQL_COPT_SS_TRUST_SERVER_CERTIFICATE
#define SQL_TRUST_SERVER_CERTIFICATE_NO 0L
#define SQL_TRUST_SERVER_CERTIFICATE_YES 1L
-/* SQL_COPT_SS_WARN_ON_CP_ERROR */
+// SQL_COPT_SS_WARN_ON_CP_ERROR
#define SQL_WARN_NO 0L
#define SQL_WARN_YES 1L
-/* SQL_COPT_SS_MARS_ENABLED */
+// SQL_COPT_SS_MARS_ENABLED
#define SQL_MARS_ENABLED_NO 0L
#define SQL_MARS_ENABLED_YES 1L
-/* SQL_TXN_ISOLATION_OPTION bitmasks */
+// SQL_TXN_ISOLATION_OPTION bitmasks
#define SQL_TXN_SS_SNAPSHOT 0x00000020L
-/* SQL_COPT_SS_COLUMN_ENCRYPTION */
-#define SQL_COLUMN_ENCRYPTION_DISABLE 0L
-#define SQL_COLUMN_ENCRYPTION_ENABLE 1L
-#define SQL_COLUMN_ENCRYPTION_DEFAULT SQL_COLUMN_ENCRYPTION_DISABLE
-// Defines for use with SQL_COPT_SS_AECEKCACHETTL
-#define SQL_AECEKCACHETTL_DEFAULT 7200L // TTL value in seconds (2 hours)
-/* The following are defines for SQL_CA_SS_COLUMN_SORT_ORDER */
+// The following are defines for SQL_CA_SS_COLUMN_SORT_ORDER
#define SQL_SS_ORDER_UNSPECIFIED 0L
#define SQL_SS_DESCENDING_ORDER 1L
#define SQL_SS_ASCENDING_ORDER 2L
#define SQL_SS_ORDER_DEFAULT SQL_SS_ORDER_UNSPECIFIED
-/*
- * Driver specific SQL data type defines.
- * Microsoft has -150 thru -199 reserved for Microsoft ODBC Driver for SQL Server usage.
- */
+// Driver specific SQL data type defines.
+// Microsoft has -150 thru -199 reserved for Microsoft ODBC Driver for SQL Server usage.
+
#define SQL_SS_VARIANT (-150)
#define SQL_SS_UDT (-151)
#define SQL_SS_XML (-152)
@@ -203,24 +201,22 @@
#define SQL_SS_TIME2 (-154)
#define SQL_SS_TIMESTAMPOFFSET (-155)
-/* Local types to be used with SQL_CA_SS_SERVER_TYPE */
+// Local types to be used with SQL_CA_SS_SERVER_TYPE
#define SQL_SS_TYPE_DEFAULT 0L
#define SQL_SS_TYPE_SMALLDATETIME 1L
#define SQL_SS_TYPE_DATETIME 2L
-/* Extended C Types range 4000 and above. Range of -100 thru 200 is reserved by Driver Manager. */
+// Extended C Types range 4000 and above. Range of -100 thru 200 is reserved by Driver Manager.
#define SQL_C_TYPES_EXTENDED 0x04000L
-/*
- * SQL_SS_LENGTH_UNLIMITED is used to describe the max length of
- * VARCHAR(max), VARBINARY(max), NVARCHAR(max), and XML columns
- */
+// SQL_SS_LENGTH_UNLIMITED is used to describe the max length of
+// VARCHAR(max), VARBINARY(max), NVARCHAR(max), and XML columns
+
#define SQL_SS_LENGTH_UNLIMITED 0
-/*
- * User Data Type definitions.
- * Returned by SQLColAttributes/SQL_CA_SS_COLUMN_UTYPE.
- */
+// User Data Type definitions.
+// Returned by SQLColAttributes/SQL_CA_SS_COLUMN_UTYPE.
+
#define SQLudtBINARY 3
#define SQLudtBIT 16
#define SQLudtBITN 0
@@ -250,35 +246,35 @@
#define SQLudtVARBINARY 4
#define SQLudtVARCHAR 2
#define MIN_USER_DATATYPE 256
-/*
- * Aggregate operator types.
- * Returned by SQLColAttributes/SQL_CA_SS_COLUMN_OP.
- */
-#define SQLAOPSTDEV 0x30 /* Standard deviation */
-#define SQLAOPSTDEVP 0x31 /* Standard deviation population */
-#define SQLAOPVAR 0x32 /* Variance */
-#define SQLAOPVARP 0x33 /* Variance population */
-#define SQLAOPCNT 0x4b /* Count */
-#define SQLAOPSUM 0x4d /* Sum */
-#define SQLAOPAVG 0x4f /* Average */
-#define SQLAOPMIN 0x51 /* Min */
-#define SQLAOPMAX 0x52 /* Max */
-#define SQLAOPANY 0x53 /* Any */
-#define SQLAOPNOOP 0x56 /* None */
-/*
- * SQLGetDiagField driver specific defines.
- * Microsoft has -1150 thru -1199 reserved for Microsoft ODBC Driver for SQL Server usage.
- */
+
+// Aggregate operator types.
+// Returned by SQLColAttributes/SQL_CA_SS_COLUMN_OP.
+
+#define SQLAOPSTDEV 0x30 // Standard deviation
+#define SQLAOPSTDEVP 0x31 // Standard deviation population
+#define SQLAOPVAR 0x32 // Variance
+#define SQLAOPVARP 0x33 // Variance population
+#define SQLAOPCNT 0x4b // Count
+#define SQLAOPSUM 0x4d // Sum
+#define SQLAOPAVG 0x4f // Average
+#define SQLAOPMIN 0x51 // Min
+#define SQLAOPMAX 0x52 // Max
+#define SQLAOPANY 0x53 // Any
+#define SQLAOPNOOP 0x56 // None
+
+// SQLGetDiagField driver specific defines.
+// Microsoft has -1150 thru -1199 reserved for Microsoft ODBC Driver for SQL Server usage.
+
#define SQL_DIAG_SS_BASE (-1150)
#define SQL_DIAG_SS_MSGSTATE (SQL_DIAG_SS_BASE)
#define SQL_DIAG_SS_SEVERITY (SQL_DIAG_SS_BASE-1)
#define SQL_DIAG_SS_SRVNAME (SQL_DIAG_SS_BASE-2)
#define SQL_DIAG_SS_PROCNAME (SQL_DIAG_SS_BASE-3)
#define SQL_DIAG_SS_LINE (SQL_DIAG_SS_BASE-4)
-/*
- * SQLGetDiagField/SQL_DIAG_DYNAMIC_FUNCTION_CODE driver specific defines.
- * Microsoft has -200 thru -299 reserved for Microsoft ODBC Driver for SQL Server usage.
- */
+
+// SQLGetDiagField/SQL_DIAG_DYNAMIC_FUNCTION_CODE driver specific defines.
+// Microsoft has -200 thru -299 reserved for Microsoft ODBC Driver for SQL Server usage.
+
#define SQL_DIAG_DFC_SS_BASE (-200)
#define SQL_DIAG_DFC_SS_ALTER_DATABASE (SQL_DIAG_DFC_SS_BASE-0)
#define SQL_DIAG_DFC_SS_CHECKPOINT (SQL_DIAG_DFC_SS_BASE-1)
@@ -343,7 +339,7 @@
#define SQL_DIAG_DFC_SS_SET_XCTLVL (SQL_DIAG_DFC_SS_BASE-55)
#define SQL_DIAG_DFC_SS_MERGE (SQL_DIAG_DFC_SS_BASE-56)
-/* Severity codes for SQL_DIAG_SS_SEVERITY */
+// Severity codes for SQL_DIAG_SS_SEVERITY
#define EX_ANY 0
#define EX_INFO 10
#define EX_MAXISEVERITY EX_INFO
@@ -365,64 +361,45 @@
#define EX_HARDWARE 24
#define EX_CONTROL 25
-/* Keystore Provider interface definition */
+// Data is defined to be past the end of the structure header.
+// This is accepted by MSVC, GCC, and C99 standard but former emits
+// unnecessary warning, hence it has to be disabled.
-typedef void errFunc(void *ctx, const wchar_t *msg, ...);
-
-#define IDS_MSG(x) ((const wchar_t*)(x))
-
-typedef struct AEKeystoreProvider
-{
- wchar_t *Name;
- int (*Init)(void *ctx, errFunc *onError);
- int (*Read)(void *ctx, errFunc *onError, void *data, unsigned int *len);
- int (*Write)(void *ctx, errFunc *onError, void *data, unsigned int len);
- int (*DecryptCEK)(
- void *ctx,
- errFunc *onError,
- const wchar_t *keyPath,
- const wchar_t *alg,
- unsigned char *ecek,
- unsigned short ecek_len,
- unsigned char **cek_out,
- unsigned short *cek_len);
- void (*Free)();
-} AEKEYSTOREPROVIDER;
-
-/* Data is defined to be past the end of the structure header.
- This is accepted by MSVC, GCC, and C99 standard but former emits
- unnecessary warning, hence it has to be disabled.
-*/
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4200)
#endif
-typedef struct AEKeystoreData
+// Communication between the driver and application via the CEKeystoreData structure
+typedef struct CEKeystoreData
{
- wchar_t *Name;
+ wchar_t *name;
unsigned int dataSize;
- char Data[];
-} AEKEYSTOREPROVIDERDATA;
+ char data[];
+} CEKEYSTOREDATA;
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
-/* The following constants are for the Azure Key Vault configuration interface */
-#define AKV_CONFIG_FLAGS 0
-#define AKVCFG_USECLIENTID 0x00000001
-#define AKVCFG_AUTORENEW 0x00000002
-
-#define AKV_CONFIG_CLIENTID 1
-#define AKV_CONFIG_CLIENTKEY 2
-
-#define AKV_CONFIG_ACCESSTOKEN 3
-#define AKV_CONFIG_TOKENEXPIRY 4
+// The following constants are for the Azure Key Vault configuration interface
+#define AKV_CONFIG_FLAGS 0
+#define AKVCFG_AUTHMODE 0x0000000F
+#define AKVCFG_AUTHMODE_ACCESSTOKEN 0
+#define AKVCFG_AUTHMODE_CLIENTKEY 1
+#define AKVCFG_AUTHMODE_PASSWORD 2
+#define AKVCFG_AUTHMODE_INTEGRATED 3
+#define AKVCFG_AUTHMODE_CERTIFICATE 4
+#define AKVCFG_NOAUTORENEW 0x00000010
+#define AKV_CONFIG_PRINCIPALID 1
+#define AKV_CONFIG_AUTHSECRET 2
+#define AKV_CONFIG_ACCESSTOKEN 3
+#define AKV_CONFIG_TOKENEXPIRY 4
#define AKV_CONFIG_MAXRETRIES 5
#define AKV_CONFIG_RETRYTIMEOUT 6
#define AKV_CONFIG_RETRYWAIT 7
-#endif /* __msodbcsql_h__ */
+#define AKV_CONFIG_RESET 255
+#endif // __msodbcsql_h__
diff --git a/source/shared/sal_def.h b/source/shared/sal_def.h
index 74725c34..910ec960 100644
--- a/source/shared/sal_def.h
+++ b/source/shared/sal_def.h
@@ -3,7 +3,7 @@
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/typedefs_for_linux.h b/source/shared/typedefs_for_linux.h
index cc6f4f68..9906c9d3 100644
--- a/source/shared/typedefs_for_linux.h
+++ b/source/shared/typedefs_for_linux.h
@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: typedefs_for_linux.h
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/version.h b/source/shared/version.h
index 1a0a3b64..90b323cb 100644
--- a/source/shared/version.h
+++ b/source/shared/version.h
@@ -4,7 +4,7 @@
// File: version.h
// Contents: Version number constants
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@@ -22,14 +22,21 @@
#define STRINGIFY(a) TOSTRING(a)
#define TOSTRING(a) #a
+
+// Increase Major number with backward incompatible breaking changes.
+// Increase Minor with backward compatible new functionalities and API changes.
+// Increase Patch for backward compatible fixes.
#define SQLVERSION_MAJOR 4
-#define SQLVERSION_MINOR 2
+#define SQLVERSION_MINOR 3
#define SQLVERSION_PATCH 0
#define SQLVERSION_BUILD 0
-// Semantic versioning pre-release, for stable releases should be empty
-#define SEMVER_PRERELEASE "preview"
-// Semantic versioning build metadata
+// Semantic versioning pre-release
+// for stable releases should be empty
+// "rc" for release candidates
+// "preview" for ETP
+#define SEMVER_PRERELEASE "RC1"
+// Semantic versioning build metadata, build meta data is not counted in precedence order.
#define SEMVER_BUILDMETA
#if SQLVERSION_BUILD > 0
@@ -37,7 +44,7 @@
#define SEMVER_BUILDMETA "+" STRINGIFY( SQLVERSION_BUILD )
#endif
-// Main version
+// Main version, dot separated 3 digits, Major.Minor.Patch
#define VER_APIVERSION_STR STRINGIFY( SQLVERSION_MAJOR ) "." STRINGIFY( SQLVERSION_MINOR ) "." STRINGIFY( SQLVERSION_PATCH )
// Remove "-" if SEMVER_PRERELEASE is empty (for stable releases)
diff --git a/source/shared/xplat.h b/source/shared/xplat.h
index 2606e40f..b29689c5 100644
--- a/source/shared/xplat.h
+++ b/source/shared/xplat.h
@@ -3,7 +3,7 @@
//
// Contents: include for definition of Windows types for non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/xplat_intsafe.h b/source/shared/xplat_intsafe.h
index df7801a3..1fd43551 100644
--- a/source/shared/xplat_intsafe.h
+++ b/source/shared/xplat_intsafe.h
@@ -4,7 +4,7 @@
// Contents: This module defines helper functions to prevent
// integer overflow bugs.
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/xplat_winerror.h b/source/shared/xplat_winerror.h
index 4734d710..f3f0878b 100644
--- a/source/shared/xplat_winerror.h
+++ b/source/shared/xplat_winerror.h
@@ -3,7 +3,7 @@
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/shared/xplat_winnls.h b/source/shared/xplat_winnls.h
index f324a15f..a91dd554 100644
--- a/source/shared/xplat_winnls.h
+++ b/source/shared/xplat_winnls.h
@@ -3,7 +3,7 @@
//
// Contents: Contains the minimal definitions to build on non-Windows platforms
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/sqlsrv/config.m4 b/source/sqlsrv/config.m4
index 255470d4..ebf62d7f 100644
--- a/source/sqlsrv/config.m4
+++ b/source/sqlsrv/config.m4
@@ -40,3 +40,8 @@ if test "$PHP_SQLSRV" != "no"; then
PHP_NEW_EXTENSION(sqlsrv, $sqlsrv_src_class $shared_src_class, $ext_shared,,-std=c++11)
PHP_ADD_BUILD_DIR([$ext_builddir/shared], 1)
fi
+
+#if (defined __APPLE__ && defined __MACH__) \
+ MACOSX_DEPLOYMENT_TARGET=`sw_vers -productVersion` \
+#endif
+
diff --git a/source/sqlsrv/config.w32 b/source/sqlsrv/config.w32
index 5560da4e..82e306f5 100644
--- a/source/sqlsrv/config.w32
+++ b/source/sqlsrv/config.w32
@@ -3,7 +3,7 @@
//
// Contents: JScript build configuration used by buildconf.bat
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/sqlsrv/conn.cpp b/source/sqlsrv/conn.cpp
index b23761b4..8a9d6da6 100644
--- a/source/sqlsrv/conn.cpp
+++ b/source/sqlsrv/conn.cpp
@@ -3,7 +3,7 @@
//
// Contents: Routines that use connection handles
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@@ -205,6 +205,7 @@ const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
const char TrustServerCertificate[] = "TrustServerCertificate";
const char TransactionIsolation[] = "TransactionIsolation";
+const char TransparentNetworkIPResolution[] = "TransparentNetworkIPResolution";
const char UID[] = "UID";
const char WSID[] = "WSID";
@@ -420,6 +421,15 @@ const connection_option SS_CONN_OPTS[] = {
CONN_ATTR_BOOL,
bool_conn_str_func::func
},
+ {
+ SSConnOptionNames::TransparentNetworkIPResolution,
+ sizeof(SSConnOptionNames::TransparentNetworkIPResolution),
+ SQLSRV_CONN_OPTION_TRANSPARANT_NETWORK_IP_RESOLUTION,
+ ODBCConnOptions::TransparentNetworkIPResolution,
+ sizeof(ODBCConnOptions::TransparentNetworkIPResolution),
+ CONN_ATTR_STRING,
+ conn_str_append_func::func
+ },
{
SSConnOptionNames::WSID,
sizeof( SSConnOptionNames::WSID ),
@@ -658,7 +668,11 @@ PHP_FUNCTION( sqlsrv_close )
if( zend_list_close( Z_RES_P( conn_r ) ) == FAILURE ) {
LOG( SEV_ERROR, "Failed to remove connection resource %1!d!", Z_RES_HANDLE_P( conn_r ));
}
-
+
+ // when conn_r is first parsed in zend_parse_parameters, conn_r becomes a zval that points to a zend_resource with a refcount of 2
+ // need to DELREF here so the refcount becomes 1 and conn_r can be appropriate destroyed by the garbage collector when it goes out of scope
+ // zend_list_close only destroy the resource pointed to by Z_RES_P( conn_r ), not the zend_resource itself
+ Z_TRY_DELREF_P(conn_r);
ZVAL_NULL( conn_r );
RETURN_TRUE;
diff --git a/source/sqlsrv/init.cpp b/source/sqlsrv/init.cpp
index d87b1a4b..84cc153a 100644
--- a/source/sqlsrv/init.cpp
+++ b/source/sqlsrv/init.cpp
@@ -2,7 +2,7 @@
// File: init.cpp
// Contents: initialization routines for the extension
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/sqlsrv/php_sqlsrv.h b/source/sqlsrv/php_sqlsrv.h
index ed31aaea..988254f4 100644
--- a/source/sqlsrv/php_sqlsrv.h
+++ b/source/sqlsrv/php_sqlsrv.h
@@ -8,7 +8,7 @@
//
// Comments: Also contains "internal" declarations shared across source files.
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/sqlsrv/stmt.cpp b/source/sqlsrv/stmt.cpp
index 2c87ef9c..c08b4570 100644
--- a/source/sqlsrv/stmt.cpp
+++ b/source/sqlsrv/stmt.cpp
@@ -3,7 +3,7 @@
//
// Contents: Routines that use statement handles
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@@ -1376,6 +1376,10 @@ PHP_FUNCTION( sqlsrv_free_stmt )
LOG( SEV_ERROR, "Failed to remove stmt resource %1!d!", Z_RES_P( stmt_r )->handle);
}
+ // when stmt_r is first parsed in zend_parse_parameters, stmt_r becomes a zval that points to a zend_resource with a refcount of 2
+ // need to DELREF here so the refcount becomes 1 and stmt_r can be appropriate destroyed by the garbage collector when it goes out of scope
+ // zend_list_close only destroy the resource pointed to by Z_RES_P( stmt_r ), not the zend_resource itself
+ Z_TRY_DELREF_P(stmt_r);
ZVAL_NULL( stmt_r );
RETURN_TRUE;
diff --git a/source/sqlsrv/template.rc b/source/sqlsrv/template.rc
index 1ea88b29..5502389a 100644
--- a/source/sqlsrv/template.rc
+++ b/source/sqlsrv/template.rc
@@ -3,7 +3,7 @@
//
// Contents: Version resource
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
diff --git a/source/sqlsrv/util.cpp b/source/sqlsrv/util.cpp
index 26d1f68d..352e5c24 100644
--- a/source/sqlsrv/util.cpp
+++ b/source/sqlsrv/util.cpp
@@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
-// Microsoft Drivers 4.2 for PHP for SQL Server
+// Microsoft Drivers 4.3 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@@ -684,8 +684,6 @@ PHP_FUNCTION( sqlsrv_get_config )
namespace {
-// Workaround for name collision problem between the SQLSRV and PDO_SQLSRV drivers on Mac
-// Place get_error_message into the anonymous namespace in util.cpp
sqlsrv_error_const* get_error_message( unsigned int sqlsrv_error_code ) {
sqlsrv_error_const *error_message = NULL;
diff --git a/test/bvt/pdo_sqlsrv/break.inc b/test/bvt/pdo_sqlsrv/break.inc
new file mode 100644
index 00000000..0540dac8
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/break.inc
@@ -0,0 +1,60 @@
+
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/break_pdo.php b/test/bvt/pdo_sqlsrv/break_pdo.php
new file mode 100644
index 00000000..6082387f
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/break_pdo.php
@@ -0,0 +1,82 @@
+query( $sql );
+
+ // Insert data
+ $sql = "INSERT INTO $tableName1 VALUES ( ?, ? )";
+ for( $t = 100; $t < 116; $t++ )
+ {
+ $stmt = $conn->prepare( $sql );
+ $ts = substr( sha1( $t ),0,5 );
+ $params = array( $t,$ts );
+ $stmt->execute( $params );
+ }
+
+ // Create table
+ $sql = "CREATE TABLE $tableName2 ( c1 INT, c2 VARCHAR(40) )";
+ $stmt = $conn->query( $sql );
+
+ // Insert data
+ $sql = "INSERT INTO $tableName2 VALUES ( ?, ? )";
+ for( $t = 200; $t < 209; $t++ )
+ {
+ $stmt = $conn->prepare( $sql );
+ $ts = substr( sha1( $t ),0,5 );
+ $params = array( $t,$ts );
+ $stmt->execute( $params );
+ }
+
+ $conn = null;
+}
+
+// Break connection by getting the session ID and killing it.
+// Note that breaking a connection and testing reconnection requires a
+// TCP/IP protocol connection (as opposed to a Shared Memory protocol).
+function BreakConnection( $conn, $conn_break )
+{
+ $stmt1 = $conn->query( "SELECT @@SPID" );
+ $obj = $stmt1->fetch( PDO::FETCH_NUM );
+ $spid = $obj[0];
+
+ $stmt2 = $conn_break->query( "KILL ".$spid );
+ sleep(1);
+}
+
+// Remove any databases previously created by GenerateDatabase
+function DropTables( $server, $uid, $pwd, $tableName1, $tableName2 )
+{
+ $conn = new PDO( "sqlsrv:server = $server ; ", $uid, $pwd );
+
+ $query="IF OBJECT_ID('tempdb.dbo.$tableName1', 'U') IS NOT NULL DROP TABLE tempdb.dbo.$tableName1";
+ $stmt=$conn->query( $query );
+
+ $query="IF OBJECT_ID('tempdb.dbo.$tableName2', 'U') IS NOT NULL DROP TABLE tempdb.dbo.$tableName2";
+ $stmt=$conn->query( $query );
+}
+
+DropTables( $server, $uid, $pwd, $tableName1, $tableName2 );
+GenerateTables( $server, $uid, $pwd, $dbName, $tableName1, $tableName2 );
+
+?>
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/connect.inc b/test/bvt/pdo_sqlsrv/connect.inc
new file mode 100644
index 00000000..a6bd479f
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/connect.inc
@@ -0,0 +1,8 @@
+
+
+
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindColumn.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindColumn.phpt
new file mode 100644
index 00000000..3904d76e
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindColumn.phpt
@@ -0,0 +1,24 @@
+--TEST--
+a variable bound to a column in a result set
+--SKIPIF--
+
+--FILE--
+prepare($query);
+$stmt->execute();
+
+$stmt->bindColumn('EmailPromotion', $emailpromo);
+while ( $row = $stmt->fetch( PDO::FETCH_BOUND ) ){
+ echo "EmailPromotion: $emailpromo\n";
+}
+
+//free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+EmailPromotion: 2
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam.phpt
new file mode 100644
index 00000000..11f22687
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam.phpt
@@ -0,0 +1,38 @@
+--TEST--
+after a variable is bound, changing the value changes the value passed in the query
+--SKIPIF--
+
+--FILE--
+prepare("select * from Person.ContactType where name = ?");
+$stmt->bindParam(1, $contact);
+$contact = "Owner";
+$stmt->execute();
+
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print "Result: "."$row[Name]\n\n";
+}
+
+$stmt = null;
+$contact = "Sales Agent";
+$stmt = $conn->prepare("select * from Person.ContactType where name = :contact");
+$stmt->bindParam(':contact', $contact);
+$contact = "Owner";
+$stmt->execute();
+
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print "Result: "."$row[Name]\n\n";
+}
+
+//free the statement and connection
+$stmt = null;
+$conn = null;
+?>
+--EXPECT--
+Result: Owner
+
+Result: Owner
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam_2.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam_2.phpt
new file mode 100644
index 00000000..f514821e
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam_2.phpt
@@ -0,0 +1,22 @@
+--TEST--
+accesses an output parameter
+--SKIPIF--
+
+--FILE--
+prepare("select ? = count(* ) from Person.Person");
+$stmt->bindParam( 1, $input1, PDO::PARAM_STR, 10);
+$stmt->execute();
+echo "Result: ".$input1;
+
+//free the statement and connection
+$conn = null;
+$stmt = null;
+?>
+--EXPECT--
+Result: 19972
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam_3.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam_3.phpt
new file mode 100644
index 00000000..d211c29b
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindParam_3.phpt
@@ -0,0 +1,23 @@
+--TEST--
+uses an input/output parameter
+--SKIPIF--
+
+--FILE--
+query("IF OBJECT_ID('dbo.sp_ReverseString', 'P') IS NOT NULL DROP PROCEDURE dbo.sp_ReverseString");
+ $dbh->query("CREATE PROCEDURE dbo.sp_ReverseString @String as VARCHAR(2048) OUTPUT as SELECT @String = REVERSE(@String)");
+ $stmt = $dbh->prepare("EXEC dbo.sp_ReverseString ?");
+ $string = "123456789";
+ $stmt->bindParam(1, $string, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 2048);
+ $stmt->execute();
+ print "Result: ".$string; // Expect 987654321
+
+ //free the statement and connection
+ $stmt = null;
+ $dbh = null;
+?>
+--EXPECT--
+Result: 987654321
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindValue.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindValue.phpt
new file mode 100644
index 00000000..07e70b0e
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_bindValue.phpt
@@ -0,0 +1,38 @@
+--TEST--
+after a value $contact is bound, changing the value does not change the value passed in the query
+--SKIPIF--
+
+--FILE--
+prepare("select * from Person.ContactType where name = ?");
+$stmt->bindValue(1, $contact);
+$contact = "Owner";
+$stmt->execute();
+
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print "Name: $row[Name]\n\n";
+}
+
+$stmt = null;
+$contact = "Sales Agent";
+$stmt = $conn->prepare("select * from Person.ContactType where name = :contact");
+$stmt->bindValue(':contact', $contact);
+$contact = "Owner";
+$stmt->execute();
+
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print "Name: $row[Name]\n\n";
+}
+
+//free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+Name: Sales Agent
+
+Name: Sales Agent
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_closeCursor.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_closeCursor.phpt
new file mode 100644
index 00000000..5cd8cd82
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_closeCursor.phpt
@@ -0,0 +1,50 @@
+--TEST--
+closes the cursor
+--SKIPIF--
+
+--FILE--
+ false ) );
+
+$stmt = $conn->prepare('SELECT * FROM Person.ContactType');
+
+$stmt2 = $conn->prepare('SELECT * FROM HumanResources.Department');
+
+$stmt->execute();
+
+$result = $stmt->fetch();
+print_r($result);
+
+$stmt->closeCursor();
+
+$stmt2->execute();
+$result = $stmt2->fetch();
+print_r($result);
+
+//free the statements and connection
+$stmt=null;
+$stmt2=null;
+$conn=null;
+?>
+--EXPECT--
+Array
+(
+ [ContactTypeID] => 1
+ [0] => 1
+ [Name] => Accounting Manager
+ [1] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [DepartmentID] => 1
+ [0] => 1
+ [Name] => Engineering
+ [1] => Engineering
+ [GroupName] => Research and Development
+ [2] => Research and Development
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [3] => 2008-04-30 00:00:00.000
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_columnCount.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_columnCount.phpt
new file mode 100644
index 00000000..ba3ca910
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_columnCount.phpt
@@ -0,0 +1,34 @@
+--TEST--
+returns the number of columns in a result set for 3 queries
+--SKIPIF--
+
+--FILE--
+prepare( $query );
+print $stmt->columnCount(); // 0
+echo " columns in the result set\n";
+
+echo "\n";
+$stmt->execute();
+print $stmt->columnCount();
+echo " columns in the result set\n";
+
+echo "\n";
+$stmt = $conn->query("select * from HumanResources.Department");
+print $stmt->columnCount();
+echo " columns in the result set\n";
+
+//free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+0 columns in the result set
+
+3 columns in the result set
+
+4 columns in the result set
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_debugDumpParams.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_debugDumpParams.phpt
new file mode 100644
index 00000000..55c0b8fa
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_debugDumpParams.phpt
@@ -0,0 +1,42 @@
+--TEST--
+displays a prepared statement
+--SKIPIF--
+
+--FILE--
+prepare("select * from Person.ContactType where name = :param");
+$stmt->execute(array($param));
+$stmt->debugDumpParams();
+
+echo "\n\n";
+
+$stmt = $conn->prepare("select * from Person.ContactType where name = ?");
+$stmt->execute(array($param));
+$stmt->debugDumpParams();
+
+//free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+SQL: [52] select * from Person.ContactType where name = :param
+Params: 1
+Key: Name: [6] :param
+paramno=0
+name=[6] ":param"
+is_param=1
+param_type=2
+
+
+SQL: [47] select * from Person.ContactType where name = ?
+Params: 1
+Key: Position #0:
+paramno=0
+name=[0] ""
+is_param=1
+param_type=2
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_errorCode.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_errorCode.phpt
new file mode 100644
index 00000000..2a3e7501
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_errorCode.phpt
@@ -0,0 +1,20 @@
+--TEST--
+shows the error code of a SQL query with a mispelled table
+--SKIPIF--
+
+--FILE--
+prepare('SELECT * FROM Person.Addressx');
+
+$stmt->execute();
+echo "Error Code: ";
+print $stmt->errorCode();
+
+// free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+Error Code: 42S02
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_errorInfo.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_errorInfo.phpt
new file mode 100644
index 00000000..6f8e4bc6
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_errorInfo.phpt
@@ -0,0 +1,24 @@
+--TEST--
+reports the error info of a SQL statement with a mispelled table name
+--SKIPIF--
+
+--FILE--
+prepare('SELECT * FROM Person.Addressx');
+
+$stmt->execute();
+print_r ($stmt->errorInfo());
+
+// free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECTREGEX--
+Array
+\(
+ \[0\] => 42S02
+ \[1\] => 208
+ \[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]Invalid object name 'Person.Addressx'.
+\)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_execute.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_execute.phpt
new file mode 100644
index 00000000..b43bd1c7
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_execute.phpt
@@ -0,0 +1,54 @@
+--TEST--
+Executes a statement
+--SKIPIF--
+
+--FILE--
+prepare( $query );
+$stmt->execute();
+
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print "$row[Name]\n";
+}
+
+echo "\n";
+$param = "Owner";
+$query = "select * from Person.ContactType where name = ?";
+$stmt = $conn->prepare( $query );
+$stmt->execute(array($param));
+
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print "$row[Name]\n";
+}
+
+// free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+Accounting Manager
+Assistant Sales Agent
+Assistant Sales Representative
+Coordinator Foreign Markets
+Export Administrator
+International Marketing Manager
+Marketing Assistant
+Marketing Manager
+Marketing Representative
+Order Administrator
+Owner
+Owner/Marketing Assistant
+Product Manager
+Purchasing Agent
+Purchasing Manager
+Regional Account Representative
+Sales Agent
+Sales Associate
+Sales Manager
+Sales Representative
+
+Owner
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetch.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetch.phpt
new file mode 100644
index 00000000..f8cc9190
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetch.phpt
@@ -0,0 +1,152 @@
+--TEST--
+fetch with all fetch styles
+--SKIPIF--
+
+--FILE--
+query( "select * from HumanResources.Department order by GroupName" );
+
+ class cc {
+ function __construct( $arg ) {
+ echo "$arg";
+ }
+
+ function __toString() {
+ return $this->DepartmentID . "; " . $this->Name . "; " . $this->GroupName;
+ }
+ }
+
+ $stmt->setFetchMode(PDO::FETCH_CLASS, 'cc', array( "arg1 " ));
+ while ( $row = $stmt->fetch(PDO::FETCH_CLASS)) {
+ print($row . "\n");
+ }
+
+ print( "\n---------- PDO::FETCH_INTO -------------\n" );
+ $stmt = $conn->query( "select * from HumanResources.Department order by GroupName" );
+ $c_obj = new cc( '' );
+
+ $stmt->setFetchMode(PDO::FETCH_INTO, $c_obj);
+ while ( $row = $stmt->fetch(PDO::FETCH_INTO)) {
+ echo "$c_obj\n";
+ }
+
+ print( "\n---------- PDO::FETCH_ASSOC -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetch( PDO::FETCH_ASSOC );
+ print_r( $result );
+
+ print( "\n---------- PDO::FETCH_NUM -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetch( PDO::FETCH_NUM );
+ print_r ($result );
+
+ print( "\n---------- PDO::FETCH_BOTH -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetch( PDO::FETCH_BOTH );
+ print_r( $result );
+
+ print( "\n---------- PDO::FETCH_LAZY -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetch( PDO::FETCH_LAZY );
+ print_r( $result );
+
+ print( "\n---------- PDO::FETCH_OBJ -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetch( PDO::FETCH_OBJ );
+ print $result->Name;
+ print( "\n \n" );
+
+ print( "\n---------- PDO::FETCH_BOUND -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $stmt->bindColumn('Name', $name);
+ $result = $stmt->fetch( PDO::FETCH_BOUND );
+ print $name;
+ print( "\n \n" );
+
+ //free the statement and connection
+ $stmt=null;
+ $conn=null;
+?>
+--EXPECT--
+---------- PDO::FETCH_CLASS -------------
+arg1 9; Human Resources; Executive General and Administration
+arg1 10; Finance; Executive General and Administration
+arg1 11; Information Services; Executive General and Administration
+arg1 14; Facilities and Maintenance; Executive General and Administration
+arg1 16; Executive; Executive General and Administration
+arg1 15; Shipping and Receiving; Inventory Management
+arg1 5; Purchasing; Inventory Management
+arg1 7; Production; Manufacturing
+arg1 8; Production Control; Manufacturing
+arg1 12; Document Control; Quality Assurance
+arg1 13; Quality Assurance; Quality Assurance
+arg1 6; Research and Development; Research and Development
+arg1 1; Engineering; Research and Development
+arg1 2; Tool Design; Research and Development
+arg1 3; Sales; Sales and Marketing
+arg1 4; Marketing; Sales and Marketing
+
+---------- PDO::FETCH_INTO -------------
+9; Human Resources; Executive General and Administration
+10; Finance; Executive General and Administration
+11; Information Services; Executive General and Administration
+14; Facilities and Maintenance; Executive General and Administration
+16; Executive; Executive General and Administration
+15; Shipping and Receiving; Inventory Management
+5; Purchasing; Inventory Management
+7; Production; Manufacturing
+8; Production Control; Manufacturing
+12; Document Control; Quality Assurance
+13; Quality Assurance; Quality Assurance
+6; Research and Development; Research and Development
+1; Engineering; Research and Development
+2; Tool Design; Research and Development
+3; Sales; Sales and Marketing
+4; Marketing; Sales and Marketing
+
+---------- PDO::FETCH_ASSOC -------------
+Array
+(
+ [ContactTypeID] => 1
+ [Name] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+
+---------- PDO::FETCH_NUM -------------
+Array
+(
+ [0] => 1
+ [1] => Accounting Manager
+ [2] => 2008-04-30 00:00:00.000
+)
+
+---------- PDO::FETCH_BOTH -------------
+Array
+(
+ [ContactTypeID] => 1
+ [0] => 1
+ [Name] => Accounting Manager
+ [1] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+)
+
+---------- PDO::FETCH_LAZY -------------
+PDORow Object
+(
+ [queryString] => select * from Person.ContactType where ContactTypeID < 5
+ [ContactTypeID] => 1
+ [Name] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+
+---------- PDO::FETCH_OBJ -------------
+Accounting Manager
+
+
+---------- PDO::FETCH_BOUND -------------
+Accounting Manager
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchAll.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchAll.phpt
new file mode 100644
index 00000000..1611942c
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchAll.phpt
@@ -0,0 +1,156 @@
+--TEST--
+fetches the rows in a result set in an array
+--SKIPIF--
+
+--FILE--
+query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetchAll(PDO::FETCH_BOTH);
+ print_r( $result );
+ print "\n-----------\n";
+
+ print "-----------\n";
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetchAll(PDO::FETCH_NUM);
+ print_r( $result );
+ print "\n-----------\n";
+
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetchAll(PDO::FETCH_COLUMN, 1);
+ print_r( $result );
+ print "\n-----------\n";
+
+ class cc {
+ function __construct( $arg ) {
+ echo "$arg\n";
+ }
+
+ function __toString() {
+ echo "To string\n";
+ }
+ };
+
+ $stmt = $conn->query( 'SELECT TOP(2) * FROM Person.ContactType' );
+ $all = $stmt->fetchAll( PDO::FETCH_CLASS, 'cc', array( 'Hi!' ));
+ var_dump( $all );
+
+ //free the statement and connection
+ $stmt=null;
+ $conn=null;
+?>
+--EXPECT--
+-----------
+Array
+(
+ [0] => Array
+ (
+ [ContactTypeID] => 1
+ [0] => 1
+ [Name] => Accounting Manager
+ [1] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+ )
+
+ [1] => Array
+ (
+ [ContactTypeID] => 2
+ [0] => 2
+ [Name] => Assistant Sales Agent
+ [1] => Assistant Sales Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+ )
+
+ [2] => Array
+ (
+ [ContactTypeID] => 3
+ [0] => 3
+ [Name] => Assistant Sales Representative
+ [1] => Assistant Sales Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+ )
+
+ [3] => Array
+ (
+ [ContactTypeID] => 4
+ [0] => 4
+ [Name] => Coordinator Foreign Markets
+ [1] => Coordinator Foreign Markets
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+ )
+
+)
+
+-----------
+-----------
+Array
+(
+ [0] => Array
+ (
+ [0] => 1
+ [1] => Accounting Manager
+ [2] => 2008-04-30 00:00:00.000
+ )
+
+ [1] => Array
+ (
+ [0] => 2
+ [1] => Assistant Sales Agent
+ [2] => 2008-04-30 00:00:00.000
+ )
+
+ [2] => Array
+ (
+ [0] => 3
+ [1] => Assistant Sales Representative
+ [2] => 2008-04-30 00:00:00.000
+ )
+
+ [3] => Array
+ (
+ [0] => 4
+ [1] => Coordinator Foreign Markets
+ [2] => 2008-04-30 00:00:00.000
+ )
+
+)
+
+-----------
+Array
+(
+ [0] => Accounting Manager
+ [1] => Assistant Sales Agent
+ [2] => Assistant Sales Representative
+ [3] => Coordinator Foreign Markets
+)
+
+-----------
+Hi!
+Hi!
+array(2) {
+ [0]=>
+ object(cc)#2 (3) {
+ ["ContactTypeID"]=>
+ string(1) "1"
+ ["Name"]=>
+ string(18) "Accounting Manager"
+ ["ModifiedDate"]=>
+ string(23) "2008-04-30 00:00:00.000"
+ }
+ [1]=>
+ object(cc)#4 (3) {
+ ["ContactTypeID"]=>
+ string(1) "2"
+ ["Name"]=>
+ string(21) "Assistant Sales Agent"
+ ["ModifiedDate"]=>
+ string(23) "2008-04-30 00:00:00.000"
+ }
+}
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchColumn.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchColumn.phpt
new file mode 100644
index 00000000..f2137200
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchColumn.phpt
@@ -0,0 +1,23 @@
+--TEST--
+fetches a column in a row
+--SKIPIF--
+
+--FILE--
+query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ while ( $result = $stmt->fetchColumn(1)) {
+ print($result . "\n");
+ }
+
+ //free the statement and connection
+ $stmt=null;
+ $conn=null;
+?>
+--EXPECT--
+Accounting Manager
+Assistant Sales Agent
+Assistant Sales Representative
+Coordinator Foreign Markets
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchObject.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchObject.phpt
new file mode 100644
index 00000000..93158bb4
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchObject.phpt
@@ -0,0 +1,19 @@
+--TEST--
+fetches the next row as an object
+--SKIPIF--
+
+--FILE--
+query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $result = $stmt->fetchObject();
+ print $result->Name;
+
+ //free the statement and connection
+ $stmt=null;
+ $conn=null;
+?>
+--EXPECT--
+Accounting Manager
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchObject_class_name.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchObject_class_name.phpt
new file mode 100644
index 00000000..a1cd3820
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_fetchObject_class_name.phpt
@@ -0,0 +1,36 @@
+--TEST--
+fetches the next row as an object of a user defined class
+--SKIPIF--
+
+--FILE--
+Name);
+ }
+ }// end of class
+ require('connect.inc');
+ $conn = new PDO( "sqlsrv:server=$server ; Database = $databaseName", "$uid", "$pwd");
+
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID = 5 " );
+ $contactTypes = $stmt->fetchObject('contactTypes');
+
+ //print the class properties
+ print $contactTypes->ContactTypeID."\n";
+ print $contactTypes->upperCaseName()."\n";
+ print $contactTypes->ModifiedDate;
+
+ // close the database connection
+ $stmt=null;
+ $conn=null;
+?>
+--EXPECT--
+5
+EXPORT ADMINISTRATOR
+2008-04-30 00:00:00.000
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_getColumnMeta.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_getColumnMeta.phpt
new file mode 100644
index 00000000..80ad5cdd
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_getColumnMeta.phpt
@@ -0,0 +1,43 @@
+--TEST--
+retrieves metadata for a column
+--SKIPIF--
+
+--FILE--
+query("select * from Person.ContactType");
+$metadata = $stmt->getColumnMeta(2);
+var_dump($metadata);
+
+print $metadata['sqlsrv:decl_type'] . "\n";
+print $metadata['native_type'] . "\n";
+print $metadata['name'];
+
+// free the statement and connection
+$stmt = null;
+$conn = null;
+?>
+--EXPECT--
+array(8) {
+ ["flags"]=>
+ int(0)
+ ["sqlsrv:decl_type"]=>
+ string(8) "datetime"
+ ["native_type"]=>
+ string(6) "string"
+ ["table"]=>
+ string(0) ""
+ ["pdo_type"]=>
+ int(2)
+ ["name"]=>
+ string(12) "ModifiedDate"
+ ["len"]=>
+ int(23)
+ ["precision"]=>
+ int(3)
+}
+datetime
+string
+ModifiedDate
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_nextRowset.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_nextRowset.phpt
new file mode 100644
index 00000000..475083c7
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_nextRowset.phpt
@@ -0,0 +1,350 @@
+--TEST--
+moves the cursor to the next result set and fetches results
+--SKIPIF--
+
+--FILE--
+query( $query1 . $query2);
+$rowset1 = $stmt->fetchAll();
+$stmt->nextRowset();
+$rowset2 = $stmt->fetchAll();
+var_dump( $rowset1 );
+var_dump( $rowset2 );
+
+// free the statement and connection
+$stmt = null;
+$conn = null;
+?>
+--EXPECT--
+array(26) {
+ [0]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "5"
+ [0]=>
+ string(1) "5"
+ }
+ [1]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "11"
+ [0]=>
+ string(2) "11"
+ }
+ [2]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "6"
+ [0]=>
+ string(1) "6"
+ }
+ [3]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "18"
+ [0]=>
+ string(2) "18"
+ }
+ [4]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "40"
+ [0]=>
+ string(2) "40"
+ }
+ [5]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "1"
+ [0]=>
+ string(1) "1"
+ }
+ [6]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "10"
+ [0]=>
+ string(2) "10"
+ }
+ [7]=>
+ array(2) {
+ ["AddressID"]=>
+ string(3) "868"
+ [0]=>
+ string(3) "868"
+ }
+ [8]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "19"
+ [0]=>
+ string(2) "19"
+ }
+ [9]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "16"
+ [0]=>
+ string(2) "16"
+ }
+ [10]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "15"
+ [0]=>
+ string(2) "15"
+ }
+ [11]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "12"
+ [0]=>
+ string(2) "12"
+ }
+ [12]=>
+ array(2) {
+ ["AddressID"]=>
+ string(5) "18249"
+ [0]=>
+ string(5) "18249"
+ }
+ [13]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "7"
+ [0]=>
+ string(1) "7"
+ }
+ [14]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "21"
+ [0]=>
+ string(2) "21"
+ }
+ [15]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "8"
+ [0]=>
+ string(1) "8"
+ }
+ [16]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "17"
+ [0]=>
+ string(2) "17"
+ }
+ [17]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "20"
+ [0]=>
+ string(2) "20"
+ }
+ [18]=>
+ array(2) {
+ ["AddressID"]=>
+ string(5) "26486"
+ [0]=>
+ string(5) "26486"
+ }
+ [19]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "3"
+ [0]=>
+ string(1) "3"
+ }
+ [20]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "14"
+ [0]=>
+ string(2) "14"
+ }
+ [21]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "9"
+ [0]=>
+ string(1) "9"
+ }
+ [22]=>
+ array(2) {
+ ["AddressID"]=>
+ string(2) "13"
+ [0]=>
+ string(2) "13"
+ }
+ [23]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "4"
+ [0]=>
+ string(1) "4"
+ }
+ [24]=>
+ array(2) {
+ ["AddressID"]=>
+ string(1) "2"
+ [0]=>
+ string(1) "2"
+ }
+ [25]=>
+ array(2) {
+ ["AddressID"]=>
+ string(3) "834"
+ [0]=>
+ string(3) "834"
+ }
+}
+array(20) {
+ [0]=>
+ array(2) {
+ ["Name"]=>
+ string(18) "Accounting Manager"
+ [0]=>
+ string(18) "Accounting Manager"
+ }
+ [1]=>
+ array(2) {
+ ["Name"]=>
+ string(21) "Assistant Sales Agent"
+ [0]=>
+ string(21) "Assistant Sales Agent"
+ }
+ [2]=>
+ array(2) {
+ ["Name"]=>
+ string(30) "Assistant Sales Representative"
+ [0]=>
+ string(30) "Assistant Sales Representative"
+ }
+ [3]=>
+ array(2) {
+ ["Name"]=>
+ string(27) "Coordinator Foreign Markets"
+ [0]=>
+ string(27) "Coordinator Foreign Markets"
+ }
+ [4]=>
+ array(2) {
+ ["Name"]=>
+ string(20) "Export Administrator"
+ [0]=>
+ string(20) "Export Administrator"
+ }
+ [5]=>
+ array(2) {
+ ["Name"]=>
+ string(31) "International Marketing Manager"
+ [0]=>
+ string(31) "International Marketing Manager"
+ }
+ [6]=>
+ array(2) {
+ ["Name"]=>
+ string(19) "Marketing Assistant"
+ [0]=>
+ string(19) "Marketing Assistant"
+ }
+ [7]=>
+ array(2) {
+ ["Name"]=>
+ string(17) "Marketing Manager"
+ [0]=>
+ string(17) "Marketing Manager"
+ }
+ [8]=>
+ array(2) {
+ ["Name"]=>
+ string(24) "Marketing Representative"
+ [0]=>
+ string(24) "Marketing Representative"
+ }
+ [9]=>
+ array(2) {
+ ["Name"]=>
+ string(19) "Order Administrator"
+ [0]=>
+ string(19) "Order Administrator"
+ }
+ [10]=>
+ array(2) {
+ ["Name"]=>
+ string(5) "Owner"
+ [0]=>
+ string(5) "Owner"
+ }
+ [11]=>
+ array(2) {
+ ["Name"]=>
+ string(25) "Owner/Marketing Assistant"
+ [0]=>
+ string(25) "Owner/Marketing Assistant"
+ }
+ [12]=>
+ array(2) {
+ ["Name"]=>
+ string(15) "Product Manager"
+ [0]=>
+ string(15) "Product Manager"
+ }
+ [13]=>
+ array(2) {
+ ["Name"]=>
+ string(16) "Purchasing Agent"
+ [0]=>
+ string(16) "Purchasing Agent"
+ }
+ [14]=>
+ array(2) {
+ ["Name"]=>
+ string(18) "Purchasing Manager"
+ [0]=>
+ string(18) "Purchasing Manager"
+ }
+ [15]=>
+ array(2) {
+ ["Name"]=>
+ string(31) "Regional Account Representative"
+ [0]=>
+ string(31) "Regional Account Representative"
+ }
+ [16]=>
+ array(2) {
+ ["Name"]=>
+ string(11) "Sales Agent"
+ [0]=>
+ string(11) "Sales Agent"
+ }
+ [17]=>
+ array(2) {
+ ["Name"]=>
+ string(15) "Sales Associate"
+ [0]=>
+ string(15) "Sales Associate"
+ }
+ [18]=>
+ array(2) {
+ ["Name"]=>
+ string(13) "Sales Manager"
+ [0]=>
+ string(13) "Sales Manager"
+ }
+ [19]=>
+ array(2) {
+ ["Name"]=>
+ string(20) "Sales Representative"
+ [0]=>
+ string(20) "Sales Representative"
+ }
+}
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_rowCount.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_rowCount.phpt
new file mode 100644
index 00000000..58c7d563
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_rowCount.phpt
@@ -0,0 +1,45 @@
+--TEST--
+returns the number of rows added to a table; returns the number of rows in a result set when you specify a scrollable cursor
+--SKIPIF--
+
+--FILE--
+exec("CREAtE TABLE Table1(col1 VARCHAR(15), col2 VARCHAR(15)) ");
+
+$col1 = 'a';
+$col2 = 'b';
+
+$query = "insert into Table1(col1, col2) values(?, ?)";
+$stmt = $conn->prepare( $query );
+$stmt->execute( array( $col1, $col2 ) );
+print $stmt->rowCount();
+print " rows affects.";
+
+echo "\n\n";
+
+//revert the insert
+$conn->exec("delete from Table1 where col1 = 'a' AND col2 = 'b'");
+
+$conn->exec("DROP TABLE Table1 ");
+
+$conn = null;
+
+$conn = new PDO( "sqlsrv:server=$server ; Database = $databaseName", "$uid", "$pwd");
+
+$query = "select * from Person.ContactType";
+$stmt = $conn->prepare( $query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
+$stmt->execute();
+print $stmt->rowCount();
+print " rows in result set.";
+
+
+//free the statement and connection
+$stmt = null;
+$conn = null;
+?>
+--EXPECT--
+1 rows affects.
+
+20 rows in result set.
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_setAttribute.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_setAttribute.phpt
new file mode 100644
index 00000000..e579d851
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_setAttribute.phpt
@@ -0,0 +1,25 @@
+--TEST--
+sets the query timeout attribute
+--SKIPIF--
+
+--FILE--
+false ) );
+
+$stmt = $conn->prepare('SELECT * FROM Person.ContactType');
+
+echo "Attribute number for ATTR_CURSOR: ".$stmt->getAttribute( constant( "PDO::ATTR_CURSOR" ) );
+
+echo "\n";
+
+$stmt->setAttribute(PDO::SQLSRV_ATTR_QUERY_TIMEOUT, 2);
+echo "Attribute number for SQLSRV_ATTR_QUERY_TIMEOUT: ".$stmt->getAttribute( constant( "PDO::SQLSRV_ATTR_QUERY_TIMEOUT" ) );
+
+//free the statement and connection
+$stmt = null;
+$conn = null;
+?>
+--EXPECT--
+Attribute number for ATTR_CURSOR: 0
+Attribute number for SQLSRV_ATTR_QUERY_TIMEOUT: 2
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdoStatement_setFetchMode.phpt b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_setFetchMode.phpt
new file mode 100644
index 00000000..85419b5d
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdoStatement_setFetchMode.phpt
@@ -0,0 +1,93 @@
+--TEST--
+specifies the fetch mode before fetching
+--SKIPIF--
+
+--FILE--
+query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ while ( $row = $stmt1->fetch()) {
+ print($row['Name'] . "\n");
+ }
+ print( "\n---------- PDO::FETCH_ASSOC -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $stmt->setFetchMode(PDO::FETCH_ASSOC);
+ $result = $stmt->fetch();
+ print_r( $result );
+
+ print( "\n---------- PDO::FETCH_NUM -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $stmt->setFetchMode(PDO::FETCH_NUM);
+ $result = $stmt->fetch();
+ print_r ($result );
+
+ print( "\n---------- PDO::FETCH_BOTH -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $stmt->setFetchMode(PDO::FETCH_BOTH);
+ $result = $stmt->fetch();
+ print_r( $result );
+
+ print( "\n---------- PDO::FETCH_LAZY -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $stmt->setFetchMode(PDO::FETCH_LAZY);
+ $result = $stmt->fetch();
+ print_r( $result );
+
+ print( "\n---------- PDO::FETCH_OBJ -------------\n" );
+ $stmt = $conn->query( "select * from Person.ContactType where ContactTypeID < 5 " );
+ $stmt->setFetchMode(PDO::FETCH_OBJ);
+ $result = $stmt->fetch();
+ print $result->Name;
+ print( "\n \n" );
+
+ //free the statements and connection
+ $stmt1 = null;
+ $stmt = null;
+ $conn = null;
+?>
+--EXPECT--
+Accounting Manager
+Assistant Sales Agent
+Assistant Sales Representative
+Coordinator Foreign Markets
+
+---------- PDO::FETCH_ASSOC -------------
+Array
+(
+ [ContactTypeID] => 1
+ [Name] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+
+---------- PDO::FETCH_NUM -------------
+Array
+(
+ [0] => 1
+ [1] => Accounting Manager
+ [2] => 2008-04-30 00:00:00.000
+)
+
+---------- PDO::FETCH_BOTH -------------
+Array
+(
+ [ContactTypeID] => 1
+ [0] => 1
+ [Name] => Accounting Manager
+ [1] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+)
+
+---------- PDO::FETCH_LAZY -------------
+PDORow Object
+(
+ [queryString] => select * from Person.ContactType where ContactTypeID < 5
+ [ContactTypeID] => 1
+ [Name] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+
+---------- PDO::FETCH_OBJ -------------
+Accounting Manager
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_beginTransaction.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_beginTransaction.phpt
new file mode 100644
index 00000000..b28b09ce
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_beginTransaction.phpt
@@ -0,0 +1,30 @@
+--TEST--
+starts a transaction, insert 2 rows and commit the transaction
+--SKIPIF--
+
+--FILE--
+exec("CREAtE TABLE Table1(col1 CHARACTER(1), col2 CHARACTER(1)) ");
+
+ $conn->beginTransaction();
+ $ret = $conn->exec("insert into Table1(col1, col2) values('a', 'b') ");
+ $ret = $conn->exec("insert into Table1(col1, col2) values('a', 'c') ");
+
+ //revert the inserts
+ $ret = $conn->exec("delete from Table1 where col1 = 'a'");
+ $conn->commit();
+ // $conn->rollback();
+ echo $ret." rows affected";
+
+ //drop the created temp table
+ $conn->exec("DROP TABLE Table1 ");
+
+ //free statement and connection
+ $ret=NULL;
+ $conn=NULL;
+?>
+--EXPECT--
+2 rows affected
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_construct.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_construct.phpt
new file mode 100644
index 00000000..ea1875ed
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_construct.phpt
@@ -0,0 +1,138 @@
+--TEST--
+connect to a server and specify a database
+--SKIPIF--
+
+--FILE--
+ true));
+
+ $query = 'SELECT * FROM Person.ContactType';
+ $stmt = $c->query( $query );
+ while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ) {
+ print_r( $row );
+ }
+ $stmt=null;
+ $c = null;
+?>
+--EXPECT--
+Array
+(
+ [ContactTypeID] => 1
+ [Name] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 2
+ [Name] => Assistant Sales Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 3
+ [Name] => Assistant Sales Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 4
+ [Name] => Coordinator Foreign Markets
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 5
+ [Name] => Export Administrator
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 6
+ [Name] => International Marketing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 7
+ [Name] => Marketing Assistant
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 8
+ [Name] => Marketing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 9
+ [Name] => Marketing Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 10
+ [Name] => Order Administrator
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 11
+ [Name] => Owner
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 12
+ [Name] => Owner/Marketing Assistant
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 13
+ [Name] => Product Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 14
+ [Name] => Purchasing Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 15
+ [Name] => Purchasing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 16
+ [Name] => Regional Account Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 17
+ [Name] => Sales Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 18
+ [Name] => Sales Associate
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 19
+ [Name] => Sales Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 20
+ [Name] => Sales Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_construct_2.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_construct_2.phpt
new file mode 100644
index 00000000..c2032000
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_construct_2.phpt
@@ -0,0 +1,139 @@
+--TEST--
+connect to a server, specifying the database later
+--SKIPIF--
+
+--FILE--
+exec( "USE $databaseName");
+ $query = 'SELECT * FROM Person.ContactType';
+ $stmt = $c->query( $query );
+ while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print_r( $row );
+ }
+ $stmt=null;
+ $c = null;
+?>
+--EXPECT--
+Array
+(
+ [ContactTypeID] => 1
+ [Name] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 2
+ [Name] => Assistant Sales Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 3
+ [Name] => Assistant Sales Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 4
+ [Name] => Coordinator Foreign Markets
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 5
+ [Name] => Export Administrator
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 6
+ [Name] => International Marketing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 7
+ [Name] => Marketing Assistant
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 8
+ [Name] => Marketing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 9
+ [Name] => Marketing Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 10
+ [Name] => Order Administrator
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 11
+ [Name] => Owner
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 12
+ [Name] => Owner/Marketing Assistant
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 13
+ [Name] => Product Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 14
+ [Name] => Purchasing Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 15
+ [Name] => Purchasing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 16
+ [Name] => Regional Account Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 17
+ [Name] => Sales Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 18
+ [Name] => Sales Associate
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 19
+ [Name] => Sales Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 20
+ [Name] => Sales Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_construct_MARS.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_construct_MARS.phpt
new file mode 100644
index 00000000..8dfd6762
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_construct_MARS.phpt
@@ -0,0 +1,148 @@
+--TEST--
+connect to a server, setting MARS to false
+--SKIPIF--
+
+--FILE--
+setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
+}
+
+catch( PDOException $e ) {
+ die( "Error connecting to SQL Server" );
+}
+
+$query = 'SELECT * FROM Person.ContactType';
+$stmt = $conn->query( $query );
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print_r( $row );
+}
+
+$stmt=null;
+$conn = null;
+?>
+--EXPECT--
+Array
+(
+ [ContactTypeID] => 1
+ [Name] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 2
+ [Name] => Assistant Sales Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 3
+ [Name] => Assistant Sales Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 4
+ [Name] => Coordinator Foreign Markets
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 5
+ [Name] => Export Administrator
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 6
+ [Name] => International Marketing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 7
+ [Name] => Marketing Assistant
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 8
+ [Name] => Marketing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 9
+ [Name] => Marketing Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 10
+ [Name] => Order Administrator
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 11
+ [Name] => Owner
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 12
+ [Name] => Owner/Marketing Assistant
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 13
+ [Name] => Product Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 14
+ [Name] => Purchasing Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 15
+ [Name] => Purchasing Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 16
+ [Name] => Regional Account Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 17
+ [Name] => Sales Agent
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 18
+ [Name] => Sales Associate
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 19
+ [Name] => Sales Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [ContactTypeID] => 20
+ [Name] => Sales Representative
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_errorCode.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_errorCode.phpt
new file mode 100644
index 00000000..59cfc751
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_errorCode.phpt
@@ -0,0 +1,18 @@
+--TEST--
+reports the error code of querying a misspelled column
+--SKIPIF--
+
+--FILE--
+query($query);
+print $conn->errorCode();
+
+//free the connection
+$conn=null;
+?>
+--EXPECT--
+42S22
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_errorInfo.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_errorInfo.phpt
new file mode 100644
index 00000000..9252ad32
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_errorInfo.phpt
@@ -0,0 +1,26 @@
+--TEST--
+reports the error info of querying a misspelled column
+--SKIPIF--
+
+--FILE--
+query($query);
+print $conn->errorCode();
+echo "\n";
+print_r ($conn->errorInfo());
+
+//free the connection
+$conn=null;
+?>
+--EXPECTREGEX--
+42S22
+Array
+\(
+ \[0\] => 42S22
+ \[1\] => 207
+ \[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]Invalid column name 'Cityx'.
+\)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_exec.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_exec.phpt
new file mode 100644
index 00000000..76ede8e8
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_exec.phpt
@@ -0,0 +1,24 @@
+--TEST--
+execute a delete and reports how many rows were deleted
+--SKIPIF--
+
+--FILE--
+exec("use tempdb");
+ $c->exec("CREAtE TABLE Table1(col1 VARCHAR(100), col2 VARCHAR(100)) ");
+
+ $ret = $c->exec("insert into Table1 values('xxxyy', 'yyxx')");
+ $ret = $c->exec("delete from Table1 where col1 = 'xxxyy'");
+ echo $ret," rows affected";
+
+ $c->exec("DROP TABLE Table1 ");
+
+ //free the statement and connection
+ $ret=null;
+ $c=null;
+?>
+--EXPECT--
+1 rows affected
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_getAttribute.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_getAttribute.phpt
new file mode 100644
index 00000000..a134c797
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_getAttribute.phpt
@@ -0,0 +1,39 @@
+--TEST--
+shows the PDO::ATR_ERRMODE attribute, before and after changing its value
+--SKIPIF--
+
+--FILE--
+getAttribute( constant( "PDO::ATTR_$val" ) ));
+}
+
+$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
+
+$attributes1 = array( "ERRMODE" );
+foreach ( $attributes1 as $val ) {
+ echo "PDO::ATTR_$val: ";
+ var_dump ($conn->getAttribute( constant( "PDO::ATTR_$val" ) ));
+}
+
+// An example using PDO::ATTR_CLIENT_VERSION
+print_r($conn->getAttribute( PDO::ATTR_CLIENT_VERSION ));
+
+//free the connection
+$conn=null;
+?>
+--EXPECTREGEX--
+PDO::ATTR_ERRMODE: int\(0\)
+PDO::ATTR_ERRMODE: int\(2\)
+Array
+\(
+ \[DriverDllName\] => msodbcsql[0-9]{2}\.dll|libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]
+ \[DriverODBCVer\] => [0-9]{1,2}\.[0-9]{1,2}
+ \[DriverVer\] => [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}
+ \[ExtensionVer\] => [0-9]\.[0-9]\.[0-9](\-((rc)|(preview))(\.[0-9]+)?)?(\+[0-9]+)?
+\)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_getAvailableDrivers.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_getAvailableDrivers.phpt
new file mode 100644
index 00000000..7db00eea
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_getAvailableDrivers.phpt
@@ -0,0 +1,16 @@
+--TEST--
+check if sqlsrv is in the array of available PDO drivers
+--SKIPIF--
+
+--FILE--
+
+--EXPECT--
+sqlsrv found
+Done
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_prepare.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_prepare.phpt
new file mode 100644
index 00000000..486ef016
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_prepare.phpt
@@ -0,0 +1,36 @@
+--TEST--
+prepares a statement with parameter markers and forward-only (server-side) cursor
+--SKIPIF--
+
+--FILE--
+exec("CREAtE TABLE Table1(col1 VARCHAR(100), col2 VARCHAR(100))");
+
+$col1 = 'a';
+$col2 = 'b';
+
+$query = "insert into Table1(col1, col2) values(?, ?)";
+$stmt = $conn->prepare( $query, array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY, PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 1 ) );
+$stmt->execute( array( $col1, $col2 ) );
+print $stmt->rowCount();
+echo " row affected\n";
+
+$query = "insert into Table1(col1, col2) values(:col1, :col2)";
+$stmt = $conn->prepare( $query, array( PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY, PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 1 ) );
+$stmt->execute( array( ':col1' => $col1, ':col2' => $col2 ) );
+print $stmt->rowCount();
+echo " row affected\n";
+
+// revert the inserts
+$conn->exec("delete from Table1 where col1 = 'a' AND col2 = 'b'");
+
+$conn->exec("DROP TABLE Table1 ");
+$stmt = null;
+$conn = null;
+?>
+--EXPECT--
+1 row affected
+1 row affected
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_prepare_2.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_prepare_2.phpt
new file mode 100644
index 00000000..639b5b7c
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_prepare_2.phpt
@@ -0,0 +1,89 @@
+--TEST--
+prepares a statement with a client-side cursor
+--SKIPIF--
+
+--FILE--
+prepare( $query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
+$stmt->execute();
+
+echo "\n";
+
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print "$row[Name]\n";
+}
+echo "\n..\n";
+
+$row = $stmt->fetch( PDO::FETCH_BOTH, PDO::FETCH_ORI_FIRST );
+print_r($row);
+
+$row = $stmt->fetch( PDO::FETCH_ASSOC, PDO::FETCH_ORI_REL, 1 );
+print "$row[Name]\n";
+
+$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT );
+print "$row[1]\n";
+
+$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR );
+print "$row[1]..\n";
+
+$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_ABS, 0 );
+print_r($row);
+
+$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_LAST );
+print_r($row);
+
+//free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+Accounting Manager
+Assistant Sales Agent
+Assistant Sales Representative
+Coordinator Foreign Markets
+Export Administrator
+International Marketing Manager
+Marketing Assistant
+Marketing Manager
+Marketing Representative
+Order Administrator
+Owner
+Owner/Marketing Assistant
+Product Manager
+Purchasing Agent
+Purchasing Manager
+Regional Account Representative
+Sales Agent
+Sales Associate
+Sales Manager
+Sales Representative
+
+..
+Array
+(
+ [ContactTypeID] => 1
+ [0] => 1
+ [Name] => Accounting Manager
+ [1] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+)
+Assistant Sales Agent
+Assistant Sales Representative
+Assistant Sales Agent..
+Array
+(
+ [0] => 1
+ [1] => Accounting Manager
+ [2] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [0] => 20
+ [1] => Sales Representative
+ [2] => 2008-04-30 00:00:00.000
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_prepare_cursor.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_prepare_cursor.phpt
new file mode 100644
index 00000000..2bb2d4eb
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_prepare_cursor.phpt
@@ -0,0 +1,91 @@
+--TEST--
+prepares a statement with a client-side cursor and specifies scroll type to buffered
+--SKIPIF--
+
+--FILE--
+prepare( $query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED));
+$stmt->execute();
+print $stmt->rowCount();
+
+echo "\n";
+
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print "$row[Name]\n";
+}
+echo "\n..\n";
+
+$row = $stmt->fetch( PDO::FETCH_BOTH, PDO::FETCH_ORI_FIRST );
+print_r($row);
+
+$row = $stmt->fetch( PDO::FETCH_ASSOC, PDO::FETCH_ORI_REL, 1 );
+print "$row[Name]\n";
+
+$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_NEXT );
+print "$row[1]\n";
+
+$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_PRIOR );
+print "$row[1]..\n";
+
+$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_ABS, 0 );
+print_r($row);
+
+$row = $stmt->fetch( PDO::FETCH_NUM, PDO::FETCH_ORI_LAST );
+print_r($row);
+
+//free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+20
+Accounting Manager
+Assistant Sales Agent
+Assistant Sales Representative
+Coordinator Foreign Markets
+Export Administrator
+International Marketing Manager
+Marketing Assistant
+Marketing Manager
+Marketing Representative
+Order Administrator
+Owner
+Owner/Marketing Assistant
+Product Manager
+Purchasing Agent
+Purchasing Manager
+Regional Account Representative
+Sales Agent
+Sales Associate
+Sales Manager
+Sales Representative
+
+..
+Array
+(
+ [ContactTypeID] => 1
+ [0] => 1
+ [Name] => Accounting Manager
+ [1] => Accounting Manager
+ [ModifiedDate] => 2008-04-30 00:00:00.000
+ [2] => 2008-04-30 00:00:00.000
+)
+Assistant Sales Agent
+Assistant Sales Representative
+Assistant Sales Agent..
+Array
+(
+ [0] => 1
+ [1] => Accounting Manager
+ [2] => 2008-04-30 00:00:00.000
+)
+Array
+(
+ [0] => 20
+ [1] => Sales Representative
+ [2] => 2008-04-30 00:00:00.000
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_query.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_query.phpt
new file mode 100644
index 00000000..77029053
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_query.phpt
@@ -0,0 +1,135 @@
+--TEST--
+default query; query for a column; query with a new class; query into an existing class
+--SKIPIF--
+
+--FILE--
+setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
+$conn->setAttribute( PDO::SQLSRV_ATTR_QUERY_TIMEOUT, 1 );
+
+$query = 'select * from Person.ContactType';
+
+// simple query
+$stmt = $conn->query( $query );
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print_r( $row['Name'] ."\n" );
+}
+
+echo "\n........ query for a column ............\n";
+
+// query for one column
+$stmt = $conn->query( $query, PDO::FETCH_COLUMN, 1 );
+while ( $row = $stmt->fetch() ){
+ echo "$row\n";
+}
+
+echo "\n........ query with a new class ............\n";
+$query = 'select * from HumanResources.Department order by GroupName';
+// query with a class
+class cc {
+ function __construct( $arg ) {
+ echo "$arg";
+ }
+
+ function __toString() {
+ return $this->DepartmentID . "; " . $this->Name . "; " . $this->GroupName;
+ }
+}
+
+$stmt = $conn->query( $query, PDO::FETCH_CLASS, 'cc', array( "arg1 " ));
+
+while ( $row = $stmt->fetch() ){
+ echo "$row\n";
+}
+
+echo "\n........ query into an existing class ............\n";
+$c_obj = new cc( '' );
+$stmt = $conn->query( $query, PDO::FETCH_INTO, $c_obj );
+while ( $stmt->fetch() ){
+ echo "$c_obj\n";
+}
+
+$stmt = null;
+$conn=null;
+?>
+--EXPECT--
+Accounting Manager
+Assistant Sales Agent
+Assistant Sales Representative
+Coordinator Foreign Markets
+Export Administrator
+International Marketing Manager
+Marketing Assistant
+Marketing Manager
+Marketing Representative
+Order Administrator
+Owner
+Owner/Marketing Assistant
+Product Manager
+Purchasing Agent
+Purchasing Manager
+Regional Account Representative
+Sales Agent
+Sales Associate
+Sales Manager
+Sales Representative
+
+........ query for a column ............
+Accounting Manager
+Assistant Sales Agent
+Assistant Sales Representative
+Coordinator Foreign Markets
+Export Administrator
+International Marketing Manager
+Marketing Assistant
+Marketing Manager
+Marketing Representative
+Order Administrator
+Owner
+Owner/Marketing Assistant
+Product Manager
+Purchasing Agent
+Purchasing Manager
+Regional Account Representative
+Sales Agent
+Sales Associate
+Sales Manager
+Sales Representative
+
+........ query with a new class ............
+arg1 9; Human Resources; Executive General and Administration
+arg1 10; Finance; Executive General and Administration
+arg1 11; Information Services; Executive General and Administration
+arg1 14; Facilities and Maintenance; Executive General and Administration
+arg1 16; Executive; Executive General and Administration
+arg1 15; Shipping and Receiving; Inventory Management
+arg1 5; Purchasing; Inventory Management
+arg1 7; Production; Manufacturing
+arg1 8; Production Control; Manufacturing
+arg1 12; Document Control; Quality Assurance
+arg1 13; Quality Assurance; Quality Assurance
+arg1 6; Research and Development; Research and Development
+arg1 1; Engineering; Research and Development
+arg1 2; Tool Design; Research and Development
+arg1 3; Sales; Sales and Marketing
+arg1 4; Marketing; Sales and Marketing
+
+........ query into an existing class ............
+9; Human Resources; Executive General and Administration
+10; Finance; Executive General and Administration
+11; Information Services; Executive General and Administration
+14; Facilities and Maintenance; Executive General and Administration
+16; Executive; Executive General and Administration
+15; Shipping and Receiving; Inventory Management
+5; Purchasing; Inventory Management
+7; Production; Manufacturing
+8; Production Control; Manufacturing
+12; Document Control; Quality Assurance
+13; Quality Assurance; Quality Assurance
+6; Research and Development; Research and Development
+1; Engineering; Research and Development
+2; Tool Design; Research and Development
+3; Sales; Sales and Marketing
+4; Marketing; Sales and Marketing
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_quote.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_quote.phpt
new file mode 100644
index 00000000..73ffc429
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_quote.phpt
@@ -0,0 +1,42 @@
+--TEST--
+insert with quoted parameters
+--SKIPIF--
+
+--FILE--
+exec("CREAtE TABLE Table1(col1 VARCHAR(15), col2 VARCHAR(15)) ");
+
+$param = 'a \' g';
+$param2 = $conn->quote( $param );
+
+$query = "INSERT INTO Table1 VALUES( ?, '1' )";
+$stmt = $conn->prepare( $query );
+$stmt->execute(array($param));
+
+$query = "INSERT INTO Table1 VALUES( ?, ? )";
+$stmt = $conn->prepare( $query );
+$stmt->execute(array($param, $param2));
+
+$query = "SELECT * FROM Table1";
+$stmt = $conn->query($query);
+while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ) ){
+ print_r( $row['col1'] ." was inserted\n" );
+}
+
+// revert the inserts
+$query = "delete from Table1 where col1 = ?";
+$stmt = $conn->prepare( $query );
+$stmt->execute(array($param));
+
+$conn->exec("DROP TABLE Table1 ");
+
+//free the statement and connection
+$stmt=null;
+$conn=null;
+?>
+--EXPECT--
+a ' g was inserted
+a ' g was inserted
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_setAttribute.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_setAttribute.phpt
new file mode 100644
index 00000000..8991ffa9
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_setAttribute.phpt
@@ -0,0 +1,29 @@
+--TEST--
+sets to PDO::ATTR_ERRMODE
+--SKIPIF--
+
+--FILE--
+getAttribute( constant( "PDO::ATTR_$val" ) ));
+ }
+
+ $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
+
+ $attributes1 = array( "ERRMODE" );
+ foreach ( $attributes1 as $val ) {
+ echo "PDO::ATTR_$val: ";
+ var_dump ($conn->getAttribute( constant( "PDO::ATTR_$val" ) ));
+ }
+
+ //free the connection
+ $conn=null;
+?>
+--EXPECT--
+PDO::ATTR_ERRMODE: int(0)
+PDO::ATTR_ERRMODE: int(2)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/msdn_pdo_setAttribute_direct_query.phpt b/test/bvt/pdo_sqlsrv/msdn_pdo_setAttribute_direct_query.phpt
new file mode 100644
index 00000000..ae2ca1b1
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/msdn_pdo_setAttribute_direct_query.phpt
@@ -0,0 +1,42 @@
+--TEST--
+sets to PDO::SQLSRV_ATTR_DIRECT_QUERY
+--SKIPIF--
+
+--FILE--
+setAttribute(constant('PDO::SQLSRV_ATTR_DIRECT_QUERY'), true);
+
+ $stmt1 = $conn->query("DROP TABLE #php_test_table");
+
+ $stmt2 = $conn->query("CREATE TABLE #php_test_table ([c1_int] int, [c2_int] int)");
+
+ $v1 = 1;
+ $v2 = 2;
+
+ $stmt3 = $conn->prepare("INSERT INTO #php_test_table (c1_int, c2_int) VALUES (:var1, :var2)");
+
+ if ($stmt3) {
+ $stmt3->bindValue(1, $v1);
+ $stmt3->bindValue(2, $v2);
+
+ if ($stmt3->execute())
+ echo "Execution succeeded\n";
+ else
+ echo "Execution failed\n";
+ }
+ else
+ var_dump($conn->errorInfo());
+
+ $stmt4 = $conn->query("DROP TABLE #php_test_table");
+
+ // free the statements and connection
+ $stmt1=null;
+ $stmt2=null;
+ $stmt3=null;
+ $stmt4=null;
+ $conn=null;
+ ?>
+--EXPECT--
+Execution succeeded
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_double.phpt b/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_double.phpt
new file mode 100644
index 00000000..abcbdac2
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_double.phpt
@@ -0,0 +1,61 @@
+--TEST--
+call a stored procedure and retrieve the errorNumber that is returned
+--SKIPIF--
+
+--FILE--
+query($tsql_dropSP);
+
+ // Create the stored procedure
+ $tsql_createSP = "CREATE PROCEDURE sp_Test_Double
+ @ErrorNumber as float(53) = 0.0 OUTPUT
+ AS
+ BEGIN
+ SET @ErrorNumber = -1.111
+ SELECT 1, 2, 3
+ END";
+ $stmt = $conn->query($tsql_createSP);
+
+ // Call the stored procedure
+ $stmt = $conn->prepare("{CALL sp_Test_Double (?)}");
+
+ $errorNumber = 0.0;
+ $stmt->bindParam(1, $errorNumber, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 20);
+ $stmt->execute();
+
+ $result = $stmt->fetchAll(PDO::FETCH_NUM);
+
+ $stmt->closeCursor();
+
+ print("Error Number: $errorNumber\n\n");
+ $value = $errorNumber - 2;
+ print("Error Number minus 2: $value\n\n");
+
+ print_r($result);
+
+ //free the statement and connection
+ $stmt = null;
+ $conn = null;
+?>
+--EXPECT--
+Error Number: -1.111
+
+Error Number minus 2: -3.111
+
+Array
+(
+ [0] => Array
+ (
+ [0] => 1
+ [1] => 2
+ [2] => 3
+ )
+
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_integer.phpt b/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_integer.phpt
new file mode 100644
index 00000000..d1e6839c
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_integer.phpt
@@ -0,0 +1,57 @@
+--TEST--
+call a stored procedure and retrieve the errorNumber that is returned
+--SKIPIF--
+
+--FILE--
+query($tsql_dropSP);
+
+ // Create the stored procedure
+ $tsql_createSP = "CREATE PROCEDURE sp_Test_Integer
+ @ErrorNumber AS INT = 0 OUTPUT
+ AS
+ BEGIN
+ SET @ErrorNumber = -1
+ SELECT 1,2,3
+ END";
+
+ $stmt = $conn->query($tsql_createSP);
+
+ // Call the stored procedure
+ $stmt = $conn->prepare("{CALL sp_Test_Integer (:errornumber)}");
+
+ $errorNumber = 0;
+ $stmt->bindParam('errornumber', $errorNumber, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT, 4);
+
+ $stmt->execute();
+ $result = $stmt->fetchAll(PDO::FETCH_NUM);
+
+ $stmt->closeCursor();
+
+ print("Error Number: $errorNumber\n\n");
+ print_r($result);
+
+ //free the statement and connection
+ $stmt = null;
+ $conn = null;
+?>
+--EXPECT--
+Error Number: -1
+
+Array
+(
+ [0] => Array
+ (
+ [0] => 1
+ [1] => 2
+ [2] => 3
+ )
+
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_string.phpt b/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_string.phpt
new file mode 100644
index 00000000..b8d60af2
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/pdo_bindParam_inout_string.phpt
@@ -0,0 +1,60 @@
+--TEST--
+call a stored procedure and retrieve the errorString that is returned
+--SKIPIF--
+
+--FILE--
+query($tsql_dropSP);
+
+ // Create the stored procedure
+ $tsql_createSP = "CREATE PROCEDURE sp_Test_String
+ @ErrorString as varchar(20) OUTPUT
+ AS
+ BEGIN
+ SET @ErrorString = REVERSE(@ErrorString)
+ SELECT 1,2,3
+ END";
+ $stmt = $conn->query($tsql_createSP);
+
+ // Call the stored procedure
+ $stmt = $conn->prepare("{CALL sp_Test_String (?)}");
+
+ $errorString = "12345";
+ $stmt->bindParam(1, $errorString, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 20);
+ print("Error String: $errorString\n\n");
+
+ $stmt->execute();
+
+ $result = $stmt->fetchAll(PDO::FETCH_NUM);
+
+ $stmt->closeCursor();
+
+ print("Error String: $errorString\n\n");
+ print_r($result);
+
+ //free the statement and connection
+ $stmt = null;
+ $conn = null;
+?>
+--EXPECT--
+Error String: 12345
+
+Error String: 54321
+
+Array
+(
+ [0] => Array
+ (
+ [0] => 1
+ [1] => 2
+ [2] => 3
+ )
+
+)
\ No newline at end of file
diff --git a/test/bvt/pdo_sqlsrv/readme.txt b/test/bvt/pdo_sqlsrv/readme.txt
new file mode 100644
index 00000000..43f4a9cc
--- /dev/null
+++ b/test/bvt/pdo_sqlsrv/readme.txt
@@ -0,0 +1,7 @@
+This folder mainly contains tests that are derived from the code examples on
+
+https://docs.microsoft.com/en-us/sql/connect/php/pdo-class
+https://docs.microsoft.com/en-us/sql/connect/php/pdostatement-class
+
+Modify connect.inc with the real credentials to run the tests, using the latest run-tests.php from
+https://raw.githubusercontent.com/php/php-src/master/run-tests.php
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/break.inc b/test/bvt/sqlsrv/break.inc
new file mode 100644
index 00000000..6a2e190e
--- /dev/null
+++ b/test/bvt/sqlsrv/break.inc
@@ -0,0 +1,106 @@
+"$databaseName", "username"=>"$username", "password"=>"$password" );
+$conn = sqlsrv_connect( $serverName, $connectionInfo );
+
+// CREATE database
+$stmt0 = sqlsrv_query($conn, "CREATE DATABASE $databaseName");
+
+// Create table
+$sql = "CREATE TABLE $tableName1 (c1 INT, c2 VARCHAR(40))";
+$stmt = sqlsrv_query($conn, $sql);
+
+// Insert data using bind parameters
+$sql = "INSERT INTO $tableName1 VALUES (?,?)";
+for($t=100; $t<115; $t++) {
+ $stmt = sqlsrv_prepare($conn, $sql);
+ $ts = substr(sha1($t),0,5);
+ $params = array($t,$ts);
+ sqlsrv_execute($stmt, $params);
+}
+
+// Create table
+$sql = "CREATE TABLE $tableName2 (c1 INT, c2 VARCHAR(40))";
+$stmt = sqlsrv_query($conn, $sql);
+
+// Insert data using bind parameters
+$sql = "INSERT INTO $tableName2 VALUES (?,?)";
+for($t=200; $t<208; $t++) {
+ $stmt = sqlsrv_prepare($conn, $sql);
+ $ts = substr(sha1($t),0,5);
+ $params = array($t,$ts);
+ sqlsrv_execute($stmt, $params);
+}
+
+sqlsrv_close( $conn );
+
+function RestartConn($serverName)
+{
+ $powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
+ $restart_string = "$powershell (get-service -ComputerName $serverName -Name mssqlserver).Stop()";
+ exec( $restart_string );
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+
+ // Wait until the service is fully stopped
+ while (substr_count($servstring, "Stopped") != 1)
+ {
+ sleep(1);
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+ }
+ $restart_string = "$powershell (get-service -ComputerName $serverName -Name mssqlserver).Start()";
+ exec( $restart_string );
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+
+ // Wait until the service is fully started
+ while (substr_count($servstring, "Running") != 1)
+ {
+ sleep(1);
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+ }
+}
+
+function StopConn($serverName)
+{
+ $powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
+ $restart_string = "$powershell (get-service -ComputerName $serverName -Name mssqlserver).Stop()";
+ exec( $restart_string );
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+
+ // Wait until the service is fully stopped
+ while (substr_count($servstring, "Stopped") != 1)
+ {
+ sleep(1);
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+ }
+}
+
+function StartConn($serverName)
+{
+ $powershell = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+ if (substr_count($servstring, "Running") != 1)
+ {
+ $restart_string = "$powershell (get-service -ComputerName $serverName -Name mssqlserver).Start()";
+ exec( $restart_string );
+ }
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+
+ // Wait until the service is fully started
+ while (substr_count($servstring, "Running") != 1)
+ {
+ sleep(1);
+ $servstring = shell_exec("$powershell get-service -ComputerName $serverName -Name mssqlserver");
+ }
+}
+?>
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/break.php b/test/bvt/sqlsrv/break.php
new file mode 100644
index 00000000..da5826c5
--- /dev/null
+++ b/test/bvt/sqlsrv/break.php
@@ -0,0 +1,88 @@
+$dbName, "uid"=>$uid, "pwd"=>$pwd );
+
+ $conn = sqlsrv_connect( $server, $connectionInfo );
+ if ( $conn === false )
+ {
+ die ( print_r( sqlsrv_errors() ) );
+ }
+
+ // Create table
+ $sql = "CREATE TABLE $tableName1 ( c1 INT, c2 VARCHAR(40) )";
+ $stmt = sqlsrv_query( $conn, $sql );
+
+ // Insert data
+ $sql = "INSERT INTO $tableName1 VALUES ( ?, ? )";
+ for( $t = 100; $t < 116; $t++ )
+ {
+ $ts = substr( sha1( $t ),0,5 );
+ $params = array( $t,$ts );
+ $stmt = sqlsrv_prepare( $conn, $sql, $params );
+ sqlsrv_execute( $stmt );
+ }
+
+ // Create table
+ $sql = "CREATE TABLE $tableName2 ( c1 INT, c2 VARCHAR(40) )";
+ $stmt = sqlsrv_query( $conn, $sql );
+
+ // Insert data
+ $sql = "INSERT INTO $tableName2 VALUES ( ?, ? )";
+ for( $t = 200; $t < 209; $t++ )
+ {
+ $ts = substr( sha1( $t ),0,5 );
+ $params = array( $t,$ts );
+ $stmt = sqlsrv_prepare( $conn, $sql, $params );
+ sqlsrv_execute( $stmt );
+ }
+
+ sqlsrv_close( $conn );
+}
+
+// Break connection by getting the session ID and killing it.
+// Note that breaking a connection and testing reconnection requires a
+// TCP/IP protocol connection (as opposed to a Shared Memory protocol).
+function BreakConnection( $conn, $conn_break )
+{
+ $stmt1 = sqlsrv_query( $conn, "SELECT @@SPID" );
+ if ( sqlsrv_fetch( $stmt1 ) )
+ {
+ $spid=sqlsrv_get_field( $stmt1, 0 );
+ }
+
+ $stmt2 = sqlsrv_prepare( $conn_break, "KILL ".$spid );
+ sqlsrv_execute( $stmt2 );
+ sleep(1);
+}
+
+// Remove the tables generated by GenerateTables
+function DropTables( $server, $uid, $pwd, $tableName1, $tableName2 )
+{
+ $connectionInfo = array( "UID"=>$uid, "PWD"=>$pwd );
+ $conn = sqlsrv_connect( $server, $connectionInfo );
+
+ $query="IF OBJECT_ID('tempdb.dbo.$tableName1, 'U') IS NOT NULL DROP TABLE tempdb.dbo.$tableName1";
+ $stmt=sqlsrv_query( $conn, $query );
+
+ $query="IF OBJECT_ID('tempdb.dbo.$tableName2, 'U') IS NOT NULL DROP TABLE tempdb.dbo.$tableName2";
+ $stmt=sqlsrv_query( $conn, $query );
+}
+
+DropTables( $server, $uid, $pwd, $tableName1, $tableName2 );
+GenerateTables( $server, $uid, $pwd, $dbName, $tableName1, $tableName2 );
+
+?>
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/connect.inc b/test/bvt/sqlsrv/connect.inc
new file mode 100644
index 00000000..07f9289a
--- /dev/null
+++ b/test/bvt/sqlsrv/connect.inc
@@ -0,0 +1,31 @@
+$databaseName, "UID"=>$uid, "PWD"=>$pwd );
+ $conn = sqlsrv_connect( $server, $connectionInfo);
+ if( $conn === false )
+ {
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+ }
+
+ $stmt0 = sqlsrv_query( $conn, "UPDATE Sales.SalesOrderHeader SET RevisionNumber = 2");
+ if ( !$stmt0 )
+ {
+ echo "Resetting the RevisionNumber failed.\n";
+ die( print_r( sqlsrv_errors(), true));
+ }
+
+ sqlsrv_close( $conn );
+}
+
+?>
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_begin_transaction.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_begin_transaction.phpt
new file mode 100644
index 00000000..c4b5c9b9
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_begin_transaction.phpt
@@ -0,0 +1,74 @@
+--TEST--
+executes two queries as part of a transaction
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>$uid, "PWD"=>$pwd);
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+/* Initiate transaction. */
+/* Exit script if transaction cannot be initiated. */
+if ( sqlsrv_begin_transaction( $conn ) === false )
+{
+ echo "Could not begin transaction.\n";
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+/* Initialize parameter values. */
+$orderId = 43659; $qty = 5; $productId = 709;
+$offerId = 1; $price = 5.70;
+
+/* Set up and execute the first query. */
+$tsql1 = "INSERT INTO Sales.SalesOrderDetail
+ (SalesOrderID,
+ OrderQty,
+ ProductID,
+ SpecialOfferID,
+ UnitPrice)
+ VALUES (?, ?, ?, ?, ?)";
+$params1 = array( $orderId, $qty, $productId, $offerId, $price);
+$stmt1 = sqlsrv_query( $conn, $tsql1, $params1 );
+
+/* Set up and execute the second query. */
+$tsql2 = "UPDATE Production.ProductInventory
+ SET Quantity = (Quantity - ?)
+ WHERE ProductID = ?";
+$params2 = array($qty, $productId);
+$stmt2 = sqlsrv_query( $conn, $tsql2, $params2 );
+
+/* If both queries were successful, commit the transaction. */
+/* Otherwise, rollback the transaction. */
+if( $stmt1 && $stmt2 )
+{
+ sqlsrv_commit( $conn );
+ echo "Transaction was committed.\n";
+}
+else
+{
+ sqlsrv_rollback( $conn );
+ echo "Transaction was rolled back.\n";
+}
+
+/* Revert the changes */
+$d_sql = "DELETE FROM Sales.SalesOrderDetail WHERE SalesOrderID=43659 AND OrderQty=5 AND ProductID=709 AND SpecialOfferID=1 AND Unitprice=5.70";
+$stmt3 = sqlsrv_query($conn, $d_sql);
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt1);
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_free_stmt($stmt3);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Transaction was committed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_begin_transaction_2.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_begin_transaction_2.phpt
new file mode 100644
index 00000000..e7b4abcf
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_begin_transaction_2.phpt
@@ -0,0 +1,78 @@
+--TEST--
+delete in a transaction
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Begin transaction. */
+if( sqlsrv_begin_transaction($conn) === false )
+{
+ echo "Could not begin transaction.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set the Order ID. */
+$orderId = 43667;
+
+/* Execute operations that are part of the transaction. Commit on
+success, roll back on failure. */
+if (perform_trans_ops($conn, $orderId))
+{
+ //If commit fails, roll back the transaction.
+ if(sqlsrv_commit($conn))
+ {
+ echo "Transaction committed.\n";
+ }
+ else
+ {
+ echo "Commit failed - rolling back.\n";
+ sqlsrv_rollback($conn);
+ }
+}
+else
+{
+ "Error in transaction operation - rolling back.\n";
+ sqlsrv_rollback($conn);
+}
+
+/*Free connection resources*/
+sqlsrv_close( $conn);
+/*---------------- FUNCTION: perform_trans_ops -----------------*/
+function perform_trans_ops($conn, $orderId)
+{
+ /* Define query to update inventory based on sales order info. */
+ $tsql1 = "UPDATE Production.ProductInventory
+ SET Quantity = Quantity + s.OrderQty
+ FROM Production.ProductInventory p
+ JOIN Sales.SalesOrderDetail s
+ ON s.ProductID = p.ProductID
+ WHERE s.SalesOrderID = ?";
+
+ /* Define the parameters array. */
+ $params = array($orderId);
+
+ /* Execute the UPDATE statement. Return false on failure. */
+ if( sqlsrv_query( $conn, $tsql1, $params) === false ) return false;
+
+ /* Delete the sales order. Return false on failure */
+ $tsql2 = "DELETE FROM Sales.SalesOrderDetail
+ WHERE SalesOrderID = ?";
+ if(sqlsrv_query( $conn, $tsql2, $params) === false ) return false;
+
+ /* Return true because all operations were successful. */
+ return true;
+}
+?>
+--EXPECT--
+Transaction committed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_cancel.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_cancel.phpt
new file mode 100644
index 00000000..382c58d6
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_cancel.phpt
@@ -0,0 +1,49 @@
+--TEST--
+executes a query, then comsumes and counts results until reaches a specified amount. The remaining query results are then discarded.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Prepare and execute the query. */
+$tsql = "SELECT OrderQty, UnitPrice FROM Sales.SalesOrderDetail ORDER BY SalesOrderID";
+$stmt = sqlsrv_prepare( $conn, $tsql);
+if( $stmt === false )
+{
+ echo "Error in statement preparation.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+if( sqlsrv_execute( $stmt ) === false)
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Initialize tracking variables. */
+$salesTotal = 0;
+$count = 0;
+
+/* Count and display the number of sales that produce revenue
+of $100,000. */
+while( ($row = sqlsrv_fetch_array( $stmt)) && $salesTotal <=100000)
+{
+ $qty = $row[0];
+ $price = $row[1];
+ $salesTotal += ( $price * $qty);
+ $count++;
+}
+echo "$count sales accounted for the first $$salesTotal in revenue.\n";
+
+/* Cancel the pending results. The statement can be reused. */
+sqlsrv_cancel( $stmt);
+?>
+--EXPECT--
+57 sales accounted for the first $104171.7607 in revenue.
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_cancel_1.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_cancel_1.phpt
new file mode 100644
index 00000000..6bf0bcc4
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_cancel_1.phpt
@@ -0,0 +1,80 @@
+--TEST--
+cancels a statement then reuse.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Prepare and execute the query. */
+echo "
" . $row[0] . " | "; + echo "" . $row[1] . " | "; + echo "" . $row[2] . " | "; + echo "" . $row[3] . " | "; + echo "" . $row[4] . " | "; + echo "" . $row[7] . " | "; + echo "
" . $row[0] . " | "; + echo "" . $row[1] . " | "; + echo "" . $row[3] . " | "; + echo "" . $row[4] . " | "; + echo "" . $row[7] . " | "; + echo "
Finished successfully"; + + + +?> +--EXPECT-- +
1 | 1970 Napa Ct. | Bothell | 79 | 9AADCB0D-36CF-483F-84D8-585C2D4EC6E9 | |
2 | 9833 Mt. Dias Blv. | Bothell | 79 | 32A54B9E-E034-4BFB-B573-A71CDE60D8C0 | |
3 | 7484 Roundtree Drive | Bothell | 79 | 4C506923-6D1B-452C-A07C-BAA6F5B142A4 |
Finished successfully
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_client_info.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_client_info.phpt
new file mode 100644
index 00000000..b0d42566
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_client_info.phpt
@@ -0,0 +1,35 @@
+--TEST--
+client information.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+if( $client_info = sqlsrv_client_info( $conn))
+{
+ foreach( $client_info as $key => $value)
+ {
+ echo $key.": ".$value."\n";
+ }
+}
+else
+{
+ echo "Client info error.\n";
+}
+
+/* Close connection resources. */
+sqlsrv_close( $conn);
+?>
+--EXPECTREGEX--
+DriverDllName: msodbcsql[0-9]{2}\.dll|libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]
+DriverODBCVer: [0-9]{1,2}\.[0-9]{1,2}
+DriverVer: [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}
+ExtensionVer: [0-9]\.[0-9]\.[0-9](\-((rc)|(preview))(\.[0-9]+)?)?(\+[0-9]+)?
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_close.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_close.phpt
new file mode 100644
index 00000000..0b95facc
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_close.phpt
@@ -0,0 +1,35 @@
+--TEST--
+closes a connection.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Prepare and execute the query. */
+$tsql = "SELECT OrderQty, UnitPrice FROM Sales.SalesOrderDetail";
+$stmt = sqlsrv_prepare( $conn, $tsql);
+if( $stmt === false )
+{
+ echo "Error in statement preparation.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+if( sqlsrv_execute( $stmt ) === false)
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Close the connection. */
+sqlsrv_close( $conn);
+echo "Connection closed.\n";
+?>
+--EXPECT--
+Connection closed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_commit.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_commit.phpt
new file mode 100644
index 00000000..ddcff9fc
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_commit.phpt
@@ -0,0 +1,71 @@
+--TEST--
+executes two queries as part of a transaction. If both queries are successful, the transaction is committed.
+--SKIPIF--
+
+?>
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+/* Initiate transaction. */
+/* Exit script if transaction cannot be initiated. */
+if (sqlsrv_begin_transaction( $conn) === false)
+{
+ echo "Could not begin transaction.\n";
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+/* Initialize parameter values. */
+$orderId = 43659; $qty = 5; $productId = 709;
+$offerId = 1; $price = 5.70;
+
+/* Set up and execute the first query. */
+$tsql1 = "INSERT INTO Sales.SalesOrderDetail
+ (SalesOrderID,
+ OrderQty,
+ ProductID,
+ SpecialOfferID,
+ UnitPrice)
+ VALUES (?, ?, ?, ?, ?)";
+$params1 = array( $orderId, $qty, $productId, $offerId, $price);
+$stmt1 = sqlsrv_query( $conn, $tsql1, $params1 );
+
+/* Set up and execute the second query. */
+$tsql2 = "UPDATE Production.ProductInventory
+ SET Quantity = (Quantity - ?)
+ WHERE ProductID = ?";
+$params2 = array($qty, $productId);
+$stmt2 = sqlsrv_query( $conn, $tsql2, $params2 );
+
+/* If both queries were successful, commit the transaction. */
+/* Otherwise, rollback the transaction. */
+if( $stmt1 && $stmt2 )
+{
+ sqlsrv_commit( $conn );
+ echo "Transaction was committed.\n";
+}
+else
+{
+ sqlsrv_rollback( $conn );
+ echo "Transaction was rolled back.\n";
+}
+
+/* Revert the changes */
+$d_sql = "DELETE FROM Sales.SalesOrderDetail WHERE SalesOrderID=43659 AND OrderQty=5 AND ProductID=709 AND SpecialOfferID=1 AND Unitprice=5.70";
+$stmt3 = sqlsrv_query($conn, $d_sql);
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt1);
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_free_stmt($stmt3);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Transaction was committed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_configure.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_configure.phpt
new file mode 100644
index 00000000..3e7aa37f
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_configure.phpt
@@ -0,0 +1,69 @@
+--TEST--
+disables the default error-handling behaviour using configure
+--SKIPIF--
+
+?>
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* The Transact-SQL PRINT statement can be used to return
+informational or warning messages*/
+$tsql = "PRINT 'The PRINT statement can be used ";
+$tsql .= "to return user-defined warnings.'";
+
+/* Execute the query and print any errors. */
+$stmt1 = sqlsrv_query( $conn, $tsql);
+if($stmt1 === false)
+{
+ echo "By default, warnings are treated as errors:\n";
+ /* Dump errors in the error collection. */
+ print_r(sqlsrv_errors(SQLSRV_ERR_ERRORS));
+}
+
+/* Disable warnings as errors behavior. */
+sqlsrv_configure("WarningsReturnAsErrors", 0);
+
+/* Execute the same query and print any errors. */
+$stmt2 = sqlsrv_query( $conn, $tsql);
+if($stmt2 === false)
+{
+ /* Dump errors in the error collection. */
+ /* Since the warning generated by the query will not be treated as
+ an error, this block of code will not be executed. */
+ print_r(sqlsrv_errors(SQLSRV_ERR_ERRORS));
+}
+else
+{
+ echo "After calling ";
+ echo "sqlsrv_configure('WarningsReturnAsErrors', 0), ";
+ echo "warnings are not treated as errors.";
+}
+
+/*Close the connection. */
+sqlsrv_close($conn);
+?>
+--EXPECTREGEX--
+By default, warnings are treated as errors:
+Array
+\(
+ \[0\] => Array
+ \(
+ \[0\] => 01000
+ \[SQLSTATE\] => 01000
+ \[1\] => 0
+ \[code\] => 0
+ \[2\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]The PRINT statement can be used to return user-defined warnings.
+ \[message\] => \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]The PRINT statement can be used to return user-defined warnings.
+ \)
+
+\)
+After calling sqlsrv_configure\('WarningsReturnAsErrors', 0\), warnings are not treated as errors.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_configure_2.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_configure_2.phpt
new file mode 100644
index 00000000..de78bcff
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_configure_2.phpt
@@ -0,0 +1,178 @@
+--TEST--
+disables the default error-handling behaviour using configure and returns warnings
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+
+/* If the connection fails, display errors and exit the script. */
+if( $conn === false )
+{
+ DisplayErrors();
+ die;
+}
+/* Display any warnings. */
+DisplayWarnings();
+
+/* Revert previous updates */
+$r_sql="UPDATE HumanResources.Employee SET VacationHours=61 WHERE BusinessEntityID=7;
+ UPDATE HumanResources.Employee SET VacationHours=62 WHERE BusinessEntityID=8;
+ UPDATE HumanResources.Employee SET VacationHours=63 WHERE BusinessEntityID=9;
+ UPDATE HumanResources.Employee SET VacationHours=7 WHERE BusinessEntityID=11";
+$stmt4=sqlsrv_query($conn, $r_sql);
+sqlsrv_free_stmt( $stmt4 );
+
+/* Drop the stored procedure if it already exists. */
+$tsql1 = "IF OBJECT_ID('SubtractVacationHours', 'P') IS NOT NULL
+ DROP PROCEDURE SubtractVacationHours";
+$stmt1 = sqlsrv_query($conn, $tsql1);
+
+/* If the query fails, display errors and exit the script. */
+if( $stmt1 === false)
+{
+ DisplayErrors();
+ die;
+}
+/* Display any warnings. */
+DisplayWarnings();
+
+/* Free the statement resources. */
+sqlsrv_free_stmt( $stmt1 );
+
+/* Create the stored procedure. */
+$tsql2 = "CREATE PROCEDURE SubtractVacationHours
+ @BusinessEntityId int,
+ @VacationHours smallint OUTPUT
+ AS
+ UPDATE HumanResources.Employee
+ SET VacationHours = VacationHours - @VacationHours
+ WHERE BusinessEntityId = @BusinessEntityId;
+ SET @VacationHours = (SELECT VacationHours
+ FROM HumanResources.Employee
+ WHERE BusinessEntityId = @BusinessEntityId);
+ IF @VacationHours < 0
+ BEGIN
+ PRINT 'WARNING: Vacation hours are now less than zero.'
+ END;";
+$stmt2 = sqlsrv_query( $conn, $tsql2 );
+
+/* If the query fails, display errors and exit the script. */
+if( $stmt2 === false)
+{
+ DisplayErrors();
+ die;
+}
+/* Display any warnings. */
+DisplayWarnings();
+
+/* Free the statement resources. */
+sqlsrv_free_stmt( $stmt2 );
+
+/* Set up the array that maps employee ID to used vacation hours. */
+$emp_hrs = array (7=>4, 8=>5, 9=>8, 11=>50);
+
+/* Initialize variables that will be used as parameters. */
+$businessEntityId = 0;
+$vacationHrs = 0;
+
+/* Set up the parameter array. */
+$params = array(
+ array(&$businessEntityId, SQLSRV_PARAM_IN),
+ array(&$vacationHrs, SQLSRV_PARAM_INOUT)
+ );
+
+/* Define and prepare the query to substract used vacation hours. */
+$tsql3 = "{call SubtractVacationHours(?, ?)}";
+$stmt3 = sqlsrv_prepare($conn, $tsql3, $params);
+
+/* If the statement preparation fails, display errors and exit the script. */
+if( $stmt3 === false)
+{
+ DisplayErrors();
+ die;
+}
+/* Display any warnings. */
+DisplayWarnings();
+
+/* Loop through the employee=>vacation hours array. Update parameter
+ values before statement execution. */
+foreach(array_keys($emp_hrs) as $businessEntityId)
+{
+ $vacationHrs = $emp_hrs[$businessEntityId];
+ /* Execute the query. If it fails, display the errors. */
+ if( sqlsrv_execute($stmt3) === false)
+ {
+ DisplayErrors();
+ die;
+ }
+ /* Display any warnings. */
+ DisplayWarnings();
+
+ /*Move to the next result returned by the stored procedure. */
+ if( sqlsrv_next_result($stmt3) === false)
+ {
+ DisplayErrors();
+ die;
+ }
+ /* Display any warnings. */
+ DisplayWarnings();
+
+ /* Display updated vacation hours. */
+ echo "BusinessEntityId $businessEntityId has $vacationHrs ";
+ echo "remaining vacation hours.\n";
+}
+
+/* Free the statement*/
+sqlsrv_free_stmt( $stmt3 );
+
+/* close connection resources. */
+sqlsrv_close( $conn );
+
+/* ------------- Error Handling Functions --------------*/
+function DisplayErrors()
+{
+ $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
+ foreach( $errors as $error )
+ {
+ echo "Error: ".$error['message']."\n";
+ }
+}
+
+function DisplayWarnings()
+{
+ $warnings = sqlsrv_errors(SQLSRV_ERR_WARNINGS);
+ if(!is_null($warnings))
+ {
+ foreach( $warnings as $warning )
+ {
+ $message = $warning['message'];
+ // Skips the message with 'unixODBC' (an unnecessary duplicate message in some platform)
+ if (! stripos($message, 'unixODBC') )
+ echo "Warning: $message\n";
+ }
+ }
+}
+?>
+--EXPECTREGEX--
+Warning: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]Changed database context to 'AdventureWorks2014'.
+Warning: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]Changed language setting to us_english.
+BusinessEntityId 7 has 57 remaining vacation hours.
+BusinessEntityId 8 has 57 remaining vacation hours.
+BusinessEntityId 9 has 55 remaining vacation hours.
+Error: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]The UPDATE statement conflicted with the CHECK constraint "CK_Employee_VacationHours". The conflict occurred in database "AdventureWorks2014", table "HumanResources.Employee", column 'VacationHours'.
+Error: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]The statement has been terminated.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_connect.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_connect.phpt
new file mode 100644
index 00000000..6e8baef5
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_connect.phpt
@@ -0,0 +1,39 @@
+--TEST--
+creates and opens a connection using Windows Authentication.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+
+if( $conn )
+{
+ echo "Connection established.\n";
+}
+else
+{
+ echo "Connection could not be established.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Prepare and execute the query. */
+$tsql = "SELECT OrderQty, UnitPrice FROM Sales.SalesOrderDetail";
+$stmt = sqlsrv_prepare( $conn, $tsql);
+if( $stmt === false )
+{
+ echo "Error in statement preparation.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+if( sqlsrv_execute( $stmt ) === false)
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Close the connection. */
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Connection established.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_connect_MARS.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_connect_MARS.phpt
new file mode 100644
index 00000000..9b357732
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_connect_MARS.phpt
@@ -0,0 +1,29 @@
+--TEST--
+disables MARS support.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+
+/* Connect to the local server using Windows Authentication and
+specify the AdventureWorks database as the database in use. */
+$serverName = "sql-2k14-sp1-1.galaxy.ad";
+$connectionInfo = array( "Database"=>"AdventureWorks2014", "UID"=>"sa", "PWD"=>"Moonshine4me", 'MultipleActiveResultSets'=> false);
+$conn = sqlsrv_connect( $serverName, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+else
+{
+ echo "Connection established.\n";
+}
+
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Connection established.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_connect_returnDateAsStrings.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_connect_returnDateAsStrings.phpt
new file mode 100644
index 00000000..8d7900de
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_connect_returnDateAsStrings.phpt
@@ -0,0 +1,23 @@
+--TEST--
+specifies to retrieve date and time types as string when connecting.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+else
+{
+ echo "Connection established.\n";
+}
+
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Connection established.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_connect_returnDatesAsStrings_utf8.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_connect_returnDatesAsStrings_utf8.phpt
new file mode 100644
index 00000000..7bf2a839
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_connect_returnDatesAsStrings_utf8.phpt
@@ -0,0 +1,38 @@
+--TEST--
+retrieves dates as string by specifying UTF-8 and ReturnDatesAsStrings when connecting.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd", 'ReturnDatesAsStrings'=> true, "CharacterSet" => 'utf-8');
+$conn = sqlsrv_connect( $server, $connectionInfo);
+
+if( $conn === false ) {
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$tsql = "SELECT VersionDate FROM AWBuildVersion";
+
+$stmt = sqlsrv_query( $conn, $tsql);
+
+if ( $stmt === false ) {
+ echo "Error in statement preparation/execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+sqlsrv_fetch( $stmt );
+
+// retrieve date as string
+$date = sqlsrv_get_field( $stmt, 0 );
+
+if ( $date === false ) {
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+echo $date;
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+2014-02-20 04:26:00.000
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_connect_utf8.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_connect_utf8.phpt
new file mode 100644
index 00000000..d6adce7c
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_connect_utf8.phpt
@@ -0,0 +1,83 @@
+--TEST--
+retrieves UTF-8 encoded data by specifying the UTF-8 character set when making the connection
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd", "CharacterSet" => 'UTF-8');
+$conn = sqlsrv_connect( $server, $connectionInfo);
+
+if ( $conn === false ) {
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+// Set up the Transact-SQL query.
+//
+$tsql1 = "UPDATE Production.ProductReview
+ SET Comments = ?
+ WHERE ProductReviewID = ?";
+
+// Set the parameter values and put them in an array. Note that
+// $comments is converted to UTF-8 encoding with the PHP function
+// utf8_encode to simulate an application that uses UTF-8 encoded data.
+//
+$reviewID = 3;
+
+$comments = utf8_encode("testing 1, 2, 3, 4. Testing.");
+$params1 = array(
+ array( $comments, null ),
+ array( $reviewID, null )
+ );
+
+// Execute the query.
+//
+$stmt1 = sqlsrv_query($conn, $tsql1, $params1);
+
+if ( $stmt1 === false ) {
+ echo "Error in statement execution.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+else {
+ echo "The update was successfully executed.
";
+}
+
+// Retrieve the newly updated data.
+//
+$tsql2 = "SELECT Comments
+ FROM Production.ProductReview
+ WHERE ProductReviewID = ?";
+
+// Set up the parameter array.
+//
+$params2 = array($reviewID);
+
+// Execute the query.
+//
+$stmt2 = sqlsrv_query($conn, $tsql2, $params2);
+if ( $stmt2 === false ) {
+ echo "Error in statement execution.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+// Retrieve and display the data.
+//
+if ( sqlsrv_fetch($stmt2) ) {
+ echo "Comments: ";
+ $data = sqlsrv_get_field( $stmt2, 0 );
+ echo $data."
";
+}
+else {
+ echo "Error in fetching data.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+// Free statement and connection resources.
+//
+sqlsrv_free_stmt( $stmt1 );
+sqlsrv_free_stmt( $stmt2 );
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+The update was successfully executed.
Comments: testing 1, 2, 3, 4. Testing.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_date_format.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_date_format.phpt
new file mode 100644
index 00000000..a0013c49
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_date_format.phpt
@@ -0,0 +1,40 @@
+--TEST--
+retrieve date as PHP type with ReturnDatesAsStrings off by default.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+
+if( $conn === false ) {
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$tsql = "SELECT VersionDate FROM AWBuildVersion";
+
+$stmt = sqlsrv_query( $conn, $tsql);
+
+if ( $stmt === false ) {
+ echo "Error in statement preparation/execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+sqlsrv_fetch( $stmt );
+
+// retrieve date as string
+$date = sqlsrv_get_field( $stmt, 0 );
+
+if ( $date === false ) {
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+$date_string = date_format( $date, 'jS, F Y' );
+echo "Date = $date_string\n";
+
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Date = 20th, February 2014
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_errors.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_errors.phpt
new file mode 100644
index 00000000..4c296046
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_errors.phpt
@@ -0,0 +1,39 @@
+--TEST--
+displays errors that occur during a failed statement execution
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up a query to select an invalid column name. */
+$tsql = "SELECT InvalidColumnName FROM Sales.SalesOrderDetail";
+
+/* Attempt execution. */
+/* Execution will fail because of the invalid column name. */
+$stmt = sqlsrv_query( $conn, $tsql);
+if( $stmt === false )
+{
+ if( ($errors = sqlsrv_errors() ) != null)
+ {
+ foreach( $errors as $error)
+ {
+ echo "SQLSTATE: ".$error[ 'SQLSTATE']."
";
+ echo "code: ".$error[ 'code']."
";
+ echo "message: ".$error[ 'message']."
";
+ }
+ }
+}
+
+/* Free connection resources */
+sqlsrv_close( $conn);
+?>
+--EXPECTREGEX--
+SQLSTATE: 42S22
code: 207
message: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]Invalid column name 'InvalidColumnName'.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_execute.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_execute.phpt
new file mode 100644
index 00000000..a44cd93a
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_execute.phpt
@@ -0,0 +1,63 @@
+--TEST--
+executes a statement that updates a field.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false)
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+
+/* Set up the Transact-SQL query. */
+$tsql = "UPDATE Sales.SalesOrderDetail
+ SET OrderQty = (?)
+ WHERE SalesOrderDetailID = (?)";
+
+/* Set up the parameters array. Parameters correspond, in order, to
+question marks in $tsql. */
+$params = array(5, 10);
+
+
+
+/* Create the statement. */
+$stmt = sqlsrv_prepare( $conn, $tsql, $params);
+if( $stmt )
+{
+ echo "Statement prepared.\n";
+}
+else
+{
+ echo "Error in preparing statement.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+
+/* Execute the statement. Display any errors that occur. */
+if( sqlsrv_execute( $stmt))
+{
+ echo "Statement executed.\n";
+}
+else
+{
+ echo "Error in executing statement.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/*revert the update */
+$r_sql = "UPDATE Sales.SalesOrderDetail SET OrderQty=6 WHERE SalesOrderDetailID=10";
+$stmt2 = sqlsrv_query($conn, $r_sql);
+
+/* Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_free_stmt($stmt2);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Statement prepared.
+Statement executed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_execute_datetime.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_execute_datetime.phpt
new file mode 100644
index 00000000..caac6ede
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_execute_datetime.phpt
@@ -0,0 +1,134 @@
+--TEST--
+execute with datetime type in bind parameters.
+--SKIPIF--
+
+?>
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false)
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Prepare with datetime type in parameter. */
+$tsql = "SELECT * FROM Sales.CurrencyRate WHERE CurrencyRateDate=(?)";
+
+//Pass in parameters directly
+$params = array( '2014-05-31 00:00:00.000');
+$stmt = sqlsrv_prepare( $conn, $tsql, $params);
+
+//Pass in parameters through reference
+$crd='2014-05-31 00:00:00.000';
+$stmt = sqlsrv_prepare( $conn, $tsql, array(&$crd));
+
+echo "Datetime Type, Select Query:
";
+if( $stmt )
+{
+ echo "Statement prepared.
";
+}
+else
+{
+ echo "Error in preparing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute the statement. Display any errors that occur. */
+if( sqlsrv_execute( $stmt))
+{
+ echo "Statement executed.
";
+}
+else
+{
+ echo "Error in executing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC))
+{
+ echo $row['CurrencyRateID'].", ".date_format($row['CurrencyRateDate'], 'Y-m-d H:i:s')."
";
+}
+echo "
";
+
+sqlsrv_free_stmt( $stmt);
+
+
+/* Prepare with datetime type in parameter. */
+$tsql = "UPDATE Sales.CurrencyRate SET FromCurrencyCode='CAD' WHERE CurrencyRateDate=(?)";
+
+//Pass in parameters directly
+$params = array( '2011-08-15 00:00:00.000');
+$stmt = sqlsrv_prepare( $conn, $tsql, $params);
+
+//Pass in parameters through reference
+$crd='2011-08-15 00:00:00.000';
+$stmt = sqlsrv_prepare( $conn, $tsql, array(&$crd));
+
+echo "Datetime Type, Update Query:
";
+if( $stmt )
+{
+ echo "Statement prepared.
";
+}
+else
+{
+ echo "Error in preparing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute the statement. Display any errors that occur. */
+if( sqlsrv_execute( $stmt))
+{
+ echo "Statement executed.
";
+}
+else
+{
+ echo "Error in executing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+echo sqlsrv_rows_affected( $stmt)." rows affected.
";
+sqlsrv_free_stmt( $stmt);
+
+
+/* Revert the Update*/
+$tsql = "UPDATE Sales.CurrencyRate SET FromCurrencyCode='USD' WHERE CurrencyRateDate=(?)";
+
+//Pass in parameters directly
+$params = array( '2011-08-15 00:00:00.000');
+$stmt = sqlsrv_prepare( $conn, $tsql, $params);
+
+//Pass in parameters through reference
+$crd='2011-08-15 00:00:00.000';
+$stmt = sqlsrv_prepare( $conn, $tsql, array(&$crd));
+
+echo "Datetime Type, Update Query:
";
+if( $stmt )
+{
+ echo "Statement prepared.
";
+}
+else
+{
+ echo "Error in preparing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute the statement. Display any errors that occur. */
+if( sqlsrv_execute( $stmt))
+{
+ echo "Statement executed.
";
+}
+else
+{
+ echo "Error in executing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+echo sqlsrv_rows_affected( $stmt)." rows affected.
";
+
+
+/* Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Datetime Type, Select Query:
Statement prepared.
Statement executed.
12425, 2014-05-31 00:00:00
12426, 2014-05-31 00:00:00
12427, 2014-05-31 00:00:00
12428, 2014-05-31 00:00:00
12429, 2014-05-31 00:00:00
12430, 2014-05-31 00:00:00
12431, 2014-05-31 00:00:00
12432, 2014-05-31 00:00:00
12433, 2014-05-31 00:00:00
12434, 2014-05-31 00:00:00
13532, 2014-05-31 00:00:00
12435, 2014-05-31 00:00:00
Datetime Type, Update Query:
Statement prepared.
Statement executed.
14 rows affected.
Datetime Type, Update Query:
Statement prepared.
Statement executed.
14 rows affected.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_execute_string.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_execute_string.phpt
new file mode 100644
index 00000000..c9effa18
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_execute_string.phpt
@@ -0,0 +1,152 @@
+--TEST--
+execute with string type in bind parameters.
+--SKIPIF--
+
+?>
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false)
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Prepare with string type in parameter. */
+$tsql = "SELECT * FROM Sales.SalesOrderDetail WHERE CarrierTrackingNumber=(?)";
+
+//Pass in parameters directly
+$params = array( '8650-4A20-B1');
+$stmt = sqlsrv_prepare( $conn, $tsql, $params);
+
+//Pass in parameters through reference
+//$ctn="8650-4A20-B1";
+//$stmt = sqlsrv_prepare( $conn, $tsql, array(&$ctn));
+
+echo "String Type, Select Query:
";
+if( $stmt )
+{
+ echo "Statement prepared.
";
+}
+else
+{
+ echo "Error in preparing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute the statement. Display any errors that occur. */
+if( sqlsrv_execute( $stmt))
+{
+ echo "Statement executed.
";
+}
+else
+{
+ echo "Error in executing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$soID = 0;
+$row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC);
+while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC))
+{
+ echo $row['SalesOrderID'].", ".$row['CarrierTrackingNumber']."
";
+ $soID = $row['SalesOrderID'];
+}
+echo "
";
+
+sqlsrv_free_stmt( $stmt);
+
+/* Prepare with string type in parameter. */
+$tsql = "UPDATE Sales.SalesOrderDetail
+ SET OrderQty=(?)
+ WHERE CarrierTrackingNumber=(?)";
+
+// RevisionNumber in SalesOrderHeader is subject to a trigger incrementing it whenever
+// changes are made to SalesOrderDetail. Since RevisonNumber is a tinyint, it can
+// overflow quickly if this test is often run. So we change it directly here first
+// before it can overflow.
+$stmt0 = sqlsrv_query( $conn, "UPDATE Sales.SalesOrderHeader SET RevisionNumber = 2 WHERE SalesOrderID = $soID" );
+
+//Pass in parameters directly
+$params = array(5, '8650-4A20-B1');
+$stmt = sqlsrv_prepare( $conn, $tsql, $params);
+
+//Pass in parameters through reference
+//$oq=5;
+//$ctn="8650-4A20-B1";
+//$stmt = sqlsrv_prepare( $conn, $tsql, array(&$oq, &$ctn));
+
+echo "String Type, Update Query:
";
+if( $stmt )
+{
+ echo "Statement prepared.
";
+}
+else
+{
+ echo "Error in preparing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute the statement. Display any errors that occur. */
+
+if( sqlsrv_execute( $stmt))
+{
+ echo "Statement executed.
";
+}
+else
+{
+ echo "Error in executing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+echo sqlsrv_rows_affected( $stmt)." rows affected.
";
+sqlsrv_free_stmt( $stmt);
+
+
+/* Revert back the Update. */
+$tsql = "UPDATE Sales.SalesOrderDetail
+ SET OrderQty=(?)
+ WHERE CarrierTrackingNumber=(?)";
+
+//Pass in parameters directly
+$params = array(1, '8650-4A20-B1');
+$stmt = sqlsrv_prepare( $conn, $tsql, $params);
+
+//Pass in parameters through reference
+//$oq=1;
+//$ctn="8650-4A20-B1";
+//$stmt = sqlsrv_prepare( $conn, $tsql, array(&$oq, &$ctn));
+
+echo "String Type, Update Query:
";
+if( $stmt )
+{
+ echo "Statement prepared.
";
+}
+else
+{
+ echo "Error in preparing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute the statement. Display any errors that occur. */
+
+if( sqlsrv_execute( $stmt))
+{
+ echo "Statement executed.
";
+}
+else
+{
+ echo "Error in executing statement.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+echo sqlsrv_rows_affected( $stmt)." rows affected.
";
+sqlsrv_free_stmt( $stmt);
+
+
+/* Free the statement and connection resources. */
+//sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+String Type, Select Query:
Statement prepared.
Statement executed.
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
51108, 8650-4A20-B1
String Type, Update Query:
Statement prepared.
Statement executed.
52 rows affected.
String Type, Update Query:
Statement prepared.
Statement executed.
52 rows affected.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_fetch.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_fetch.phpt
new file mode 100644
index 00000000..a5162be1
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_fetch.phpt
@@ -0,0 +1,63 @@
+--TEST--
+retrieve a row of data.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up and execute the query. Note that both ReviewerName and
+Comments are of SQL Server type nvarchar. */
+$tsql = "SELECT ReviewerName, Comments
+ FROM Production.ProductReview
+ WHERE ProductReviewID=1";
+$stmt = sqlsrv_query( $conn, $tsql);
+if( $stmt === false )
+{
+ echo "Error in statement preparation/execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Make the first row of the result set available for reading. */
+if( sqlsrv_fetch( $stmt ) === false)
+{
+ echo "Error in retrieving row.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Note: Fields must be accessed in order.
+Get the first field of the row. Note that no return type is
+specified. Data will be returned as a string, the default for
+a field of type nvarchar.*/
+$name = sqlsrv_get_field( $stmt, 0);
+echo "$name: ";
+
+/*Get the second field of the row as a stream.
+Because the default return type for a nvarchar field is a
+string, the return type must be specified as a stream. */
+$stream = sqlsrv_get_field( $stmt, 1,
+ SQLSRV_PHPTYPE_STREAM( SQLSRV_ENC_CHAR));
+while( !feof( $stream ))
+{
+ $str = fread( $stream, 10000);
+ echo $str;
+}
+
+/* Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+
+?>
+--EXPECT--
+John Smith: I can't believe I'm singing the praises of a pair of socks, but I just came back from a grueling
+3-day ride and these socks really helped make the trip a blast. They're lightweight yet really cushioned my feet all day.
+The reinforced toe is nearly bullet-proof and I didn't experience any problems with rubbing or blisters like I have with
+other brands. I know it sounds silly, but it's always the little stuff (like comfortable feet) that makes or breaks a long trip.
+I won't go on another trip without them!
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_fetch_array.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_fetch_array.phpt
new file mode 100644
index 00000000..b355f74a
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_fetch_array.phpt
@@ -0,0 +1,39 @@
+--TEST--
+retrieves each row of a result set as an associative array.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up and execute the query. */
+$tsql = "SELECT FirstName, LastName
+ FROM Person.Person
+ WHERE LastName='Alan'";
+$stmt = sqlsrv_query( $conn, $tsql);
+if( $stmt === false)
+{
+ echo "Error in query preparation/execution.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Retrieve each row as an associative array and display the results.*/
+while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC))
+{
+ echo $row['LastName'].", ".$row['FirstName']."
";
+}
+
+/* Free statement and connection resources. */
+
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Alan, Alisha
Alan, Bob
Alan, Cheryl
Alan, Jamie
Alan, Kari
Alan, Kelvin
Alan, Meghan
Alan, Stanley
Alan, Xavier
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_fetch_array_2.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_fetch_array_2.phpt
new file mode 100644
index 00000000..4d803987
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_fetch_array_2.phpt
@@ -0,0 +1,61 @@
+--TEST--
+retrieves each row of a result set as a numerically indexed array.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Define the query. */
+$tsql = "SELECT ProductID,
+ UnitPrice,
+ StockedQty
+ FROM Purchasing.PurchaseOrderDetail
+ WHERE StockedQty < 3
+ AND DueDate='2014-01-29'";
+
+/* Execute the query. */
+$stmt = sqlsrv_query( $conn, $tsql);
+if ( $stmt )
+{
+ echo "Statement executed.\n";
+}
+else
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Iterate through the result set printing a row of data upon each
+iteration.*/
+while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC))
+{
+ echo "ProdID: ".$row[0]."\n";
+ echo "UnitPrice: ".$row[1]."\n";
+ echo "StockedQty: ".$row[2]."\n";
+ echo "-----------------\n";
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Statement executed.
+ProdID: 931
+UnitPrice: 34.3455
+StockedQty: .00
+-----------------
+ProdID: 932
+UnitPrice: 39.2385
+StockedQty: .00
+-----------------
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_fetch_object.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_fetch_object.phpt
new file mode 100644
index 00000000..77cc759e
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_fetch_object.phpt
@@ -0,0 +1,39 @@
+--TEST--
+retrieves each row of a result set as a PHP object
+--SKIPIF--
+
+?>
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up and execute the query. */
+$tsql = "SELECT FirstName, LastName
+ FROM Person.Person
+ WHERE LastName='Alan'";
+$stmt = sqlsrv_query( $conn, $tsql);
+if( $stmt === false )
+{
+ echo "Error in query preparation/execution.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Retrieve each row as a PHP object and display the results.*/
+while( $obj = sqlsrv_fetch_object( $stmt))
+{
+ echo $obj->LastName.", ".$obj->FirstName."
";
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Alan, Alisha
Alan, Bob
Alan, Cheryl
Alan, Jamie
Alan, Kari
Alan, Kelvin
Alan, Meghan
Alan, Stanley
Alan, Xavier
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_fetch_object_2.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_fetch_object_2.phpt
new file mode 100644
index 00000000..54177f37
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_fetch_object_2.phpt
@@ -0,0 +1,108 @@
+--TEST--
+retrieves each row of a result set as an instance of the Product class defined in the script.
+--SKIPIF--
+
+--FILE--
+objID = $ID;
+ }
+ public $objID;
+ public $name;
+ public $StockedQty;
+ public $SafetyStockLevel;
+ private $UnitPrice;
+ function getPrice()
+ {
+ return $this->UnitPrice;
+ }
+}
+
+/* Connect to the local server using Windows Authentication, and
+specify the AdventureWorks database as the database in use. */
+require('connect.inc');
+$connectionInfo = array( "Database"=>"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Define the query. */
+$tsql = "SELECT Name,
+ SafetyStockLevel,
+ StockedQty,
+ UnitPrice,
+ Color
+ FROM Purchasing.PurchaseOrderDetail AS pdo
+ JOIN Production.Product AS p
+ ON pdo.ProductID = p.ProductID
+ WHERE pdo.StockedQty < ?
+ AND pdo.DueDate= ?";
+
+/* Set the parameter values. */
+$params = array(3, '2014-01-29');
+
+/* Execute the query. */
+$stmt = sqlsrv_query( $conn, $tsql, $params);
+if ( $stmt )
+{
+ echo "Statement executed.\n";
+}
+else
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Iterate through the result set, printing a row of data upon each
+ iteration. Note the following:
+ 1) $product is an instance of the Product class.
+ 2) The $ctorParams parameter is required in the call to
+ sqlsrv_fetch_object, because the Product class constructor is
+ explicity defined and requires parameter values.
+ 3) The "Name" property is added to the $product instance because
+ the existing "name" property does not match.
+ 4) The "Color" property is added to the $product instance
+ because there is no matching property.
+ 5) The private property "UnitPrice" is populated with the value
+ of the "UnitPrice" field.*/
+$i=0; //Used as the $objID in the Product class constructor.
+while( $product = sqlsrv_fetch_object( $stmt, "Product", array($i)))
+{
+ echo "Object ID: ".$product->objID."\n";
+ echo "Product Name: ".$product->Name."\n";
+ echo "Stocked Qty: ".$product->StockedQty."\n";
+ echo "Safety Stock Level: ".$product->SafetyStockLevel."\n";
+ echo "Product Color: ".$product->Color."\n";
+ echo "Unit Price: ".$product->getPrice()."\n";
+ echo "-----------------\n";
+ $i++;
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Statement executed.
+Object ID:
+Product Name: LL Road Tire
+Stocked Qty: .00
+Safety Stock Level: 500
+Product Color:
+Unit Price: 34.3455
+-----------------
+Object ID:
+Product Name: ML Road Tire
+Stocked Qty: .00
+Safety Stock Level: 500
+Product Color:
+Unit Price: 39.2385
+-----------------
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_field_metadata.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_field_metadata.phpt
new file mode 100644
index 00000000..5e596774
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_field_metadata.phpt
@@ -0,0 +1,38 @@
+--TEST--
+creates a statement resource then retrieves and displays the field metadata
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Prepare the statement. */
+$tsql = "SELECT ReviewerName, Comments FROM Production.ProductReview";
+$stmt = sqlsrv_prepare( $conn, $tsql);
+
+/* Get and display field metadata. */
+foreach( sqlsrv_field_metadata( $stmt) as $fieldMetadata)
+{
+ foreach( $fieldMetadata as $name => $value)
+ {
+ echo "$name: $value
";
+ }
+ echo "
";
+}
+
+/* Note: sqlsrv_field_metadata can be called on any statement
+resource, pre- or post-execution. */
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Name: ReviewerName
Type: -9
Size: 50
Precision:
Scale:
Nullable: 0
Name: Comments
Type: -9
Size: 3850
Precision:
Scale:
Nullable: 1
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_free_stmt.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_free_stmt.phpt
new file mode 100644
index 00000000..db66ad54
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_free_stmt.phpt
@@ -0,0 +1,42 @@
+--TEST--
+creates a statement resource, executes a simple query, and free all resources associated with the statement
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$stmt = sqlsrv_query( $conn, "SELECT * FROM Person.Person");
+if( $stmt )
+{
+ echo "Statement executed.
";
+}
+else
+{
+ echo "Query could not be executed.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Get and display field metadata. */
+foreach( sqlsrv_field_metadata( $stmt) as $fieldMetadata)
+{
+ foreach( $fieldMetadata as $name => $value)
+ {
+ echo "$name: $value
";
+ }
+ echo "
";
+}
+
+/* Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Statement executed.
Name: BusinessEntityID
Type: 4
Size:
Precision: 10
Scale:
Nullable: 0
Name: PersonType
Type: -8
Size: 2
Precision:
Scale:
Nullable: 0
Name: NameStyle
Type: -7
Size:
Precision: 1
Scale:
Nullable: 0
Name: Title
Type: -9
Size: 8
Precision:
Scale:
Nullable: 1
Name: FirstName
Type: -9
Size: 50
Precision:
Scale:
Nullable: 0
Name: MiddleName
Type: -9
Size: 50
Precision:
Scale:
Nullable: 1
Name: LastName
Type: -9
Size: 50
Precision:
Scale:
Nullable: 0
Name: Suffix
Type: -9
Size: 10
Precision:
Scale:
Nullable: 1
Name: EmailPromotion
Type: 4
Size:
Precision: 10
Scale:
Nullable: 0
Name: AdditionalContactInfo
Type: -152
Size: 0
Precision:
Scale:
Nullable: 1
Name: Demographics
Type: -152
Size: 0
Precision:
Scale:
Nullable: 1
Name: rowguid
Type: -11
Size: 36
Precision:
Scale:
Nullable: 0
Name: ModifiedDate
Type: 93
Size:
Precision: 23
Scale: 3
Nullable: 0
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_get_field.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_get_field.phpt
new file mode 100644
index 00000000..c663a2c1
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_get_field.phpt
@@ -0,0 +1,63 @@
+--TEST--
+retrieves a row of data
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up and execute the query. Note that both ReviewerName and
+Comments are of the SQL Server nvarchar type. */
+$tsql = "SELECT ReviewerName, Comments
+ FROM Production.ProductReview
+ WHERE ProductReviewID=1";
+$stmt = sqlsrv_query( $conn, $tsql);
+if( $stmt === false )
+{
+ echo "Error in statement preparation/execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Make the first row of the result set available for reading. */
+if( sqlsrv_fetch( $stmt ) === false )
+{
+ echo "Error in retrieving row.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Note: Fields must be accessed in order.
+Get the first field of the row. Note that no return type is
+specified. Data will be returned as a string, the default for
+a field of type nvarchar.*/
+$name = sqlsrv_get_field( $stmt, 0);
+echo "$name: ";
+
+/*Get the second field of the row as a stream.
+Because the default return type for a nvarchar field is a
+string, the return type must be specified as a stream. */
+$stream = sqlsrv_get_field( $stmt, 1,
+ SQLSRV_PHPTYPE_STREAM( SQLSRV_ENC_CHAR));
+while( !feof( $stream))
+{
+ $str = fread( $stream, 10000);
+ echo $str;
+}
+
+
+/* Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+John Smith: I can't believe I'm singing the praises of a pair of socks, but I just came back from a grueling
+3-day ride and these socks really helped make the trip a blast. They're lightweight yet really cushioned my feet all day.
+The reinforced toe is nearly bullet-proof and I didn't experience any problems with rubbing or blisters like I have with
+other brands. I know it sounds silly, but it's always the little stuff (like comfortable feet) that makes or breaks a long trip.
+I won't go on another trip without them!
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream.phpt
new file mode 100644
index 00000000..a2e1b5a9
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream.phpt
@@ -0,0 +1,73 @@
+--TEST--
+retrieves datatime as string and nvarchar as stream.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/*revert inserts from previous tests*/
+$d_sql = "DELETE FROM Production.ProductReview WHERE EmailAddress!='john@fourthcoffee.com' AND ProductID=709";
+$stmt4 = sqlsrv_query($conn, $d_sql);
+
+/* Set up and execute the query. Note that both ReviewerName and
+ Comments are of the SQL Server nvarchar type. */
+ $tsql = "SELECT ReviewerName,
+ ReviewDate,
+ Rating,
+ Comments
+ FROM Production.ProductReview
+ WHERE ProductID = ?
+ ORDER BY ReviewDate DESC";
+
+/* Set the parameter value. */
+$productID = 709;
+$params = array( $productID);
+
+/* Execute the query. */
+$stmt = sqlsrv_query($conn, $tsql, $params);
+if( $stmt === false )
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Retrieve and display the data. The first and third fields are
+retrieved according to their default types, strings. The second field
+is retrieved as a string with 8-bit character encoding. The fourth
+field is retrieved as a stream with 8-bit character encoding.*/
+while ( sqlsrv_fetch( $stmt))
+{
+ echo "Name: ".sqlsrv_get_field( $stmt, 0 )."\n";
+ echo "Date: ".sqlsrv_get_field( $stmt, 1,
+ SQLSRV_PHPTYPE_STRING( SQLSRV_ENC_CHAR))."\n";
+ echo "Rating: ".sqlsrv_get_field( $stmt, 2 )."\n";
+ echo "Comments: ";
+ $comments = sqlsrv_get_field( $stmt, 3,
+ SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_CHAR));
+ fpassthru( $comments);
+ echo "\n";
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close($conn);
+?>
+--EXPECT--
+Name: John Smith
+Date: 2013-09-18 00:00:00.000
+Rating: 5
+Comments: I can't believe I'm singing the praises of a pair of socks, but I just came back from a grueling
+3-day ride and these socks really helped make the trip a blast. They're lightweight yet really cushioned my feet all day.
+The reinforced toe is nearly bullet-proof and I didn't experience any problems with rubbing or blisters like I have with
+other brands. I know it sounds silly, but it's always the little stuff (like comfortable feet) that makes or breaks a long trip.
+I won't go on another trip without them!
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream_binary.php b/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream_binary.php
new file mode 100644
index 00000000..751229f1
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream_binary.php
@@ -0,0 +1,48 @@
+"AdventureWorks2014", "UID"=>"sa", "PWD"=>"Moonshine4me");
+$conn = sqlsrv_connect( $serverName, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up the Transact-SQL query. */
+$tsql = "SELECT LargePhoto
+ FROM Production.ProductPhoto
+ WHERE ProductPhotoID = ?";
+
+/* Set the parameter values and put them in an array. */
+$productPhotoID = 70;
+$params = array( $productPhotoID);
+
+/* Execute the query. */
+$stmt = sqlsrv_query($conn, $tsql, $params);
+if( $stmt === false )
+{
+ echo "Error in statement execution.";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Retrieve and display the data.
+The return data is retrieved as a binary stream. */
+if ( sqlsrv_fetch( $stmt ) )
+{
+ $image = sqlsrv_get_field( $stmt, 0,
+ SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
+ header("Content-Type: image/jpg");
+ fpassthru($image);
+}
+else
+{
+ echo "Error in retrieving data.";
+ die(print_r( sqlsrv_errors(), true));
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream_char.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream_char.phpt
new file mode 100644
index 00000000..257fa109
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_get_field_stream_char.phpt
@@ -0,0 +1,66 @@
+--TEST--
+retrieves row as a stream specified as a character stream.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up the Transact-SQL query. */
+$tsql = "SELECT ReviewerName,
+ CONVERT(varchar(32), ReviewDate, 107) AS [ReviewDate],
+ Rating,
+ Comments
+ FROM Production.ProductReview
+ WHERE ProductReviewID = ? ";
+
+/* Set the parameter value. */
+$productReviewID = 1;
+$params = array( $productReviewID);
+
+/* Execute the query. */
+$stmt = sqlsrv_query($conn, $tsql, $params);
+if( $stmt === false )
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Retrieve and display the data. The first three fields are retrieved
+as strings and the fourth as a stream with character encoding. */
+if(sqlsrv_fetch( $stmt ) === false )
+{
+ echo "Error in retrieving row.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+echo "Name: ".sqlsrv_get_field( $stmt, 0 )."\n";
+echo "Date: ".sqlsrv_get_field( $stmt, 1 )."\n";
+echo "Rating: ".sqlsrv_get_field( $stmt, 2 )."\n";
+echo "Comments: ";
+$comments = sqlsrv_get_field( $stmt, 3,
+ SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_CHAR));
+fpassthru($comments);
+
+/* Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Name: John Smith
+Date: Sep 18, 2013
+Rating: 5
+Comments: I can't believe I'm singing the praises of a pair of socks, but I just came back from a grueling
+3-day ride and these socks really helped make the trip a blast. They're lightweight yet really cushioned my feet all day.
+The reinforced toe is nearly bullet-proof and I didn't experience any problems with rubbing or blisters like I have with
+other brands. I know it sounds silly, but it's always the little stuff (like comfortable feet) that makes or breaks a long trip.
+I won't go on another trip without them!
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_get_field_string_utf8.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_get_field_string_utf8.phpt
new file mode 100644
index 00000000..22ab346c
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_get_field_string_utf8.phpt
@@ -0,0 +1,40 @@
+--TEST--
+retrieves dates as strings by specifying UTF-8 when fetching the string.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd", "ReturnDatesAsStrings" => false);
+$conn = sqlsrv_connect( $server, $connectionInfo);
+
+
+if( $conn === false ) {
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$tsql = "SELECT VersionDate FROM AWBuildVersion";
+
+$stmt = sqlsrv_query( $conn, $tsql);
+
+if ( $stmt === false ) {
+ echo "Error in statement preparation/execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+sqlsrv_fetch( $stmt );
+
+// retrieve date as string
+$date = sqlsrv_get_field( $stmt, 0, SQLSRV_PHPTYPE_STRING("UTF-8"));
+
+if( $date === false ) {
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+echo $date;
+
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+2014-02-20 04:26:00.000
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_has_rows.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_has_rows.phpt
new file mode 100644
index 00000000..7b514105
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_has_rows.phpt
@@ -0,0 +1,24 @@
+--TEST--
+indicate if the result set has one or more rows.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+
+$stmt = sqlsrv_query( $conn, "select * from Person.Person where PersonType = 'EM'" , array());
+
+if ($stmt !== NULL) {
+ $rows = sqlsrv_has_rows( $stmt );
+
+ if ($rows === true)
+ echo "\nthere are rows\n";
+ else
+ echo "\nno rows\n";
+}
+
+?>
+--EXPECT--
+there are rows
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_next_result.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_next_result.phpt
new file mode 100644
index 00000000..039bbadd
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_next_result.phpt
@@ -0,0 +1,151 @@
+--TEST--
+first result is consumed without calling next_result, the next result is made available by calling next_result
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/*revert inserts from previous tests*/
+$d_sql = "DELETE FROM Production.ProductReview WHERE EmailAddress!='john@fourthcoffee.com' AND ProductID=709";
+$stmt4 = sqlsrv_query($conn, $d_sql);
+
+/* Drop the stored procedure if it already exists. */
+$tsql_dropSP = "IF OBJECT_ID('InsertProductReview', 'P') IS NOT NULL
+ DROP PROCEDURE InsertProductReview";
+$stmt1 = sqlsrv_query( $conn, $tsql_dropSP);
+if( $stmt1 === false )
+{
+ echo "Error in executing statement 1.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Create the stored procedure. */
+$tsql_createSP = " CREATE PROCEDURE InsertProductReview
+ @ProductID int,
+ @ReviewerName nvarchar(50),
+ @ReviewDate datetime,
+ @EmailAddress nvarchar(50),
+ @Rating int,
+ @Comments nvarchar(3850)
+ AS
+ BEGIN
+ INSERT INTO Production.ProductReview
+ (ProductID,
+ ReviewerName,
+ ReviewDate,
+ EmailAddress,
+ Rating,
+ Comments)
+ VALUES
+ (@ProductID,
+ @ReviewerName,
+ @ReviewDate,
+ @EmailAddress,
+ @Rating,
+ @Comments);
+ SELECT * FROM Production.ProductReview
+ WHERE ProductID = @ProductID;
+ END";
+$stmt2 = sqlsrv_query( $conn, $tsql_createSP);
+
+if( $stmt2 === false)
+{
+ echo "Error in executing statement 2.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+/*-------- The next few steps call the stored procedure. --------*/
+
+/* Define the Transact-SQL query. Use question marks (?) in place of the
+parameters to be passed to the stored procedure */
+$tsql_callSP = "{call InsertProductReview(?, ?, ?, ?, ?, ?)}";
+
+/* Define the parameter array. */
+$productID = 709;
+$reviewerName = "Morris Gogh";
+$reviewDate = "2008-02-12";
+$emailAddress = "customer@email.com";
+$rating = 3;
+$comments = "[Insert comments here.]";
+$params = array(
+ $productID,
+ $reviewerName,
+ $reviewDate,
+ $emailAddress,
+ $rating,
+ $comments
+ );
+
+/* Execute the query. */
+$stmt3 = sqlsrv_query( $conn, $tsql_callSP, $params);
+if( $stmt3 === false)
+{
+ echo "Error in executing statement 3.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+echo "
"; + +/* Consume the first result (rows affected by INSERT query in the +stored procedure) without calling sqlsrv_next_result. */ +echo "Rows affectd: ".sqlsrv_rows_affected($stmt3)."-----\n"; + +echo "
"; + +/* Move to the next result and display results. */ +$next_result = sqlsrv_next_result($stmt3); +if( $next_result ) +{ + echo "
";
+ echo "\nReview information for product ID ".$productID.".---\n";
+ while( $row = sqlsrv_fetch_array( $stmt3, SQLSRV_FETCH_ASSOC))
+ {
+ echo "
ReviewerName: ".$row['ReviewerName']."\n";
+ echo "
ReviewDate: ".date_format($row['ReviewDate'],
+ "M j, Y")."\n";
+ echo "
EmailAddress: ".$row['EmailAddress']."\n";
+ echo "
Rating: ".$row['Rating']."\n\n";
+ }
+}
+elseif( is_null($next_result))
+{
+ echo "
"; + echo "No more results.\n"; +} +else +{ + echo "Error in moving to next result.\n"; + die(print_r(sqlsrv_errors(), true)); +} + +/* Free statement and connection resources. */ +sqlsrv_free_stmt( $stmt1 ); +sqlsrv_free_stmt( $stmt2 ); +sqlsrv_free_stmt( $stmt3 ); +sqlsrv_free_stmt( $stmt4 ); + + +sqlsrv_close( $conn ); +?> +--EXPECT-- +
Rows affectd: 1----- +
+Review information for product ID 709.---
+
ReviewerName: John Smith
+
ReviewDate: Sep 18, 2013
+
EmailAddress: john@fourthcoffee.com
+
Rating: 5
+
+
ReviewerName: Morris Gogh
+
ReviewDate: Feb 12, 2008
+
EmailAddress: customer@email.com
+
Rating: 3
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_next_result_2.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_next_result_2.phpt
new file mode 100644
index 00000000..0a191780
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_next_result_2.phpt
@@ -0,0 +1,111 @@
+--TEST--
+executes a batch query that retrieves information, insert an entry, then again retrieves information
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Revert inserts from previous msdn_next_result_2 tests */
+$d_sql = "DELETE FROM Production.ProductReview WHERE EmailAddress!='laura@treyresearch.net' AND ProductID=798";
+$stmt = sqlsrv_query($conn, $d_sql);
+
+/* Define the batch query. */
+$tsql = "--Query 1
+ SELECT ProductID, ReviewerName, Rating
+ FROM Production.ProductReview
+ WHERE ProductID=?;
+
+ --Query 2
+ INSERT INTO Production.ProductReview (ProductID,
+ ReviewerName,
+ ReviewDate,
+ EmailAddress,
+ Rating)
+ VALUES (?, ?, ?, ?, ?);
+
+ --Query 3
+ SELECT ProductID, ReviewerName, Rating
+ FROM Production.ProductReview
+ WHERE ProductID=?;";
+
+/* Assign parameter values and execute the query. */
+$params = array(798,
+ 798,
+ 'CustomerName',
+ '2008-4-15',
+ 'test@customer.com',
+ 3,
+ 798 );
+$stmt = sqlsrv_query($conn, $tsql, $params);
+if( $stmt === false )
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+
+/* Retrieve and display the first result. */
+echo "Query 1 result:\n";
+while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC ))
+{
+ print_r($row);
+}
+
+echo "
"; + +/* Move to the next result of the batch query. */ +sqlsrv_next_result($stmt); + +/* Display the result of the second query. */ +echo "Query 2 result:\n"; +echo "Rows Affected: ".sqlsrv_rows_affected($stmt)."\n"; + +echo "
"; + +/* Move to the next result of the batch query. */ +sqlsrv_next_result($stmt); + +/* Retrieve and display the third result. */ +echo "Query 3 result:\n"; +while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_NUMERIC )) +{ + print_r($row); +} + +/* Free statement and connection resources. */ +sqlsrv_free_stmt( $stmt ); +sqlsrv_close( $conn ); +?> +--EXPECT-- +Query 1 result: +Array +( + [0] => 798 + [1] => Laura Norman + [2] => 5 +) +
Query 2 result: +Rows Affected: 1 +
Query 3 result:
+Array
+(
+ [0] => 798
+ [1] => Laura Norman
+ [2] => 5
+)
+Array
+(
+ [0] => 798
+ [1] => CustomerName
+ [2] => 3
+)
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_num_fields.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_num_fields.phpt
new file mode 100644
index 00000000..6f5ef96b
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_num_fields.phpt
@@ -0,0 +1,45 @@
+--TEST--
+retrieve all fields
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Define and execute the query. */
+$tsql = "SELECT TOP (3) * FROM HumanResources.Department";
+$stmt = sqlsrv_query($conn, $tsql);
+if( $stmt === false)
+{
+ echo "Error in executing query.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Retrieve the number of fields. */
+$numFields = sqlsrv_num_fields( $stmt );
+
+/* Iterate through each row of the result set. */
+while( sqlsrv_fetch( $stmt ))
+{
+ /* Iterate through the fields of each row. */
+ for($i = 0; $i < $numFields; $i++)
+ {
+ echo sqlsrv_get_field($stmt, $i,
+ SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR))." ";
+ }
+ echo "
";
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt );
+sqlsrv_close( $conn );
+?>
+--EXPECT--
+1 Engineering Research and Development 2008-04-30 00:00:00.000
2 Tool Design Research and Development 2008-04-30 00:00:00.000
3 Sales Sales and Marketing 2008-04-30 00:00:00.000
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_num_rows.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_num_rows.phpt
new file mode 100644
index 00000000..e37ee376
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_num_rows.phpt
@@ -0,0 +1,27 @@
+--TEST--
+num_rows with a ekyset cursor should work.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$stmt = sqlsrv_query( $conn, "select * from Sales.SalesOrderHeader where CustomerID = 29565" , array(), array( "Scrollable" => SQLSRV_CURSOR_KEYSET ));
+
+ $row_count = sqlsrv_num_rows( $stmt );
+
+ if ($row_count === false)
+ echo "\nerror\n";
+ else if ($row_count >=0)
+ echo "\n$row_count\n";
+?>
+--EXPECT--
+
+8
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_num_rows_2.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_num_rows_2.phpt
new file mode 100644
index 00000000..76d7afda
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_num_rows_2.phpt
@@ -0,0 +1,36 @@
+--TEST--
+when there is a batch query, the number of rows is only available when use a client-side cursor.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+// $tsql = "select * from HumanResources.Department";
+
+// Client-side cursor and batch statements
+$tsql = "select top 8 * from HumanResources.EmployeePayHistory;select top 2 * from HumanResources.Employee;";
+
+// works
+$stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"buffered"));
+
+// fails
+// $stmt = sqlsrv_query($conn, $tsql);
+// $stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"forward"));
+// $stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"static"));
+// $stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"keyset"));
+// $stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"dynamic"));
+
+$row_count = sqlsrv_num_rows( $stmt );
+echo "
\nRow count first result set = $row_count
";
+
+sqlsrv_next_result($stmt);
+
+$row_count = sqlsrv_num_rows( $stmt );
+echo "
\nRow count second result set = $row_count
";
+?>
+--EXPECT--
+
+Row count first result set = 8
+Row count second result set = 2
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_prepare.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_prepare.phpt
new file mode 100644
index 00000000..54a1535d
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_prepare.phpt
@@ -0,0 +1,60 @@
+--TEST--
+Prepares and executes a statement.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up Transact-SQL query. */
+$tsql = "UPDATE Sales.SalesOrderDetail
+ SET OrderQty = ?
+ WHERE SalesOrderDetailID = ?";
+
+/* Assign parameter values. */
+$param1 = 5;
+$param2 = 10;
+$params = array( &$param1, &$param2);
+
+/* Prepare the statement. */
+if( $stmt = sqlsrv_prepare( $conn, $tsql, $params))
+{
+ echo "Statement prepared.
";
+}
+else
+{
+ echo "Statement could not be prepared.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute the statement. */
+if( sqlsrv_execute( $stmt))
+{
+ echo "Statement executed.
";
+}
+else
+{
+ echo "Statement could not be executed.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/*revert the update */
+$r_sql = "UPDATE Sales.SalesOrderDetail SET OrderQty=6 WHERE SalesOrderDetailID=10";
+$stmt2 = sqlsrv_query($conn, $r_sql);
+
+/* Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_free_stmt($stmt2);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Statement prepared.
Statement executed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_prepare_2.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_prepare_2.phpt
new file mode 100644
index 00000000..b22724eb
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_prepare_2.phpt
@@ -0,0 +1,107 @@
+--TEST--
+Prepares a statement and then re-execute it with different parameter values.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Define the parameterized query. */
+$tsql = "UPDATE Sales.SalesOrderDetail
+ SET OrderQty = ?
+ WHERE SalesOrderDetailID = ?";
+
+/* Initialize parameters and prepare the statement. Variables $qty
+and $id are bound to the statement, $stmt1. */
+$qty = 0; $id = 0;
+$stmt1 = sqlsrv_prepare( $conn, $tsql, array( &$qty, &$id));
+if( $stmt1 )
+{
+ echo "Statement 1 prepared.
";
+}
+else
+{
+ echo "Error in statement preparation.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up the SalesOrderDetailID and OrderQty information. This array
+maps the order ID to order quantity in key=>value pairs. */
+$orders = array( 20=>10, 21=>20, 22=>30);
+
+/* Execute the statement for each order. */
+foreach( $orders as $id => $qty)
+{
+ // Because $id and $qty are bound to $stmt1, their updated
+ // values are used with each execution of the statement.
+ if( sqlsrv_execute( $stmt1) === false )
+ {
+ echo "Error in statement execution.
";
+ die( print_r( sqlsrv_errors(), true));
+ }
+}
+echo "Orders updated.
";
+
+/* Free $stmt1 resources. This allows $id and $qty to be bound to a different statement.*/
+sqlsrv_free_stmt( $stmt1);
+
+/* Now verify that the results were successfully written by selecting
+the newly inserted rows. */
+$tsql = "SELECT OrderQty
+ FROM Sales.SalesOrderDetail
+ WHERE SalesOrderDetailID = ?";
+
+/* Prepare the statement. Variable $id is bound to $stmt2. */
+$stmt2 = sqlsrv_prepare( $conn, $tsql, array( &$id));
+if( $stmt2 )
+{
+ echo "Statement 2 prepared.
";
+}
+else
+{
+ echo "Error in statement preparation.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute the statement for each order. */
+foreach( array_keys($orders) as $id)
+{
+ /* Because $id is bound to $stmt2, its updated value
+ is used with each execution of the statement. */
+ if( sqlsrv_execute( $stmt2))
+ {
+ sqlsrv_fetch( $stmt2);
+ $quantity = sqlsrv_get_field( $stmt2, 0);
+ echo "Order $id is for $quantity units.
";
+ }
+ else
+ {
+ echo "Error in statement execution.
";
+ die( print_r( sqlsrv_errors(), true));
+ }
+}
+
+/* revert the update */
+$r_sql3 = "UPDATE Sales.SalesOrderDetail SET OrderQty = 2 WHERE SalesOrderDetailID = 20";
+$stmt3 = sqlsrv_query($conn, $r_sql3);
+$r_sql4 = "UPDATE Sales.SalesOrderDetail SET OrderQty = 3 WHERE SalesOrderDetailID = 21";
+$stmt4 = sqlsrv_query($conn, $r_sql4);
+$r_sql5 = "UPDATE Sales.SalesOrderDetail SET OrderQty = 2 WHERE SalesOrderDetailID = 22";
+$stmt5 = sqlsrv_query($conn, $r_sql5);
+
+/* Free $stmt2 and connection resources. */
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_free_stmt( $stmt3);
+sqlsrv_free_stmt( $stmt4);
+sqlsrv_free_stmt( $stmt5);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Statement 1 prepared.
Orders updated.
Statement 2 prepared.
Order 20 is for 10 units.
Order 21 is for 20 units.
Order 22 is for 30 units.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_prepare_bind_param.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_prepare_bind_param.phpt
new file mode 100644
index 00000000..56b2bf00
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_prepare_bind_param.phpt
@@ -0,0 +1,88 @@
+--TEST--
+binding of variables using prepare function
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$tsql = "INSERT INTO Sales.SalesOrderDetail (SalesOrderID,
+ OrderQty,
+ ProductID,
+ SpecialOfferID,
+ UnitPrice)
+ VALUES (?, ?, ?, ?, ?)";
+
+/* Each sub array here will be a parameter array for a query.
+The values in each sub array are, in order, SalesOrderID, OrderQty,
+ ProductID, SpecialOfferID, UnitPrice. */
+$parameters = array( array(43659, 8, 711, 1, 20.19),
+ array(43660, 6, 762, 1, 419.46),
+ array(43661, 4, 741, 1, 818.70)
+ );
+
+/* Initialize parameter values. */
+$orderId = 0;
+$qty = 0;
+$prodId = 0;
+$specialOfferId = 0;
+$price = 0.0;
+
+/* Prepare the statement. $params is implicitly bound to $stmt. */
+$stmt = sqlsrv_prepare( $conn, $tsql, array( &$orderId,
+ &$qty,
+ &$prodId,
+ &$specialOfferId,
+ &$price));
+if( $stmt === false )
+{
+ echo "Statement could not be prepared.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Execute a statement for each set of params in $parameters.
+Because $params is bound to $stmt, as the values are changed, the
+new values are used in the subsequent execution. */
+foreach( $parameters as $params)
+{
+ list($orderId, $qty, $prodId, $specialOfferId, $price) = $params;
+ if( sqlsrv_execute($stmt) === false )
+ {
+ echo "Statement could not be executed.\n";
+ die( print_r( sqlsrv_errors(), true));
+ }
+ else
+ {
+ /* Verify that the row was successfully inserted. */
+ echo "Rows affected: ".sqlsrv_rows_affected( $stmt )."\n";
+ }
+}
+
+/* Revert the changes */
+$d_sql2 = "DELETE FROM Sales.SalesOrderDetail WHERE SalesOrderID=43659 AND OrderQty=8 AND ProductID=711 AND SpecialOfferID=1 AND Unitprice=20.19";
+$stmt2 = sqlsrv_query($conn, $d_sql2);
+$d_sql3 = "DELETE FROM Sales.SalesOrderDetail WHERE SalesOrderID=43660 AND OrderQty=6 AND ProductID=762 AND SpecialOfferID=1 AND Unitprice=419.46";
+$stmt3 = sqlsrv_query($conn, $d_sql3);
+$d_sql4 = "DELETE FROM Sales.SalesOrderDetail WHERE SalesOrderID=43661 AND OrderQty=4 AND ProductID=741 AND SpecialOfferID=1 AND Unitprice=818.70";
+$stmt4 = sqlsrv_query($conn, $d_sql4);
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_free_stmt( $stmt3);
+sqlsrv_free_stmt( $stmt4);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Rows affected: 1
+Rows affected: 1
+Rows affected: 1
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_prepare_scrollable_buffered.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_prepare_scrollable_buffered.phpt
new file mode 100644
index 00000000..50d071e9
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_prepare_scrollable_buffered.phpt
@@ -0,0 +1,37 @@
+--TEST--
+server side cursor specified when preparing
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if ( $conn === false ) {
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$tsql = "select * from HumanResources.Employee";
+$stmt = sqlsrv_prepare( $conn, $tsql, array(), array("Scrollable"=>SQLSRV_CURSOR_CLIENT_BUFFERED));
+
+if (! $stmt ) {
+ echo "Statement could not be prepared.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+sqlsrv_execute( $stmt);
+
+$row_count = sqlsrv_num_rows( $stmt );
+if ($row_count)
+ echo "\nRow count = $row_count\n";
+
+$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_FIRST);
+if ($row ) {
+ $EmployeeID = sqlsrv_get_field( $stmt, 0);
+ echo "Employee ID = $EmployeeID \n";
+}
+?>
+--EXPECT--
+Row count = 290
+Employee ID = 1
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query.phpt
new file mode 100644
index 00000000..cd5a19c4
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query.phpt
@@ -0,0 +1,55 @@
+--TEST--
+Query insert into a table
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up the parameterized query. */
+$tsql = "INSERT INTO Sales.SalesOrderDetail
+ (SalesOrderID,
+ OrderQty,
+ ProductID,
+ SpecialOfferID,
+ UnitPrice,
+ UnitPriceDiscount)
+ VALUES
+ (?, ?, ?, ?, ?, ?)";
+
+/* Set parameter values. */
+$params = array(75123, 5, 741, 1, 818.70, 0.00);
+
+// RevisionNumber in SalesOrderHeader is subject to a trigger incrementing it whenever
+// changes are made to SalesOrderDetail. Since RevisonNumber is a tinyint, it can
+// overflow quickly if this test is often run. So we change it directly here first
+// before it can overflow.
+$stmt0 = sqlsrv_query( $conn, "UPDATE Sales.SalesOrderHeader SET RevisionNumber = 2 WHERE SalesOrderID = $params[0]");
+
+/* Prepare and execute the query. */
+$stmt = sqlsrv_query( $conn, $tsql, $params);
+if( $stmt )
+{
+ echo "Row successfully inserted.\n";
+}
+else
+{
+ echo "Row insertion failed.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Row successfully inserted.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_2.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_2.phpt
new file mode 100644
index 00000000..8b95c87d
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_2.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Query update a field in a table
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up the parameterized query. */
+$tsql = "UPDATE Sales.SalesOrderDetail
+ SET OrderQty = ( ?)
+ WHERE SalesOrderDetailID = ( ?)";
+
+/* Assign literal parameter values. */
+$params = array( 5, 10);
+
+/* Execute the query. */
+if( sqlsrv_query( $conn, $tsql, $params))
+{
+ echo "Statement executed.\n";
+}
+else
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/*revert the update */
+$r_sql = "UPDATE Sales.SalesOrderDetail SET OrderQty=6 WHERE SalesOrderDetailID=10";
+$stmt = sqlsrv_query($conn, $r_sql);
+
+/* Free connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Statement executed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_bind_param.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_bind_param.phpt
new file mode 100644
index 00000000..ee43e3e3
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_bind_param.phpt
@@ -0,0 +1,63 @@
+--TEST--
+updates the quantity in a table, the quantity and product ID are parameters in the UPDATE query.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Define the Transact-SQL query.
+Use question marks as parameter placeholders. */
+$tsql1 = "UPDATE Production.ProductInventory
+ SET Quantity = ?
+ WHERE ProductID = ?";
+
+/* Initialize $qty and $productId */
+$qty = 10; $productId = 709;
+
+/* Execute the statement with the specified parameter values. */
+$stmt1 = sqlsrv_query( $conn, $tsql1, array($qty, $productId));
+if( $stmt1 === false )
+{
+ echo "Statement 1 could not be executed.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Free statement resources. */
+sqlsrv_free_stmt( $stmt1);
+
+/* Now verify the updated quantity.
+Use a question mark as parameter placeholder. */
+$tsql2 = "SELECT Quantity
+ FROM Production.ProductInventory
+ WHERE ProductID = ?";
+
+/* Execute the statement with the specified parameter value.
+Display the returned data if no errors occur. */
+$stmt2 = sqlsrv_query( $conn, $tsql2, array($productId));
+if( $stmt2 === false )
+{
+ echo "Statement 2 could not be executed.\n";
+ die( print_r(sqlsrv_errors(), true));
+}
+else
+{
+ $qty = sqlsrv_fetch_array( $stmt2);
+ echo "There are $qty[0] of product $productId in inventory.\n";
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+There are 10 of product 709 in inventory.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_param_inout.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_param_inout.phpt
new file mode 100644
index 00000000..693b2739
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_param_inout.phpt
@@ -0,0 +1,88 @@
+--TEST--
+queries a call procedure with an in-out parameter.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+/* Drop the stored procedure if it already exists. */
+$tsql_dropSP = "IF OBJECT_ID('SubtractVacationHours', 'P') IS NOT NULL
+ DROP PROCEDURE SubtractVacationHours";
+$stmt1 = sqlsrv_query( $conn, $tsql_dropSP);
+if( $stmt1 === false )
+{
+ echo "Error in executing statement 1.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Create the stored procedure. */
+$tsql_createSP = "CREATE PROCEDURE SubtractVacationHours
+ @BusinessEntityID int,
+ @VacationHrs smallint OUTPUT
+ AS
+ UPDATE HumanResources.Employee
+ SET VacationHours = VacationHours - @VacationHrs
+ WHERE BusinessEntityID = @BusinessEntityID;
+ SET @VacationHrs = (SELECT VacationHours
+ FROM HumanResources.Employee
+ WHERE BusinessEntityID = @BusinessEntityID)";
+
+$stmt2 = sqlsrv_query( $conn, $tsql_createSP);
+if( $stmt2 === false )
+{
+ echo "Error in executing statement 2.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/*--------- The next few steps call the stored procedure. ---------*/
+
+/* Define the Transact-SQL query. Use question marks (?) in place of
+the parameters to be passed to the stored procedure */
+$tsql_callSP = "{call SubtractVacationHours( ?, ?)}";
+
+/* Define the parameter array. By default, the first parameter is an
+INPUT parameter. The second parameter is specified as an INOUT
+parameter. Initializing $vacationHrs to 8 sets the returned PHPTYPE to
+integer. To ensure data type integrity, output parameters should be
+initialized before calling the stored procedure, or the desired
+PHPTYPE should be specified in the $params array.*/
+
+$employeeId = 4;
+$vacationHrs = 1;
+$params = array(
+ array($employeeId, SQLSRV_PARAM_IN),
+ array(&$vacationHrs, SQLSRV_PARAM_INOUT)
+ );
+
+/* Execute the query. */
+$stmt3 = sqlsrv_query( $conn, $tsql_callSP, $params);
+if( $stmt3 === false )
+{
+ echo "Error in executing statement 3.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Display the value of the output parameter $vacationHrs. */
+sqlsrv_next_result($stmt3);
+echo "Remaining vacation hours: ".$vacationHrs;
+
+/* Revert the update in vacation hours */
+$r_sql = "UPDATE HumanResources.Employee SET VacationHours=48 WHERE BusinessEntityID=4";
+$stmt4 = sqlsrv_query($conn, $r_sql);
+
+/*Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt1);
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_free_stmt( $stmt3);
+sqlsrv_free_stmt( $stmt4);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Remaining vacation hours: 47
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_param_out.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_param_out.phpt
new file mode 100644
index 00000000..62662dda
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_param_out.phpt
@@ -0,0 +1,82 @@
+--TEST--
+queries a call to procedure with input and output parameters.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Drop the stored procedure if it already exists. */
+$tsql_dropSP = "IF OBJECT_ID('GetEmployeeSalesYTD', 'P') IS NOT NULL
+ DROP PROCEDURE GetEmployeeSalesYTD";
+$stmt1 = sqlsrv_query( $conn, $tsql_dropSP);
+if( $stmt1 === false )
+{
+ echo "Error in executing statement 1.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Create the stored procedure. */
+$tsql_createSP = " CREATE PROCEDURE GetEmployeeSalesYTD
+ @SalesPerson nvarchar(50),
+ @SalesYTD money OUTPUT
+ AS
+ SELECT @SalesYTD = SalesYTD
+ FROM Sales.SalesPerson AS sp
+ JOIN HumanResources.vEmployee AS e
+ ON e.BusinessEntityID = sp.BusinessEntityID
+ WHERE LastName = @SalesPerson";
+$stmt2 = sqlsrv_query( $conn, $tsql_createSP);
+if( $stmt2 === false )
+{
+ echo "Error in executing statement 2.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/*--------- The next few steps call the stored procedure. ---------*/
+
+/* Define the Transact-SQL query. Use question marks (?) in place of
+ the parameters to be passed to the stored procedure */
+$tsql_callSP = "{call GetEmployeeSalesYTD( ?, ? )}";
+
+/* Define the parameter array. By default, the first parameter is an
+INPUT parameter. The second parameter is specified as an OUTPUT
+parameter. Initializing $salesYTD to 0.0 sets the returned PHPTYPE to
+float. To ensure data type integrity, output parameters should be
+initialized before calling the stored procedure, or the desired
+PHPTYPE should be specified in the $params array.*/
+$lastName = "Blythe";
+$salesYTD = 0.0;
+$params = array(
+ array(&$lastName, SQLSRV_PARAM_IN),
+ array(&$salesYTD, SQLSRV_PARAM_OUT)
+ );
+
+/* Execute the query. */
+$stmt3 = sqlsrv_query( $conn, $tsql_callSP, $params);
+if( $stmt3 === false )
+{
+ echo "Error in executing statement 3.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Display the value of the output parameter $salesYTD. */
+echo "YTD sales for ".$lastName." are ". $salesYTD. ".";
+
+/*Free the statement and connection resources. */
+sqlsrv_free_stmt( $stmt1);
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_free_stmt( $stmt3);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+YTD sales for Blythe are 3763178.1787.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_scrollable.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_scrollable.phpt
new file mode 100644
index 00000000..e9444ea9
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_scrollable.phpt
@@ -0,0 +1,74 @@
+--TEST--
+server side cursor specified when querying
+--SKIPIF--
+
+--FILE--
+ "tempdb", "UID"=>"sa", "PWD"=>"Moonshine4me"));
+
+require('connect.inc');
+$connectionInfo = array( "Database"=>"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if ( $conn === false ) {
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+$stmt = sqlsrv_query( $conn, "DROP TABLE dbo.ScrollTest" );
+if ( $stmt !== false ) {
+ sqlsrv_free_stmt( $stmt );
+}
+
+$stmt = sqlsrv_query( $conn, "CREATE TABLE ScrollTest (id int, value char(10))" );
+if ( $stmt === false ) {
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+$stmt = sqlsrv_query( $conn, "INSERT INTO ScrollTest (id, value) VALUES(?,?)", array( 1, "Row 1" ));
+if ( $stmt === false ) {
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+$stmt = sqlsrv_query( $conn, "INSERT INTO ScrollTest (id, value) VALUES(?,?)", array( 2, "Row 2" ));
+if ( $stmt === false ) {
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+$stmt = sqlsrv_query( $conn, "INSERT INTO ScrollTest (id, value) VALUES(?,?)", array( 3, "Row 3" ));
+if ( $stmt === false ) {
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+$stmt = sqlsrv_query( $conn, "SELECT * FROM ScrollTest", array(), array( "Scrollable" => 'keyset' ));
+// $stmt = sqlsrv_query( $conn, "SELECT * FROM ScrollTest", array(), array( "Scrollable" => 'dynamic' ));
+// $stmt = sqlsrv_query( $conn, "SELECT * FROM ScrollTest", array(), array( "Scrollable" => 'static' ));
+
+$rows = sqlsrv_has_rows( $stmt );
+if ( $rows != true ) {
+ die( "Should have rows" );
+}
+
+$result = sqlsrv_fetch( $stmt, SQLSRV_SCROLL_LAST );
+$field1 = sqlsrv_get_field( $stmt, 0 );
+$field2 = sqlsrv_get_field( $stmt, 1 );
+echo "\n$field1 $field2\n";
+
+//$stmt2 = sqlsrv_query( $conn, "delete from ScrollTest where id = 3" );
+// or
+$stmt2 = sqlsrv_query( $conn, "UPDATE ScrollTest SET id = 4 WHERE id = 3" );
+if ( $stmt2 !== false ) {
+ sqlsrv_free_stmt( $stmt2 );
+}
+
+$result = sqlsrv_fetch( $stmt, SQLSRV_SCROLL_LAST );
+$field1 = sqlsrv_get_field( $stmt, 0 );
+$field2 = sqlsrv_get_field( $stmt, 1 );
+echo "\n$field1 $field2\n";
+
+sqlsrv_free_stmt( $stmt );
+sqlsrv_close( $conn );
+?>
+--EXPECT--
+3 Row 3
+
+4 Row 3
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_scrollable_buffered.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_scrollable_buffered.phpt
new file mode 100644
index 00000000..a0789ea4
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_scrollable_buffered.phpt
@@ -0,0 +1,66 @@
+--TEST--
+client side buffered cursor
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if ( $conn === false ) {
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$tsql = "select * from HumanResources.Department";
+
+// Execute the query with client-side cursor.
+$stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"buffered"));
+if (! $stmt) {
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+// row count is always available with a client-side cursor
+$row_count = sqlsrv_num_rows( $stmt );
+echo "\nRow count = $row_count\n";
+
+// Move to a specific row in the result set.
+$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_FIRST);
+$EmployeeID = sqlsrv_get_field( $stmt, 0);
+echo "Employee ID = $EmployeeID \n";
+
+// Client-side cursor and batch statements
+$tsql = "select top 2 * from HumanResources.Employee;Select top 3 * from HumanResources.EmployeePayHistory";
+
+$stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"buffered"));
+if (! $stmt) {
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$row_count = sqlsrv_num_rows( $stmt );
+echo "\nRow count for first result set = $row_count\n";
+
+$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_FIRST);
+$EmployeeID = sqlsrv_get_field( $stmt, 0);
+echo "Employee ID = $EmployeeID \n";
+
+sqlsrv_next_result($stmt);
+
+$row_count = sqlsrv_num_rows( $stmt );
+echo "\nRow count for second result set = $row_count\n";
+
+$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_LAST);
+$BusinessEntityID = sqlsrv_get_field( $stmt, 0);
+echo "Business Entity ID = $BusinessEntityID \n";
+?>
+--EXPECT--
+Row count = 16
+Employee ID = 1
+
+Row count for first result set = 2
+Employee ID = 1
+
+Row count for second result set = 3
+Business Entity ID = 3
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_sqltype.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_sqltype.phpt
new file mode 100644
index 00000000..0ecd18e6
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_sqltype.phpt
@@ -0,0 +1,87 @@
+--TEST--
+sqlsrv types are specified for the parameters in query.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Define the query. */
+$tsql1 = "INSERT INTO HumanResources.EmployeePayHistory (BusinessEntityID,
+ RateChangeDate,
+ Rate,
+ PayFrequency)
+ VALUES (?, ?, ?, ?)";
+
+/* Construct the parameter array. */
+$businessEntityId = 6;
+$changeDate = "2005-06-07";
+$rate = 30;
+$payFrequency = 2;
+$params1 = array(
+ array($businessEntityId, null),
+ array($changeDate, null, null, SQLSRV_SQLTYPE_DATETIME),
+ array($rate, null, null, SQLSRV_SQLTYPE_MONEY),
+ array($payFrequency, null, null, SQLSRV_SQLTYPE_TINYINT)
+ );
+
+/* Execute the INSERT query. */
+$stmt1 = sqlsrv_query($conn, $tsql1, $params1);
+if( $stmt1 === false )
+{
+ echo "Error in execution of INSERT.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Retrieve the newly inserted data. */
+/* Define the query. */
+$tsql2 = "SELECT BusinessEntityID, RateChangeDate, Rate, PayFrequency
+ FROM HumanResources.EmployeePayHistory
+ WHERE BusinessEntityID = ? AND RateChangeDate = ?";
+
+/* Construct the parameter array. */
+$params2 = array($businessEntityId, $changeDate);
+
+/*Execute the SELECT query. */
+$stmt2 = sqlsrv_query($conn, $tsql2, $params2);
+if( $stmt2 === false )
+{
+ echo "Error in execution of SELECT.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Retrieve and display the results. */
+$row = sqlsrv_fetch_array( $stmt2 );
+if( $row === false )
+{
+ echo "Error in fetching data.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+echo "BusinessEntityID: ".$row['BusinessEntityID']."\n";
+echo "Change Date: ".date_format($row['RateChangeDate'], "Y-m-d")."\n";
+echo "Rate: ".$row['Rate']."\n";
+echo "PayFrequency: ".$row['PayFrequency']."\n";
+
+/* Revert the insert */
+$d_sql = "delete from HumanResources.EmployeePayHistory where BusinessEntityId=6 and RateChangeDate='2005-06-07 00:00:00.000'";
+$stmt = sqlsrv_query($conn, $d_sql);
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt($stmt1);
+sqlsrv_free_stmt($stmt2);
+sqlsrv_close($conn);
+?>
+--EXPECT--
+BusinessEntityID: 6
+Change Date: 2005-06-07
+Rate: 30.0000
+PayFrequency: 2
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_stream.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_stream.phpt
new file mode 100644
index 00000000..4f1b737a
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_stream.phpt
@@ -0,0 +1,56 @@
+--TEST--
+insert stream.
+--SKIPIF--
+
+?>
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up the Transact-SQL query. */
+$tsql = "INSERT INTO Production.ProductReview (ProductID,
+ ReviewerName,
+ ReviewDate,
+ EmailAddress,
+ Rating,
+ Comments)
+ VALUES (?, ?, ?, ?, ?, ?)";
+
+/* Set the parameter values and put them in an array.
+Note that $comments is opened as a stream. */
+$productID = '709';
+$name = 'Customer Name';
+$date = date("Y-m-d");
+$email = 'customer@name.com';
+$rating = 3;
+$comments = fopen( "data://text/plain,[ Insert lengthy comment here.]",
+ "r");
+$params = array($productID, $name, $date, $email, $rating, $comments);
+
+/* Execute the query. All stream data is sent upon execution.*/
+$stmt = sqlsrv_query($conn, $tsql, $params);
+if( $stmt === false )
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+else
+{
+ echo "The query was successfully executed.";
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+The query was successfully executed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_query_utf8.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_query_utf8.phpt
new file mode 100644
index 00000000..100d1ce4
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_query_utf8.phpt
@@ -0,0 +1,91 @@
+--TEST--
+specify the UTF-8 character set when querying
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if ( $conn === false ) {
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+// Set up the Transact-SQL query.
+//
+$tsql1 = "UPDATE Production.ProductReview
+ SET Comments = ?
+ WHERE ProductReviewID = ?";
+
+// Set the parameter values and put them in an array. Note that
+// $comments is converted to UTF-8 encoding with the PHP function
+// utf8_encode to simulate an application that uses UTF-8 encoded data.
+//
+$reviewID = 3;
+$comments = utf8_encode("testing");
+$params1 = array(
+ array($comments,
+ SQLSRV_PARAM_IN,
+ SQLSRV_PHPTYPE_STRING('UTF-8')
+ ),
+ array($reviewID)
+ );
+
+// Execute the query.
+//
+$stmt1 = sqlsrv_query($conn, $tsql1, $params1);
+
+if ( $stmt1 === false ) {
+ echo "Error in statement execution.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+else {
+ echo "The update was successfully executed.
";
+}
+
+// Retrieve the newly updated data.
+//
+$tsql2 = "SELECT Comments
+ FROM Production.ProductReview
+ WHERE ProductReviewID = ?";
+
+// Set up the parameter array.
+//
+$params2 = array($reviewID);
+
+// Execute the query.
+//
+$stmt2 = sqlsrv_query($conn, $tsql2, $params2);
+if ( $stmt2 === false ) {
+ echo "Error in statement execution.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+// Retrieve and display the data.
+//
+if ( sqlsrv_fetch($stmt2) ) {
+ echo "Comments: ";
+ $data = sqlsrv_get_field($stmt2,
+ 0,
+ SQLSRV_PHPTYPE_STRING('UTF-8')
+ );
+ echo $data."
";
+}
+else {
+ echo "Error in fetching data.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+// Free statement and connection resources.
+//
+sqlsrv_free_stmt( $stmt1 );
+sqlsrv_free_stmt( $stmt2 );
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+The update was successfully executed.
Comments: testing
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_rollback.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_rollback.phpt
new file mode 100644
index 00000000..d96c8373
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_rollback.phpt
@@ -0,0 +1,70 @@
+--TEST--
+Rolls back the current transaction on the specified connection and returns the connection to the auto-commit mode.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+/* Initiate transaction. */
+/* Exit script if transaction cannot be initiated. */
+if ( sqlsrv_begin_transaction( $conn) === false )
+{
+ echo "Could not begin transaction.\n";
+ die( print_r( sqlsrv_errors(), true ));
+}
+
+/* Initialize parameter values. */
+$orderId = 43659; $qty = 5; $productId = 709;
+$offerId = 1; $price = 5.70;
+
+/* Set up and execute the first query. */
+$tsql1 = "INSERT INTO Sales.SalesOrderDetail
+ (SalesOrderID,
+ OrderQty,
+ ProductID,
+ SpecialOfferID,
+ UnitPrice)
+ VALUES (?, ?, ?, ?, ?)";
+$params1 = array( $orderId, $qty, $productId, $offerId, $price);
+$stmt1 = sqlsrv_query( $conn, $tsql1, $params1 );
+
+/* Set up and executee the second query. */
+$tsql2 = "UPDATE Production.ProductInventory
+ SET Quantity = (Quantity - ?)
+ WHERE ProductID = ?";
+$params2 = array($qty, $productId);
+$stmt2 = sqlsrv_query( $conn, $tsql2, $params2 );
+
+/* If both queries were successful, commit the transaction. */
+/* Otherwise, rollback the transaction. */
+if( $stmt1 && $stmt2 )
+{
+ sqlsrv_commit( $conn );
+ echo "Transaction was committed.\n";
+}
+else
+{
+ sqlsrv_rollback( $conn );
+ echo "Transaction was rolled back.\n";
+}
+
+/* Revert the changes */
+$d_sql = "DELETE FROM Sales.SalesOrderDetail WHERE SalesOrderID=43659 AND OrderQty=5 AND ProductID=709 AND SpecialOfferID=1 AND Unitprice=5.70";
+$stmt3 = sqlsrv_query($conn, $d_sql);
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt1);
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_free_stmt($stmt3);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+Transaction was committed.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_rows_affected.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_rows_affected.phpt
new file mode 100644
index 00000000..983812ab
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_rows_affected.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Returns the number of rows modified by the last statement executed.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up Transact-SQL query. */
+$tsql = "UPDATE Sales.SalesOrderDetail
+ SET SpecialOfferID = ?
+ WHERE ProductID = ?";
+
+/* Set parameter values. */
+$params = array(2, 709);
+
+/* Execute the statement. */
+$stmt = sqlsrv_query( $conn, $tsql, $params);
+
+/* Get the number of rows affected and display appropriate message.*/
+$rows_affected = sqlsrv_rows_affected( $stmt);
+if( $rows_affected === false)
+{
+ echo "Error in calling sqlsrv_rows_affected.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+elseif( $rows_affected == -1)
+{
+ echo "No information available.\n";
+}
+else
+{
+ echo $rows_affected." rows were updated.\n";
+}
+
+/*revert the update */
+$r_sql2 = "UPDATE Sales.SalesOrderDetail SET SpecialOfferID=1 WHERE ProductID=709 AND UnitPriceDiscount=0.00";
+$stmt2 = sqlsrv_query($conn, $r_sql2);
+$r_sql3 = "UPDATE Sales.SalesOrderDetail SET SpecialOfferID=3 WHERE ProductID=709 AND UnitPriceDiscount=0.05";
+$stmt3 = sqlsrv_query($conn, $r_sql3);
+$r_sql4 = "UPDATE Sales.SalesOrderDetail SET SpecialOfferID=4 WHERE ProductID=709 AND UnitPriceDiscount=0.10";
+$stmt4 = sqlsrv_query($conn, $r_sql4);
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_free_stmt( $stmt2);
+sqlsrv_free_stmt( $stmt3);
+sqlsrv_free_stmt( $stmt4);
+sqlsrv_close( $conn);
+?>
+--EXPECTREGEX--
+[0-9]+ rows were updated.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_send_stream_data.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_send_stream_data.phpt
new file mode 100644
index 00000000..eab20a3d
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_send_stream_data.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Sends data from parameter streams to the server
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Define the query. */
+$tsql = "UPDATE Production.ProductReview
+ SET Comments = ( ?)
+ WHERE ProductReviewID = 3";
+
+/* Open parameter data as a stream and put it in the $params array. */
+$comment = fopen( "data://text/plain,[ Insert lengthy comment.]", "r");
+$params = array( &$comment);
+
+/* Prepare the statement. Use the $options array to turn off the
+default behavior, which is to send all stream data at the time of query
+execution. */
+$options = array("SendStreamParamsAtExec"=>0);
+$stmt = sqlsrv_prepare( $conn, $tsql, $params, $options);
+
+/* Execute the statement. */
+sqlsrv_execute( $stmt);
+
+/* Send up to 8K of parameter data to the server with each call to
+sqlsrv_send_stream_data. Count the calls. */
+$i = 1;
+while( sqlsrv_send_stream_data( $stmt))
+{
+ echo "$i call(s) made.
";
+ $i++;
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+1 call(s) made.
2 call(s) made.
3 call(s) made.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_send_stream_data_no_sendStreamParamsAtExec.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_send_stream_data_no_sendStreamParamsAtExec.phpt
new file mode 100644
index 00000000..f324c3c7
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_send_stream_data_no_sendStreamParamsAtExec.phpt
@@ -0,0 +1,67 @@
+--TEST--
+sned stream data with SendStreamParamsAtExec turned off.
+--SKIPIF--
+
+?>
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Set up the Transact-SQL query. */
+$tsql = "INSERT INTO Production.ProductReview (ProductID,
+ ReviewerName,
+ ReviewDate,
+ EmailAddress,
+ Rating,
+ Comments)
+ VALUES (?, ?, ?, ?, ?, ?)";
+
+/* Set the parameter values and put them in an array.
+Note that $comments is opened as a stream. */
+$productID = '709';
+$name = 'Customer Name';
+$date = date("Y-m-d");
+$email = 'customer@name.com';
+$rating = 3;
+$comments = fopen( "data://text/plain,[ Insert lengthy comment here.]",
+ "r");
+$params = array($productID, $name, $date, $email, $rating, $comments);
+
+/* Turn off the default behavior of sending all stream data at
+execution. */
+$options = array("SendStreamParamsAtExec" => 0);
+
+/* Execute the query. */
+$stmt = sqlsrv_query($conn, $tsql, $params, $options);
+if( $stmt === false )
+{
+ echo "Error in statement execution.\n";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Send up to 8K of parameter data to the server with each call to
+sqlsrv_send_stream_data. Count the calls. */
+$i = 1;
+while( sqlsrv_send_stream_data( $stmt))
+{
+ echo "$i call(s) made.\n";
+ $i++;
+}
+
+/* Free statement and connection resources. */
+sqlsrv_free_stmt( $stmt);
+sqlsrv_close( $conn);
+?>
+--EXPECT--
+1 call(s) made.
+2 call(s) made.
+3 call(s) made.
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/msdn_sqlsrv_server_info.phpt b/test/bvt/sqlsrv/msdn_sqlsrv_server_info.phpt
new file mode 100644
index 00000000..c15096b5
--- /dev/null
+++ b/test/bvt/sqlsrv/msdn_sqlsrv_server_info.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Returns information about the server.
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+$conn = sqlsrv_connect( $server, $connectionInfo);
+if( $conn === false )
+{
+ echo "Could not connect.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+$server_info = sqlsrv_server_info( $conn);
+if( $server_info )
+{
+ foreach( $server_info as $key => $value)
+ {
+ echo $key.": ".$value."
";
+ }
+}
+else
+{
+ echo "Error in retrieving server info.
";
+ die( print_r( sqlsrv_errors(), true));
+}
+
+/* Free connection resources. */
+sqlsrv_close( $conn);
+?>
+--EXPECTREGEX--
+CurrentDatabase: AdventureWorks.*
SQLServerVersion: 1[2-9].00.[0-9]{4}
SQLServerName: SQL.+
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/readme.txt b/test/bvt/sqlsrv/readme.txt
new file mode 100644
index 00000000..d1a2c766
--- /dev/null
+++ b/test/bvt/sqlsrv/readme.txt
@@ -0,0 +1,6 @@
+This folder mainly contains tests that are derived from the code examples on
+
+https://docs.microsoft.com/en-us/sql/connect/php/sqlsrv-driver-api-reference
+
+Modify connect.inc with the real credentials to run the tests, using the latest run-tests.php from
+https://raw.githubusercontent.com/php/php-src/master/run-tests.php
\ No newline at end of file
diff --git a/test/bvt/sqlsrv/sqlsrv_param_inout.phpt b/test/bvt/sqlsrv/sqlsrv_param_inout.phpt
new file mode 100644
index 00000000..603f0ab5
--- /dev/null
+++ b/test/bvt/sqlsrv/sqlsrv_param_inout.phpt
@@ -0,0 +1,67 @@
+--TEST--
+call a stored procedure (SQLSRV Driver) and retrieve the errorNumber that is returned
+--SKIPIF--
+
+--FILE--
+"$databaseName", "UID"=>"$uid", "PWD"=>"$pwd");
+ $conn = sqlsrv_connect( $server, $connectionInfo);
+
+ if ($conn === false){
+ echo "Could not connect.\n";
+ die (print_r (sqlsrv_errors(), true));
+ }
+
+ // Drop the stored procedure if it already exists
+ $tsql_dropSP = "IF OBJECT_ID('sp_Test', 'P') IS NOT NULL
+ DROP PROCEDURE sp_Test";
+ $stmt1 = sqlsrv_query($conn, $tsql_dropSP);
+ if ($stmt1 === false) {
+ echo "Error in executing statement 1.\n";
+ die (print_r (sqlsrv_errors(), true));
+ }
+
+ // Create the stored procedure
+ $tsql_createSP = "CREATE PROCEDURE sp_Test
+ @ErrorNumber INT = 0 OUTPUT
+ AS
+ BEGIN
+ SET @ErrorNumber = -1
+ SELECT 1,2,3
+ END";
+ $stmt2 = sqlsrv_query($conn, $tsql_createSP);
+ if ($stmt2 === false) {
+ echo "Error in executing statement 2.\n";
+ die (print_r (sqlsrv_errors(), true));
+ }
+
+ // Call the stored procedure
+ $tsql_callSP = "{CALL sp_Test (?)}";
+
+ // Define the parameter array
+ $errorNumber = -5;
+ $params = array(
+ array(&$errorNumber, SQLSRV_PARAM_INOUT)
+ );
+
+ // Execute the query
+ $stmt3 = sqlsrv_query($conn, $tsql_callSP, $params);
+ if ($stmt3 === false) {
+ echo "Error in executing statement 3.\n";
+ die (print_r (sqlsrv_errors(), true));
+ }
+
+ // Display the value of the output parameter $errorNumber
+ sqlsrv_next_result($stmt3);
+ print("Error Number: $errorNumber\n\n");
+
+ // Free the statement and connection resources. */
+ sqlsrv_free_stmt( $stmt1);
+ sqlsrv_free_stmt( $stmt2);
+ sqlsrv_free_stmt( $stmt3);
+ sqlsrv_close( $conn);
+?>
+--EXPECT--
+Error Number: -1
diff --git a/test/pdo_sqlsrv/MsCommon.inc b/test/pdo_sqlsrv/MsCommon.inc
index 10634abe..d1ec0c43 100644
--- a/test/pdo_sqlsrv/MsCommon.inc
+++ b/test/pdo_sqlsrv/MsCommon.inc
@@ -1201,7 +1201,8 @@ function NumRows($conn, $tableName)
function InsertQuery($tableName)
{
- return (InsertQueryEx($tableName, rand(1, 20)));
+ include_once 'MsData_UTF8.inc';
+ return (InsertQueryExUTF8($tableName, rand(1, 20)));
}
function InsertRows($conn, $tableName, $rowCount)
@@ -1535,94 +1536,4 @@ function PhpVersionComponents( &$major, &$minor, &$sub )
$minor = strtok( "." );
$sub = strtok( "." );
}
-
-function InsertQueryEx($tableName, $index)
-{
- $query = "";
- switch ($index)
- {
- case 1:
- $query = "INSERT INTO [$tableName] ([c1_int], [c2_tinyint], [c3_smallint], [c4_bigint], [c5_bit], [c6_float], [c7_real], [c8_decimal], [c9_numeric], [c10_money], [c11_smallmoney], [c12_char], [c13_varchar], [c14_varchar_max], [c15_nchar], [c16_nvarchar], [c17_nvarchar_max], [c18_text], [c19_ntext], [c20_binary], [c21_varbinary], [c22_varbinary_max], [c23_image], [c24_uniqueidentifier], [c25_datetime], [c26_smalldatetime], [c28_xml]) VALUES ((0), (113), (-1), (-293433712), (0), (0), (-3.4E+38), (100000000000000000000000), (null), (0.4204), (0.5017), (' bzbo>o~bh~Bߩ+~AZ>~C_<@:O/v~bA|/o :+~*CuzrBU/@_zb/UrboZo.Cv,bAuZhbZ֢b
BboZC+֢oO* rrbBB+:>o*/b
,