Microsoft Drivers 3.0 for PHP for SQL Server

This commit is contained in:
icosahedron 2012-03-07 02:49:23 +00:00
parent 9c37a48e57
commit c727ada07e
37 changed files with 10831 additions and 591 deletions

View file

@ -1 +1 @@
Microsoft Drivers for PHP for SQL Server 2.0 Cumulative Update 1
Microsoft Drivers 3.0 for PHP for SQL Server (PDO driver)

View file

@ -1,6 +1,6 @@
* Copyright and License Information *
Copyright 2010 Microsoft Corporation
Copyright Microsoft Corporation
Licensed under the Apache License, Version 2.0 (the "License"); you
may not use this file except in compliance with the License.
@ -14,33 +14,25 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.
* Notes about changes to the Microsoft Drivers for PHP for SQL Server
Driver 2.0 *
* Notes about changes to the Microsoft Drivers 3.0 for PHP for SQL Server *
For details about the changes included in this release, please see our blog at
http://blogs.msdn.com/sqlphp or see the SQLSRV20_Readme.htm
http://blogs.msdn.com/sqlphp or see the SQLSRV_Readme.htm
file that is part of the download package.
* Notes about compiling the Microsoft Drivers for PHP for SQL Server 2.0 *
* Notes about compiling the Microsoft Drivers 3.0 for PHP for SQL Server *
Prerequisites:
* You must first be able to build PHP without including these
extensions. For help with doing this, see xthe official PHP website,
extensions. For help with doing this, see the official PHP website,
http://php.net.
* The header file sqlncli.h is required to build these extensions. It
may be installed with the Microsoft SQL Server® 2008 R2 Native Client
(found at Microsoft.com)
To compile the SQLSRV20 and PDO_SQLSRV20:
To compile the SQLSRV30 and PDO_SQLSRV30:
1) Copy the source code directories from this repository into the ext
subdirectory.
1a) Make sure that sqlncli.h is either on the INCLUDE file path or
copied locally to the extension directories.
2) run buildconf.bat to rebuild the configure.js script to include the
new drivers.
@ -61,8 +53,8 @@ wish to do so, run "nmake clean" first.
php_sqlsrv.dll and php_pdo_sqlsrv.dll to your PHP extension directory.
Also enable them within your PHP installation's php.ini file.
This software has been compiled and tested under PHP 5.2.10 and PHP 5.3.0
using the Visual C++ 2008 Express and Standard compilers.
This software has been compiled and tested under PHP 5.3.6 and later
using the Visual C++ 2008 and 2010, Express and Standard compilers.
* Note about version.h *

View file

@ -3,7 +3,7 @@
//
// Contents: JScript build configuration used by buildconf.bat
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -18,20 +18,21 @@
// limitations under the License.
//----------------------------------------------------------------------------------------------------------------------------------
ARG_WITH("pdo-sqlsrv", "MS SQL Server support for PDO", "no");
ARG_WITH("pdo-sqlsrv", "enable Microsoft Drivers for PHP for SQL Server (PDO driver)", "no");
if( PHP_PDO_SQLSRV != "no" ) {
if (CHECK_LIB("odbc32.lib", "pdo_sqlsrv") && CHECK_LIB("odbccp32.lib", "pdo_sqlsrv") &&
CHECK_LIB("version.lib", "pdo_sqlsrv") && CHECK_LIB("psapi.lib", "pdo_sqlsrv")) {
EXTENSION("pdo_sqlsrv", "pdo_dbh.cpp pdo_init.cpp pdo_stmt.cpp pdo_util.cpp pdo_parser.cpp core_init.cpp core_conn.cpp core_stmt.cpp core_util.cpp core_stream.cpp" )
EXTENSION("pdo_sqlsrv", "pdo_dbh.cpp pdo_init.cpp pdo_stmt.cpp pdo_util.cpp pdo_parser.cpp core_init.cpp core_conn.cpp core_stmt.cpp core_util.cpp core_stream.cpp core_results.cpp" )
CHECK_HEADER_ADD_INCLUDE('sql.h', 'CFLAGS_PDO_SQLSRV_ODBC');
CHECK_HEADER_ADD_INCLUDE('sqlext.h', 'CFLAGS_PDO_SQLSRV_ODBC');
ADD_FLAG( 'LDFLAGS_PDO_SQLSRV', '/NXCOMPAT /DYNAMICBASE' );
ADD_FLAG( 'CFLAGS_PDO_SQLSRV', '/EHsc' );
ADD_FLAG( 'CFLAGS_PDO_SQLSRV', '/GS' );
ADD_FLAG( 'CFLAGS_PDO_SQLSRV', '/D ZEND_WIN32_FORCE_INLINE' );
ADD_FLAG( 'CFLAGS_PDO_SQLSRV', '/D _HAS_CPP0X=0' );
ADD_EXTENSION_DEP('pdo_sqlsrv', 'pdo');
}

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use connection handles shared between sqlsrv and pdo_sqlsrv
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -43,7 +43,7 @@ const int INFO_BUFFER_LEN = 256;
const char* PROCESSOR_ARCH[] = { "x86", "x64", "ia64" };
// ODBC driver name.
const char CONNECTION_STRING_DRIVER_NAME[] = "Driver={SQL Server Native Client 10.0};";
const char CONNECTION_STRING_DRIVER_NAME[] = "Driver={SQL Server Native Client 11.0};";
// default options if only the server is specified
const char CONNECTION_STRING_DEFAULT_OPTIONS[] = "Mars_Connection={Yes}";
@ -562,6 +562,20 @@ void build_connection_string_and_set_conn_attr( sqlsrv_conn* conn, const char* s
return;
}
// workaround for a bug in ODBC Driver Manager wherein the Driver Manager creates a 0 KB file
// if the TraceFile option is set, even if the "TraceOn" is not present or the "TraceOn"
// flag is set to false.
if( zend_hash_index_exists( options, SQLSRV_CONN_OPTION_TRACE_FILE )) {
zval** trace_value = NULL;
int zr = zend_hash_index_find( options, SQLSRV_CONN_OPTION_TRACE_ON, (void**)&trace_value );
if( zr == FAILURE || !zend_is_true( *trace_value )) {
zend_hash_index_del( options, SQLSRV_CONN_OPTION_TRACE_FILE );
}
}
for( zend_hash_internal_pointer_reset( options );
zend_hash_has_more_elements( options ) == SUCCESS;
zend_hash_move_forward( options )) {
@ -573,10 +587,10 @@ void build_connection_string_and_set_conn_attr( sqlsrv_conn* conn, const char* s
zval** data = NULL;
type = zend_hash_get_current_key_ex( options, &key, &key_len, &index, 0, NULL );
CHECK_CUSTOM_ERROR(( type != HASH_KEY_IS_LONG ), conn, SQLSRV_ERROR_INVALID_OPTION_KEY ) {
throw core::CoreException();
}
// The driver layer should ensure a valid key.
DEBUG_SQLSRV_ASSERT(( type == HASH_KEY_IS_LONG ), "build_connection_string_and_set_conn_attr: invalid connection option key type." );
core::sqlsrv_zend_hash_get_current_data( *conn, options, (void**) &data TSRMLS_CC );
conn_opt = get_connection_option( conn, index, valid_conn_opts TSRMLS_CC );
@ -660,13 +674,14 @@ void determine_server_version( sqlsrv_conn* conn TSRMLS_DC )
char p[ INFO_BUFFER_LEN ];
core::SQLGetInfo( conn, SQL_DBMS_VER, p, INFO_BUFFER_LEN, &info_len TSRMLS_CC );
errno = 0;
char version_major_str[ 3 ];
SERVER_VERSION version_major;
memcpy( version_major_str, p, 2 );
version_major_str[ 2 ] = '\0';
version_major = static_cast<SERVER_VERSION>( atoi( version_major_str ));
CHECK_CUSTOM_ERROR( version_major == 0 || errno == ERANGE || errno == EINVAL, conn, SQLSRV_ERROR_UNKNOWN_SERVER_VERSION )
CHECK_CUSTOM_ERROR( version_major == 0 && ( errno == ERANGE || errno == EINVAL ), conn, SQLSRV_ERROR_UNKNOWN_SERVER_VERSION )
{
throw core::CoreException();
}

View file

@ -3,7 +3,7 @@
//
// Contents: common initialization routines shared by PDO and sqlsrv
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

1338
pdo_sqlsrv/core_results.cpp Normal file
View file

@ -0,0 +1,1338 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: core_results.cpp
//
// Contents: Result sets
//
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at:
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//---------------------------------------------------------------------------------------------------------------------------------
#include "core_sqlsrv.h"
#include <functional>
#include <iostream>
#include <sstream>
using namespace core;
// conversion matrix
// each entry holds a function that can perform the conversion or NULL which means the conversion isn't supported
// this is initialized the first time the buffered result set is created.
sqlsrv_buffered_result_set::conv_matrix_t sqlsrv_buffered_result_set::conv_matrix;
namespace {
// *** internal types ***
#pragma warning(disable:4200)
// *** internal constants ***
const int INITIAL_FIELD_STRING_LEN = 256; // base allocation size when retrieving a string field
// *** internal functions ***
// return an integral type rounded up to a certain number
template <int align, typename T>
T align_to( T number )
{
DEBUG_SQLSRV_ASSERT( (number + align) > number, "Number to align overflowed" );
return ((number % align) == 0) ? number : (number + align - (number % align));
}
// return a pointer address aligned to a certain address boundary
template <int align, typename T>
T* align_to( T* ptr )
{
size_t p_value = (size_t) ptr;
return align_to<align, size_t>( p_value );
}
// set the nth bit of the bitstream starting at ptr
void set_bit( void* ptr, unsigned int bit )
{
unsigned char* null_bits = reinterpret_cast<unsigned char*>( ptr );
null_bits += bit >> 3;
*null_bits |= 1 << ( 7 - ( bit & 0x7 ));
}
// retrieve the nth bit from the bitstream starting at ptr
bool get_bit( void* ptr, unsigned int bit )
{
unsigned char* null_bits = reinterpret_cast<unsigned char*>( ptr );
null_bits += bit >> 3;
return ((*null_bits & (1 << ( 7 - ( bit & 0x07 )))) != 0);
}
// read in LOB field during buffered result creation
SQLPOINTER read_lob_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_buffered_result_set::meta_data& meta,
unsigned long mem_used TSRMLS_DC );
// dtor for each row in the cache
void cache_row_dtor( void* data );
// convert a number to a string using locales
// There is an extra copy here, but given the size is short (usually <20 bytes) and the complications of
// subclassing a new streambuf just to avoid the copy, it's easier to do the copy
template <typename Char, typename Number>
SQLRETURN number_to_string( Number* number_data, __out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& last_error )
{
std::basic_ostringstream<Char> os;
std::locale loc;
os.imbue( loc );
std::use_facet< std::num_put< Char > >( loc ).put( std::basic_ostream<Char>::_Iter( os.rdbuf() ), os, ' ', *number_data );
std::basic_string<Char>& str_num = os.str();
if( os.fail() ) {
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error(
(SQLCHAR*) "IMSSP", (SQLCHAR*) "Failed to convert number to string", -1 );
return SQL_ERROR;
}
if( str_num.size() * sizeof(Char) + sizeof(Char) > (size_t) buffer_length ) {
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error(
(SQLCHAR*) "HY090", (SQLCHAR*) "Buffer length too small to hold number as string", -1 );
return SQL_ERROR;
}
*out_buffer_length = str_num.size() * sizeof(Char) + sizeof(Char); // include NULL terminator
memcpy( buffer, str_num.c_str(), *out_buffer_length );
return SQL_SUCCESS;
}
template <typename Number, typename Char>
SQLRETURN string_to_number( Char* string_data, SQLLEN str_len, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length, sqlsrv_error_auto_ptr& last_error )
{
Number* number_data = reinterpret_cast<Number*>( buffer );
std::locale loc; // default locale should match system
std::basic_istringstream<Char> is;
is.str( string_data );
is.imbue( loc );
std::ios_base::iostate st = 0;
std::use_facet< std::num_get< Char > >( loc ).get( std::basic_istream<Char>::_Iter( is.rdbuf( ) ),
std::basic_istream<Char>::_Iter(0), is, st, *number_data );
if( st & std::ios_base::failbit ) {
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error(
(SQLCHAR*) "22003", (SQLCHAR*) "Numeric value out of range", 103 );
return SQL_ERROR;
}
*out_buffer_length = sizeof( Number );
return SQL_SUCCESS;
}
// "closure" for the hash table destructor
struct row_dtor_closure {
sqlsrv_buffered_result_set* results;
BYTE* row_data;
row_dtor_closure( sqlsrv_buffered_result_set* st, BYTE* row ) :
results( st ), row_data( row )
{
}
};
sqlsrv_error* odbc_get_diag_rec( sqlsrv_stmt* odbc, SQLSMALLINT record_number )
{
SQLWCHAR wsql_state[ SQL_SQLSTATE_BUFSIZE ];
SQLCHAR* sql_state = reinterpret_cast<SQLCHAR*>( wsql_state );
SQLWCHAR wnative_message[ SQL_MAX_MESSAGE_LENGTH + 1 ];
sqlsrv_malloc_auto_ptr<SQLCHAR> native_message;
SQLINTEGER native_code;
SQLINTEGER message_len;
SQLRETURN r = SQLGetDiagRecW( SQL_HANDLE_STMT, odbc->handle(), record_number, wsql_state, &native_code, wnative_message,
SQL_MAX_MESSAGE_LENGTH + 1, NULL );
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
return NULL;
}
// convert the error into the encoding of the context
SQLSRV_ENCODING enc = odbc->encoding();
if( enc == SQLSRV_ENCODING_DEFAULT ) {
enc = odbc->conn->encoding();
}
// convert the error into the encoding of the context
message_len = SQL_SQLSTATE_BUFSIZE * sizeof(WCHAR);
convert_string_from_utf16( enc, reinterpret_cast<char**>( &sql_state ), message_len,
false /*no free*/ );
message_len = (SQL_MAX_MESSAGE_LENGTH + 1) * sizeof( WCHAR );
native_message = reinterpret_cast<SQLCHAR*>( wnative_message );
convert_string_from_utf16( enc, reinterpret_cast<char**>( &native_message ), message_len,
false /*no free*/ );
return new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) sql_state, (SQLCHAR*) native_message,
native_code );
}
} // namespace
// base class result set
sqlsrv_result_set::sqlsrv_result_set( sqlsrv_stmt* stmt ) :
odbc( stmt )
{
}
// ODBC result set
// This object simply wraps ODBC function calls
sqlsrv_odbc_result_set::sqlsrv_odbc_result_set( sqlsrv_stmt* stmt ) :
sqlsrv_result_set( stmt )
{
}
sqlsrv_odbc_result_set::~sqlsrv_odbc_result_set( void )
{
}
SQLRETURN sqlsrv_odbc_result_set::fetch( SQLSMALLINT orientation, SQLLEN offset TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLFetchScroll( odbc, orientation, offset TSRMLS_CC );
}
SQLRETURN sqlsrv_odbc_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out SQLPOINTER buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLGetData( odbc, field_index, target_type, buffer, buffer_length, out_buffer_length, handle_warning TSRMLS_CC );
}
SQLRETURN sqlsrv_odbc_result_set::get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLGetDiagField( odbc, record_number, diag_identifier, diag_info_buffer, buffer_length,
out_buffer_length TSRMLS_CC );
}
sqlsrv_error* sqlsrv_odbc_result_set::get_diag_rec( SQLSMALLINT record_number )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return odbc_get_diag_rec( odbc, record_number );
}
SQLLEN sqlsrv_odbc_result_set::row_count( TSRMLS_D )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLRowCount( odbc TSRMLS_CC );
}
// Buffered result set
// This class holds a result set in memory
sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS_DC ) :
sqlsrv_result_set( stmt ),
cache(NULL),
col_count(0),
meta(NULL),
current(0),
last_field_index(-1),
read_so_far(0)
{
// 10 is an arbitrary number for now for the initial size of the cache
ALLOC_HASHTABLE( cache );
core::sqlsrv_zend_hash_init( *stmt, cache, 10 /* # of buckets */, NULL /* hashfn */, cache_row_dtor /*dtor*/, 0 /*persistent*/
TSRMLS_CC );
col_count = core::SQLNumResultCols( stmt TSRMLS_CC );
// there is no result set to buffer
if( col_count == 0 ) {
return;
}
SQLULEN null_bytes = ( col_count / 8 ) + 1; // number of bits to reserve at the beginning of each row for NULL flags
meta = static_cast<sqlsrv_buffered_result_set::meta_data*>( sqlsrv_malloc( col_count *
sizeof( sqlsrv_buffered_result_set::meta_data )));
// set up the conversion matrix if this is the first time we're called
if( conv_matrix.size() == 0 ) {
conv_matrix[ SQL_C_CHAR ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::to_same_string;
conv_matrix[ SQL_C_CHAR ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::system_to_wide_string;
conv_matrix[ SQL_C_CHAR ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_binary_string;
conv_matrix[ SQL_C_CHAR ][ SQL_C_DOUBLE ] = &sqlsrv_buffered_result_set::string_to_double;
conv_matrix[ SQL_C_CHAR ][ SQL_C_LONG ] = &sqlsrv_buffered_result_set::string_to_long;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::to_same_string;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_binary_string;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::wide_to_system_string;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_DOUBLE ] = &sqlsrv_buffered_result_set::wstring_to_double;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_LONG ] = &sqlsrv_buffered_result_set::wstring_to_long;
conv_matrix[ SQL_C_BINARY ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_same_string;
conv_matrix[ SQL_C_BINARY ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::binary_to_system_string;
conv_matrix[ SQL_C_BINARY ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::binary_to_wide_string;
conv_matrix[ SQL_C_LONG ][ SQL_C_DOUBLE ] = &sqlsrv_buffered_result_set::long_to_double;
conv_matrix[ SQL_C_LONG ][ SQL_C_LONG ] = &sqlsrv_buffered_result_set::to_long;
conv_matrix[ SQL_C_LONG ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_long;
conv_matrix[ SQL_C_LONG ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::long_to_system_string;
conv_matrix[ SQL_C_LONG ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::long_to_wide_string;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_DOUBLE ] = &sqlsrv_buffered_result_set::to_double;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_double;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::double_to_system_string;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_LONG ] = &sqlsrv_buffered_result_set::double_to_long;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::double_to_wide_string;
}
// get the meta data and calculate the size of a row buffer
SQLULEN offset = null_bytes;
for( SQLSMALLINT i = 0; i < col_count; ++i ) {
core::SQLDescribeCol( stmt, i + 1, NULL, 0, NULL, &meta[i].type, &meta[i].length, &meta[i].scale, NULL TSRMLS_CC );
offset = align_to<4>( offset );
meta[i].offset = offset;
switch( meta[i].type ) {
// these types are the display size
case SQL_BIGINT:
case SQL_DECIMAL:
case SQL_GUID:
case SQL_NUMERIC:
core::SQLColAttribute( stmt, i + 1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL,
reinterpret_cast<SQLLEN*>( &meta[i].length ) TSRMLS_CC );
meta[i].length += sizeof( char ) + sizeof( SQLULEN ); // null terminator space
offset += meta[i].length;
break;
// these types are the column size
case SQL_BINARY:
case SQL_CHAR:
case SQL_SS_UDT:
case SQL_VARBINARY:
case SQL_VARCHAR:
// var* field types are length prefixed
if( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
offset += sizeof( void* );
}
else {
meta[i].length += sizeof( SQLULEN ) + sizeof( char ); // length plus null terminator space
offset += meta[i].length;
}
break;
case SQL_WCHAR:
case SQL_WVARCHAR:
if( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
offset += sizeof( void* );
}
else {
meta[i].length *= sizeof( WCHAR );
meta[i].length += sizeof( SQLULEN ) + sizeof( WCHAR ); // length plus null terminator space
offset += meta[i].length;
}
break;
// these types are LOBs
case SQL_LONGVARBINARY:
case SQL_LONGVARCHAR:
case SQL_WLONGVARCHAR:
case SQL_SS_XML:
meta[i].length = sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN;
offset += sizeof( void* );
break;
// these types are the ISO date size
case SQL_DATETIME:
case SQL_TYPE_DATE:
case SQL_SS_TIME2:
case SQL_SS_TIMESTAMPOFFSET:
case SQL_TYPE_TIMESTAMP:
core::SQLColAttribute( stmt, i + 1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL,
reinterpret_cast<SQLLEN*>( &meta[i].length ) TSRMLS_CC );
meta[i].length += sizeof(char) + sizeof( SQLULEN ); // null terminator space
offset += meta[i].length;
break;
// these types are the native size
case SQL_BIT:
case SQL_INTEGER:
case SQL_SMALLINT:
case SQL_TINYINT:
meta[i].length = sizeof( long );
offset += meta[i].length;
break;
case SQL_REAL:
case SQL_FLOAT:
meta[i].length = sizeof( double );
offset += meta[i].length;
break;
default:
SQLSRV_ASSERT( false, "Unknown type in sqlsrv_buffered_query::sqlsrv_buffered_query" );
break;
}
switch( meta[i].type ) {
case SQL_BIGINT:
case SQL_CHAR:
case SQL_DATETIME:
case SQL_DECIMAL:
case SQL_GUID:
case SQL_NUMERIC:
case SQL_LONGVARCHAR:
case SQL_TYPE_DATE:
case SQL_SS_TIME2:
case SQL_SS_TIMESTAMPOFFSET:
case SQL_SS_XML:
case SQL_TYPE_TIMESTAMP:
case SQL_VARCHAR:
meta[i].c_type = SQL_C_CHAR;
break;
case SQL_SS_UDT:
case SQL_LONGVARBINARY:
case SQL_BINARY:
case SQL_VARBINARY:
meta[i].c_type = SQL_C_BINARY;
break;
case SQL_WLONGVARCHAR:
case SQL_WCHAR:
case SQL_WVARCHAR:
meta[i].c_type = SQL_C_WCHAR;
break;
case SQL_BIT:
case SQL_INTEGER:
case SQL_SMALLINT:
case SQL_TINYINT:
meta[i].c_type = SQL_C_LONG;
break;
case SQL_REAL:
case SQL_FLOAT:
meta[i].c_type = SQL_C_DOUBLE;
break;
default:
SQLSRV_ASSERT( false, "Unknown type in sqlsrv_buffered_query::sqlsrv_buffered_query" );
break;
}
}
// read the data into the cache
// (offset from the above loop has the size of the row buffer necessary)
unsigned long mem_used = 0;
unsigned long row_count = 0;
while( core::SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 TSRMLS_CC ) != SQL_NO_DATA ) {
// allocate the row buffer
unsigned char* row = static_cast<unsigned char*>( sqlsrv_malloc( offset ));
memset( row, 0, offset );
// read the fields into the row buffer
for( SQLSMALLINT i = 0; i < col_count; ++i ) {
SQLLEN out_buffer_temp = SQL_NULL_DATA;
SQLPOINTER buffer;
SQLLEN* out_buffer_length = &out_buffer_temp;
switch( meta[i].c_type ) {
case SQL_C_CHAR:
case SQL_C_WCHAR:
case SQL_C_BINARY:
if( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
out_buffer_length = &out_buffer_temp;
SQLPOINTER* lob_addr = reinterpret_cast<SQLPOINTER*>( &row[ meta[i].offset ] );
*lob_addr = read_lob_field( stmt, i, meta[i], mem_used TSRMLS_CC );
// a NULL pointer means NULL field
if( *lob_addr == NULL ) {
*out_buffer_length = SQL_NULL_DATA;
}
else {
*out_buffer_length = **reinterpret_cast<SQLLEN**>( lob_addr );
mem_used += *out_buffer_length;
}
}
else {
mem_used += meta[i].length;
CHECK_CUSTOM_ERROR( mem_used > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
buffer = row + meta[i].offset + sizeof( SQLULEN );
out_buffer_length = reinterpret_cast<SQLLEN*>( row + meta[i].offset );
core::SQLGetData( stmt, i + 1, meta[i].c_type, buffer, meta[i].length, out_buffer_length,
false TSRMLS_CC );
}
break;
case SQL_C_LONG:
case SQL_C_DOUBLE:
{
mem_used += meta[i].length;
CHECK_CUSTOM_ERROR( mem_used > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
buffer = row + meta[i].offset;
out_buffer_length = &out_buffer_temp;
core::SQLGetData( stmt, i + 1, meta[i].c_type, buffer, meta[i].length, out_buffer_length,
false TSRMLS_CC );
}
break;
default:
SQLSRV_ASSERT( false, "Unknown C type" );
break;
}
if( *out_buffer_length == SQL_NULL_DATA ) {
unsigned char* null_bits = reinterpret_cast<unsigned char*>( row );
set_bit( row, i );
}
}
SQLSRV_ASSERT( row_count < LONG_MAX, "Hard maximum of 2 billion rows exceeded in a buffered query" );
// add it to the cache
row_dtor_closure cl( this, row );
sqlsrv_zend_hash_next_index_insert( *stmt, cache, &cl, sizeof( cl ) TSRMLS_CC );
}
}
sqlsrv_buffered_result_set::~sqlsrv_buffered_result_set( void )
{
// free the rows
if( cache ) {
zend_hash_destroy( cache );
FREE_HASHTABLE( cache );
cache = NULL;
}
// free the meta data
if( meta ) {
efree( meta );
meta = NULL;
}
}
SQLRETURN sqlsrv_buffered_result_set::fetch( SQLSMALLINT orientation, SQLLEN offset TSRMLS_DC )
{
last_error = NULL;
last_field_index = -1;
read_so_far = 0;
switch( orientation ) {
case SQL_FETCH_NEXT:
offset = 1;
orientation = SQL_FETCH_RELATIVE;
break;
case SQL_FETCH_PRIOR:
offset = -1;
orientation = SQL_FETCH_RELATIVE;
break;
}
switch( orientation ) {
case SQL_FETCH_FIRST:
current = 1;
break;
case SQL_FETCH_LAST:
current = row_count( TSRMLS_C );
break;
case SQL_FETCH_ABSOLUTE:
current = offset;
break;
case SQL_FETCH_RELATIVE:
current += offset;
break;
default:
SQLSRV_ASSERT( false, "Invalid fetch orientation. Should have been caught before here." );
break;
}
// check validity of current row
// the cursor can never get further away than just before the first row
if( current <= 0 && ( offset < 0 || orientation != SQL_FETCH_RELATIVE )) {
current = 0;
return SQL_NO_DATA;
}
// the cursor can never get further away than just after the last row
if( current > row_count( TSRMLS_C ) || ( current <= 0 && offset > 0 ) /*overflow condition*/ ) {
current = row_count( TSRMLS_C ) + 1;
return SQL_NO_DATA;
}
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out SQLPOINTER buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
last_error = NULL;
field_index--; // convert from 1 based to 0 based
SQLSRV_ASSERT( field_index < column_count(), "Invalid field index requested" );
if( field_index != last_field_index ) {
last_field_index = field_index;
read_so_far = 0;
}
unsigned char* row = get_row();
// if the field is null, then return SQL_NULL_DATA
if( get_bit( row, field_index )) {
*out_buffer_length = SQL_NULL_DATA;
return SQL_SUCCESS;
}
// check to make sure the conversion type is valid
if( conv_matrix.find( meta[ field_index ].c_type ) == conv_matrix.end() ||
conv_matrix.find( meta[ field_index ].c_type )->second.find( target_type ) ==
conv_matrix.find( meta[ field_index ].c_type )->second.end() ) {
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "07006",
(SQLCHAR*) "Restricted data type attribute violation", 0 );
return SQL_ERROR;
}
return (( this )->*( conv_matrix[ meta[ field_index ].c_type ][ target_type ] ))( field_index, buffer, buffer_length,
out_buffer_length );
}
SQLRETURN sqlsrv_buffered_result_set::get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC )
{
SQLSRV_ASSERT( record_number == 1, "Only record number 1 can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
SQLSRV_ASSERT( diag_identifier == SQL_DIAG_SQLSTATE,
"Only SQL_DIAG_SQLSTATE can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
SQLSRV_ASSERT( buffer_length >= SQL_SQLSTATE_BUFSIZE,
"Buffer not big enough to return SQLSTATE in sqlsrv_buffered_result_set::get_diag_field" );
if( last_error == NULL ) {
return SQL_NO_DATA;
}
SQLSRV_ASSERT( last_error->sqlstate != NULL,
"Must have a SQLSTATE in a valid last_error in sqlsrv_buffered_result_set::get_diag_field" );
memcpy( diag_info_buffer, last_error->sqlstate, min( buffer_length, SQL_SQLSTATE_BUFSIZE ));
return SQL_SUCCESS;
}
unsigned char* sqlsrv_buffered_result_set::get_row( void )
{
row_dtor_closure* cl_ptr;
int zr = zend_hash_index_find( cache, current - 1, (void**) &cl_ptr );
SQLSRV_ASSERT( zr == SUCCESS, "Failed to find row %1!d! in the cache", current );
return cl_ptr->row_data;
}
sqlsrv_error* sqlsrv_buffered_result_set::get_diag_rec( SQLSMALLINT record_number )
{
// we only hold a single error if there is one, otherwise return the ODBC error(s)
if( last_error == NULL ) {
return odbc_get_diag_rec( odbc, record_number );
}
if( record_number > 1 ) {
return NULL;
}
return new (sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( last_error->sqlstate, last_error->native_message, last_error->native_code );
}
SQLLEN sqlsrv_buffered_result_set::row_count( TSRMLS_D )
{
last_error = NULL;
return zend_hash_num_elements( cache );
}
// private functions
template <typename Char>
SQLRETURN binary_to_string( SQLCHAR* field_data, SQLLEN& read_so_far, __out void* buffer,
SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& out_error )
{
// hex characters for the conversion loop below
static char hex_chars[] = "0123456789ABCDEF";
SQLSRV_ASSERT( out_error == NULL, "Pending error for sqlsrv_buffered_results_set::binary_to_string" );
SQLRETURN r = SQL_ERROR;
// Set the amount of space necessary for null characters at the end of the data.
SQLSMALLINT extra = sizeof(Char);
SQLSRV_ASSERT( ((buffer_length - extra) % (extra * 2)) == 0, "Must be multiple of 2 for binary to system string or "
"multiple of 4 for binary to wide string" );
// all fields will be treated as ODBC returns varchar(max) fields:
// the entire length of the string is returned the first
// call in out_buffer_len. Successive calls return how much is
// left minus how much has already been read by previous reads
// *2 is for each byte to hex conversion and * extra is for either system or wide string allocation
*out_buffer_length = (*reinterpret_cast<SQLLEN*>( field_data - sizeof( SQLULEN )) - read_so_far) * 2 * extra;
// copy as much as we can into the buffer
SQLLEN to_copy;
if( buffer_length < *out_buffer_length + extra ) {
to_copy = (buffer_length - extra);
out_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
r = SQL_SUCCESS_WITH_INFO;
}
else {
r = SQL_SUCCESS;
to_copy = *out_buffer_length;
}
// if there are bytes to copy as hex
if( to_copy > 0 ) {
// quick hex conversion routine
Char* h = reinterpret_cast<Char*>( buffer );
BYTE* b = reinterpret_cast<BYTE*>( field_data );
// to_copy contains the number of bytes to copy, so we divide the number in half (or quarter)
// to get the number of hex digits we can copy
SQLLEN to_copy_hex = to_copy / (2 * extra);
for( int i = 0; i < to_copy_hex; ++i ) {
*h = hex_chars[ (*b & 0xf0) >> 4 ];
h++;
*h = hex_chars[ (*b++ & 0x0f) ];
h++;
}
read_so_far += to_copy_hex;
*h = static_cast<Char>( 0 );
}
else {
reinterpret_cast<char*>( buffer )[0] = '\0';
}
return r;
}
SQLRETURN sqlsrv_buffered_result_set::binary_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
}
else {
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN );
}
return binary_to_string<char>( field_data, read_so_far, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::binary_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
}
else {
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN );
}
return binary_to_string<WCHAR>( field_data, read_so_far, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::double_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof(LONG), "Buffer length must be able to find a long in "
"sqlsrv_buffered_result_set::double_to_long" );
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
LONG* long_data = reinterpret_cast<LONG*>( buffer );
if( *double_data < double( LONG_MIN ) || *double_data > double( LONG_MAX )) {
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) "22003",
(SQLCHAR*) "Numeric value out of range", 0 );
return SQL_ERROR;
}
if( *double_data != floor( *double_data )) {
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) "01S07",
(SQLCHAR*) "Fractional truncation", 0 );
return SQL_SUCCESS_WITH_INFO;
}
*long_data = static_cast<LONG>( *double_data );
*out_buffer_length = sizeof( LONG );
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::double_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to system string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::double_to_system_string" );
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
return number_to_string<char>( double_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::double_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to wide string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::double_to_wide_string" );
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
return number_to_string<WCHAR>( double_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::long_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof(double), "Buffer length must be able to find a long in sqlsrv_buffered_result_set::double_to_long" );
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( buffer );
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
*double_data = static_cast<LONG>( *long_data );
*out_buffer_length = sizeof( double );
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::long_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to system string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::long_to_system_string" );
unsigned char* row = get_row();
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
return number_to_string<char>( long_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::long_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to wide string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::long_to_wide_string" );
unsigned char* row = get_row();
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
return number_to_string<WCHAR>( long_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::string_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_CHAR, "Invalid conversion from string to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer needs to be big enough to hold a double" );
unsigned char* row = get_row();
char* string_data = reinterpret_cast<char*>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
return string_to_number<double>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::wstring_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_WCHAR, "Invalid conversion from wide string to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer needs to be big enough to hold a double" );
unsigned char* row = get_row();
SQLWCHAR* string_data = reinterpret_cast<SQLWCHAR*>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN ) / sizeof( SQLWCHAR );
return string_to_number<double>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::string_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_CHAR, "Invalid conversion from string to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer needs to be big enough to hold a long" );
unsigned char* row = get_row();
char* string_data = reinterpret_cast<char*>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
return string_to_number<LONG>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::wstring_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_WCHAR, "Invalid conversion from wide string to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer needs to be big enough to hold a long" );
unsigned char* row = get_row();
SQLWCHAR* string_data = reinterpret_cast<SQLWCHAR*>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN ) / sizeof( SQLWCHAR );
return string_to_number<LONG>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::system_to_wide_string" );
SQLSRV_ASSERT( buffer_length % 2 == 0, "Odd buffer length passed to sqlsrv_buffered_result_set::system_to_wide_string" );
SQLRETURN r = SQL_ERROR;
unsigned char* row = get_row();
SQLCHAR* field_data = NULL;
SQLULEN field_len = NULL;
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_len = **reinterpret_cast<SQLLEN**>( &row[ meta[ field_index ].offset ] );
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN ) + read_so_far;
}
else {
field_len = *reinterpret_cast<SQLLEN*>( &row[ meta[ field_index ].offset ] );
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN ) + read_so_far;
}
// all fields will be treated as ODBC returns varchar(max) fields:
// the entire length of the string is returned the first
// call in out_buffer_len. Successive calls return how much is
// left minus how much has already been read by previous reads
*out_buffer_length = (*reinterpret_cast<SQLLEN*>( field_data - sizeof( SQLULEN )) - read_so_far) * sizeof(WCHAR);
// to_copy is the number of characters to copy, not including the null terminator
// supposedly it will never happen that a Windows MBCS will explode to UTF-16 surrogate pair.
SQLLEN to_copy;
if( (size_t) buffer_length < (field_len - read_so_far + sizeof(char)) * sizeof(WCHAR)) {
to_copy = (buffer_length - sizeof(WCHAR)) / sizeof(WCHAR); // to_copy is the number of characters
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
r = SQL_SUCCESS_WITH_INFO;
}
else {
r = SQL_SUCCESS;
to_copy = field_len - read_so_far;
}
if( to_copy > 0 ) {
bool tried_again = false;
do {
int ch_space = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS, (LPCSTR) field_data, to_copy,
(LPWSTR) buffer, to_copy );
if( ch_space == 0 ) {
switch( GetLastError() ) {
case ERROR_NO_UNICODE_TRANSLATION:
// the theory here is the conversion failed because the end of the buffer we provided contained only
// half a character at the end
if( !tried_again ) {
to_copy--;
tried_again = true;
continue;
}
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "IMSSP", (SQLCHAR*) "Invalid Unicode translation", -1 );
break;
default:
SQLSRV_ASSERT( false, "Severe error translating Unicode" );
break;
}
return SQL_ERROR;
}
((WCHAR*)buffer)[ to_copy ] = L'\0';
read_so_far += to_copy;
break;
} while( true );
}
else {
reinterpret_cast<WCHAR*>( buffer )[0] = L'\0';
}
return r;
}
SQLRETURN sqlsrv_buffered_result_set::to_same_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::to_same_string" );
SQLRETURN r = SQL_ERROR;
unsigned char* row = get_row();
// Set the amount of space necessary for null characters at the end of the data.
SQLSMALLINT extra = 0;
switch( meta[ field_index ].c_type ) {
case SQL_C_WCHAR:
extra = sizeof( SQLWCHAR );
break;
case SQL_C_BINARY:
extra = 0;
break;
case SQL_C_CHAR:
extra = sizeof( SQLCHAR );
break;
default:
SQLSRV_ASSERT( false, "Invalid type in get_string_data" );
break;
}
SQLCHAR* field_data = NULL;
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
}
else {
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN );
}
// all fields will be treated as ODBC returns varchar(max) fields:
// the entire length of the string is returned the first
// call in out_buffer_len. Successive calls return how much is
// left minus how much has already been read by previous reads
*out_buffer_length = *reinterpret_cast<SQLLEN*>( field_data - sizeof( SQLULEN )) - read_so_far;
// copy as much as we can into the buffer
SQLLEN to_copy;
if( buffer_length < *out_buffer_length + extra ) {
to_copy = buffer_length - extra;
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
r = SQL_SUCCESS_WITH_INFO;
}
else {
r = SQL_SUCCESS;
to_copy = *out_buffer_length;
}
SQLSRV_ASSERT( to_copy >= 0, "Negative field length calculated in buffered result set" );
if( to_copy > 0 ) {
memcpy( buffer, field_data + read_so_far, to_copy );
read_so_far += to_copy;
}
if( extra ) {
OACR_WARNING_SUPPRESS( 26001, "Buffer length verified above" );
memcpy( reinterpret_cast<SQLCHAR*>( buffer ) + to_copy, L"\0", extra );
}
return r;
}
SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::wide_to_system_string" );
SQLRETURN r = SQL_ERROR;
unsigned char* row = get_row();
SQLCHAR* field_data = NULL;
SQLULEN field_len = NULL;
// if this is the first time called for this field, just convert the entire string to system first then
// use that to read from instead of converting chunk by chunk. This is because it's impossible to know
// the total length of the string for output_buffer_length without doing the conversion and returning
// SQL_NO_TOTAL is not consistent with what our other conversion functions do (system_to_wide_string and
// to_same_string).
if( read_so_far == 0 ) {
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_len = **reinterpret_cast<SQLLEN**>( &row[ meta[ field_index ].offset ] );
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN ) + read_so_far;
}
else {
field_len = *reinterpret_cast<SQLLEN*>( &row[ meta[ field_index ].offset ] );
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN ) + read_so_far;
}
BOOL default_char_used = FALSE;
char default_char = '?';
// allocate enough to handle WC -> DBCS conversion if it happens
temp_string = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( field_len, sizeof( char ), sizeof(char)));
temp_length = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR) field_data, field_len / sizeof(WCHAR),
(LPSTR) temp_string.get(), field_len, &default_char, &default_char_used );
if( temp_length == 0 ) {
switch( GetLastError() ) {
case ERROR_NO_UNICODE_TRANSLATION:
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "IMSSP", (SQLCHAR*) "Invalid Unicode translation", -1 );
break;
default:
SQLSRV_ASSERT( false, "Severe error translating Unicode" );
break;
}
return SQL_ERROR;
}
}
*out_buffer_length = (temp_length - read_so_far);
SQLLEN to_copy = 0;
if( (size_t) buffer_length < (temp_length - read_so_far + sizeof(char))) {
to_copy = buffer_length - sizeof(char);
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
r = SQL_SUCCESS_WITH_INFO;
}
else {
to_copy = (temp_length - read_so_far);
r = SQL_SUCCESS;
}
if( to_copy > 0 ) {
memcpy( buffer, temp_string.get() + read_so_far, to_copy );
}
SQLSRV_ASSERT( to_copy >= 0, "Invalid field copy length" );
OACR_WARNING_SUPPRESS( BUFFER_UNDERFLOW, "Buffer length verified above" );
((SQLCHAR*) buffer)[ to_copy ] = '\0';
read_so_far += to_copy;
return r;
}
SQLRETURN sqlsrv_buffered_result_set::to_binary_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
return to_same_string( field_index, buffer, buffer_length, out_buffer_length );
}
SQLRETURN sqlsrv_buffered_result_set::to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invlid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer too small for SQL_C_LONG" ); // technically should ignore this
unsigned char* row = get_row();
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
memcpy( buffer, long_data, sizeof( LONG ));
*out_buffer_length = sizeof( LONG );
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invlid conversion to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer too small for SQL_C_DOUBLE" ); // technically should ignore this
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
memcpy( buffer, double_data, sizeof( double ));
*out_buffer_length = sizeof( double );
return SQL_SUCCESS;
}
namespace {
// called for each row in the cache when the cache is destroyed in the destructor
void cache_row_dtor( void* data )
{
row_dtor_closure* cl = reinterpret_cast<row_dtor_closure*>( data );
BYTE* row = cl->row_data;
// don't release this here, since this is called from the destructor of the result_set
sqlsrv_buffered_result_set* result_set = cl->results;
for( SQLSMALLINT i = 0; i < result_set->column_count(); ++i ) {
if( result_set->col_meta_data(i).length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
void* out_of_row_data = *reinterpret_cast<void**>( &row[ result_set->col_meta_data(i).offset ] );
sqlsrv_free( out_of_row_data );
}
}
sqlsrv_free( row );
}
SQLPOINTER read_lob_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_buffered_result_set::meta_data& meta,
unsigned long mem_used TSRMLS_DC )
{
SQLSMALLINT extra = 0;
SQLLEN* output_buffer_len = NULL;
// Set the amount of space necessary for null characters at the end of the data.
switch( meta.c_type ) {
case SQL_C_WCHAR:
extra = sizeof( SQLWCHAR );
break;
case SQL_C_BINARY:
extra = 0;
break;
case SQL_C_CHAR:
extra = sizeof( SQLCHAR );
break;
default:
SQLSRV_ASSERT( false, "Invalid type in read_lob_field" );
break;
}
SQLLEN already_read = 0;
SQLLEN to_read = INITIAL_FIELD_STRING_LEN;
sqlsrv_malloc_auto_ptr<char> buffer;
buffer = static_cast<char*>( sqlsrv_malloc( INITIAL_FIELD_STRING_LEN + extra + sizeof( SQLULEN )));
SQLRETURN r = SQL_SUCCESS;
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
SQLLEN last_field_len = 0;
bool full_length_returned = false;
do {
output_buffer_len = reinterpret_cast<SQLLEN*>( buffer.get() );
r = core::SQLGetData( stmt, field_index + 1, meta.c_type, buffer.get() + already_read + sizeof( SQLULEN ),
to_read - already_read + extra, &last_field_len, false /*handle_warning*/ TSRMLS_CC );
// if the field is NULL, then return a NULL pointer
if( last_field_len == SQL_NULL_DATA ) {
return NULL;
}
// if the last read was successful, we're done
if( r == SQL_SUCCESS ) {
// check to make sure we haven't overflown our memory limit
CHECK_CUSTOM_ERROR( mem_used + last_field_len > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
break;
}
// else if it wasn't the truncated warning (01004) then we're done
else if( r == SQL_SUCCESS_WITH_INFO ) {
SQLSMALLINT len;
core::SQLGetDiagField( stmt, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len
TSRMLS_CC );
if( !is_truncated_warning( state )) {
break;
}
}
SQLSRV_ASSERT( SQL_SUCCEEDED( r ), "Unknown SQL error not triggered" );
// if the type of the field returns the total to be read, we use that and preallocate the buffer
if( last_field_len != SQL_NO_TOTAL ) {
CHECK_CUSTOM_ERROR( mem_used + last_field_len > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
already_read += to_read - already_read;
to_read = last_field_len;
buffer.resize( to_read + extra + sizeof( SQLULEN ));
output_buffer_len = reinterpret_cast<SQLLEN*>( buffer.get() );
// record the size of the field since we have it available
*output_buffer_len = last_field_len;
full_length_returned = true;
}
// otherwise allocate another chunk of memory to read in
else {
already_read += to_read - already_read;
to_read *= 2;
CHECK_CUSTOM_ERROR( mem_used + to_read > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
buffer.resize( to_read + extra + sizeof( SQLULEN ));
output_buffer_len = reinterpret_cast<SQLLEN*>( buffer.get() );
}
} while( true );
SQLSRV_ASSERT( output_buffer_len != NULL, "Output buffer not allocated properly" );
// most LOB field types return the total length in the last_field_len, but some field types such as XML
// only return the amount read on the last read
if( !full_length_returned ) {
*output_buffer_len = already_read + last_field_len;
}
char* return_buffer = buffer;
buffer.transferred();
return return_buffer;
}
}

View file

@ -6,7 +6,7 @@
//
// Contents: Core routines and constants shared by the Microsoft Drivers for PHP for SQL Server
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -45,6 +45,10 @@ OACR_WARNING_DISABLE( INDEX_NEGATIVE, "Third party code." )
OACR_WARNING_DISABLE( UNANNOTATED_BUFFER, "Third party code." )
OACR_WARNING_DISABLE( INDEX_UNDERFLOW, "Third party code." )
OACR_WARNING_DISABLE( REALLOCLEAK, "Third party code." )
OACR_WARNING_DISABLE( ALLOC_SIZE_OVERFLOW_WITH_ACCESS, "Third party code." )
#else
// define to eliminate static analysis hints in the code
#define OACR_WARNING_SUPPRESS( warning, msg )
#endif
extern "C" {
@ -88,8 +92,6 @@ OACR_WARNING_POP
#include <sql.h>
#include <sqlext.h>
#include <deque>
#if !defined(WC_ERR_INVALID_CHARS)
// imported from winnls.h as it isn't included by 5.3.0
#define WC_ERR_INVALID_CHARS 0x00000080 // error for invalid chars
@ -101,8 +103,10 @@ OACR_WARNING_POP
#undef inline
#endif
#include <deque>
#include <map>
#include <algorithm>
#include <limits>
#include <cassert>
#include <strsafe.h>
@ -216,10 +220,46 @@ struct sqlsrv_static_assert<true> { static const int value = 1; };
#define SQLSRV_STATIC_ASSERT( c ) (sqlsrv_static_assert<(c) != 0>() )
//*********************************************************************************************************************************
// Logging
//*********************************************************************************************************************************
// log_callback
// a driver specific callback for logging messages
// severity - severity of the message: notice, warning, or error
// msg - the message to log in a FormatMessage style formatting
// print_args - args to the message
typedef void (*log_callback)( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
// each driver must register a log callback. This should be the first thing a driver does.
void core_sqlsrv_register_logger( log_callback );
// a simple wrapper around a PHP error logging function.
void write_to_log( unsigned int severity TSRMLS_DC, const char* msg, ... );
// a macro to make it convenient to use the function.
#define LOG( severity, msg, ...) write_to_log( severity TSRMLS_CC, msg, __VA_ARGS__ )
// mask for filtering which severities are written to the log
enum logging_severity {
SEV_ERROR = 0x01,
SEV_WARNING = 0x02,
SEV_NOTICE = 0x04,
SEV_ALL = -1,
};
// Kill the PHP process and log the message to PHP
void die( const char* msg, ... );
#define DIE( msg, ... ) { die( msg, __VA_ARGS__ ); }
//*********************************************************************************************************************************
// Resource/Memory Management
//*********************************************************************************************************************************
// the macro max is defined and overrides the call to max in the allocator class
#pragma push_macro( "max" )
#undef max
// new memory allocation/free debugging facilities to help us verify that all allocations are being
// released in a timely manner and not just at the end of the script.
// Zend has memory logging and checking, but it can generate a lot of noise for just one extension.
@ -229,36 +269,89 @@ struct sqlsrv_static_assert<true> { static const int value = 1; };
// #define SQLSRV_MEM_DEBUG 1
#if defined( PHP_DEBUG ) && !defined( ZTS ) && defined( SQLSRV_MEM_DEBUG )
// macro to log memory allocation and frees locations and their sizes
inline void* emalloc_trace( size_t size, const char* file, int line )
inline void* sqlsrv_malloc_trace( size_t size, const char* file, int line )
{
void* ptr = emalloc( size );
LOG( SEV_NOTICE, "emalloc returned %4!08x!: %1!d! bytes at %2!s!:%3!d!", size, file, line, ptr );
return ptr;
}
inline void* erealloc_trace( void* original, size_t size, const char* file, int line )
inline void* sqlsrv_malloc_trace( size_t element_count, size_t element_size, size_t extra, const char* file, int line )
{
OACR_WARNING_SUPPRESS( ALLOC_SIZE_OVERFLOW_IN_ALLOC_WRAPPER, "Overflow verified below" );
if(( element_count > 0 && element_size > 0 ) &&
( element_count > element_size * element_count || element_size > element_size * element_count )) {
DIE( "Integer overflow in sqlsrv_malloc" );
}
if( element_size * element_count > element_size * element_count + extra ) {
DIE( "Integer overflow in sqlsrv_malloc" );
}
if( element_size * element_count + extra == 0 ) {
DIE( "Allocation size must be more than 0" );
}
void* ptr = emalloc( element_size * element_count + extra );
LOG( SEV_NOTICE, "emalloc returned %4!08x!: %1!d! bytes at %2!s!:%3!d!", size, file, line, ptr );
return ptr;
}
inline void* sqlsrv_realloc_trace( void* buffer, size_t size, const char* file, int line )
{
void* ptr = erealloc( original, size );
LOG( SEV_NOTICE, "erealloc returned %5!08x! from %4!08x!: %1!d! bytes at %2!s!:%3!d!", size, file, line, ptr, original );
return ptr;
}
inline void efree_trace( void* ptr, const char* file, int line )
inline void sqlsrv_free_trace( void* ptr, const char* file, int line )
{
LOG( SEV_NOTICE, "efree %1!08x! at %2!s!:%3!d!", ptr, file, line );
efree( ptr );
}
#define sqlsrv_malloc( size ) emalloc_trace( size, __FILE__, __LINE__ )
#define sqlsrv_realloc( buffer, size ) erealloc_trace( buffer, size, __FILE__, __LINE__ )
#define sqlsrv_free( ptr ) efree_trace( ptr, __FILE__, __LINE__ )
#define sqlsrv_malloc( size ) sqlsrv_malloc_trace( size, __FILE__, __LINE__ )
#define sqlsrv_malloc( count, size, extra ) sqlsrv_malloc_trace( count, size, extra, __FILE__, __LINE__ )
#define sqlsrv_realloc( buffer, size ) sqlsrv_realloc_trace( buffer, size, __FILE__, __LINE__ )
#define sqlsrv_free( ptr ) sqlsrv_free_trace( ptr, __FILE__, __LINE__ )
#else
#define sqlsrv_malloc( size ) emalloc( size )
#define sqlsrv_realloc( buffer, size ) erealloc( buffer, size )
#define sqlsrv_free( ptr ) efree( ptr )
inline void* sqlsrv_malloc( size_t size )
{
return emalloc( size );
}
inline void* sqlsrv_malloc( size_t element_count, size_t element_size, size_t extra )
{
OACR_WARNING_SUPPRESS( ALLOC_SIZE_OVERFLOW_IN_ALLOC_WRAPPER, "Overflow verified below" );
if(( element_count > 0 && element_size > 0 ) &&
( element_count > element_size * element_count || element_size > element_size * element_count )) {
DIE( "Integer overflow in sqlsrv_malloc" );
}
if( element_size * element_count > element_size * element_count + extra ) {
DIE( "Integer overflow in sqlsrv_malloc" );
}
if( element_size * element_count + extra == 0 ) {
DIE( "Allocation size must be more than 0" );
}
return emalloc( element_size * element_count + extra );
}
inline void* sqlsrv_realloc( void* buffer, size_t size )
{
return erealloc( buffer, size );
}
inline void sqlsrv_free( void* ptr )
{
efree( ptr );
}
#endif
@ -273,6 +366,84 @@ struct remove_const<const T*> {
typedef T* type;
};
// allocator that uses the zend memory manager to manage memory
// this allows us to use STL classes that still work with Zend objects
template<typename T>
struct sqlsrv_allocator {
// typedefs used by the STL classes
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
// conversion typedef (used by list and other STL classes)
template<typename U>
struct rebind {
typedef sqlsrv_allocator<U> other;
};
inline sqlsrv_allocator() {}
inline ~sqlsrv_allocator() {}
inline sqlsrv_allocator( sqlsrv_allocator const& ) {}
template<typename U>
inline sqlsrv_allocator( sqlsrv_allocator<U> const& ) {}
// address (doesn't work if the class defines operator&)
inline pointer address( reference r )
{
return &r;
}
inline const_pointer address( const_reference r )
{
return &r;
}
// memory allocation/deallocation
inline pointer allocate( size_type cnt,
typename std::allocator<void>::const_pointer = 0 )
{
return reinterpret_cast<pointer>( sqlsrv_malloc(cnt, sizeof (T), 0));
}
inline void deallocate( pointer p, size_type )
{
sqlsrv_free(p);
}
// size
inline size_type max_size( void ) const
{
return std::numeric_limits<size_type>::max() / sizeof(T);
}
// object construction/destruction
inline void construct( pointer p, const T& t )
{
new(p) T(t);
}
inline void destroy(pointer p)
{
p->~T();
}
// equality operators
inline bool operator==( sqlsrv_allocator const& )
{
return true;
}
inline bool operator!=( sqlsrv_allocator const& a )
{
return !operator==(a);
}
};
// base class for auto_ptrs that we define below. It provides common operators and functions
// used by all the classes.
@ -398,6 +569,8 @@ protected:
// in a variable of sqlsrv_malloc_auto_ptr. sqlsrv_malloc_auto_ptr will "own" that block and assure that it is
// freed until the variable is destroyed (out of scope) or ownership is transferred using the function
// "transferred".
// DO NOT CALL sqlsrv_realloc with a sqlsrv_malloc_auto_ptr. Use the resize member function.
template <typename T>
class sqlsrv_malloc_auto_ptr : public sqlsrv_auto_ptr<T, sqlsrv_malloc_auto_ptr<T> > {
@ -432,6 +605,13 @@ public:
src.transferred();
this->_ptr = p;
}
// DO NOT CALL sqlsrv_realloc with a sqlsrv_malloc_auto_ptr. Use the resize member function.
// has the same parameter list as sqlsrv_realloc: new_size is the size in bytes of the newly allocated buffer
void resize( size_t new_size )
{
_ptr = reinterpret_cast<T*>( sqlsrv_realloc( _ptr, new_size ));
}
};
@ -507,6 +687,9 @@ private:
zval_auto_ptr( const zval_auto_ptr& src );
};
#pragma pop_macro( "max" )
//*********************************************************************************************************************************
// sqlsrv_error
//*********************************************************************************************************************************
@ -546,6 +729,11 @@ struct sqlsrv_error : public sqlsrv_error_const {
format = printf_format;
}
sqlsrv_error( sqlsrv_error_const const& prototype )
{
sqlsrv_error( prototype.sqlstate, prototype.native_message, prototype.native_code, prototype.format );
}
~sqlsrv_error( void )
{
if( sqlstate != NULL ) {
@ -816,6 +1004,7 @@ enum SQLSRV_STMT_OPTIONS {
SQLSRV_STMT_OPTION_QUERY_TIMEOUT,
SQLSRV_STMT_OPTION_SEND_STREAMS_AT_EXEC,
SQLSRV_STMT_OPTION_SCROLLABLE,
SQLSRV_STMT_OPTION_CLIENT_BUFFER_MAX_SIZE,
// Driver specific connection options
SQLSRV_STMT_OPTION_DRIVER_SPECIFIC = 1000,
@ -825,6 +1014,8 @@ enum SQLSRV_STMT_OPTIONS {
namespace ODBCConnOptions {
const char APP[] = "APP";
const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char CharacterSet[] = "CharacterSet";
const char ConnectionPooling[] = "ConnectionPooling";
const char Database[] = "Database";
@ -832,6 +1023,7 @@ const char Encrypt[] = "Encrypt";
const char Failover_Partner[] = "Failover_Partner";
const char LoginTimeout[] = "LoginTimggeout";
const char MARS_ODBC[] = "MARS_Connection";
const char MultiSubnetFailover[] = "MultiSubnetFailover";
const char QuotedId[] = "QuotedId";
const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
@ -861,6 +1053,9 @@ enum SQLSRV_CONN_OPTIONS {
SQLSRV_CONN_OPTION_TRANS_ISOLATION,
SQLSRV_CONN_OPTION_TRUST_SERVER_CERT,
SQLSRV_CONN_OPTION_WSID,
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
// Driver specific connection options
SQLSRV_CONN_OPTION_DRIVER_SPECIFIC = 1000,
@ -963,6 +1158,11 @@ struct stmt_option_send_at_exec : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* opt, zval* value_z TSRMLS_DC );
};
struct stmt_option_buffered_query_limit : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* opt, zval* value_z TSRMLS_DC );
};
// used to hold the table for statment options
struct stmt_option {
@ -1029,25 +1229,28 @@ struct sqlsrv_output_param {
}
};
// forward decls
struct sqlsrv_result_set;
// *** Statement resource structure ***
struct sqlsrv_stmt : public sqlsrv_context {
void free_param_data( TSRMLS_D );
virtual void new_result_set( void );
virtual void new_result_set( TSRMLS_D );
sqlsrv_conn* conn; // Connection that created this statement
bool executed; // Whether the statement has been executed yet (used for error messages)
bool past_fetch_end; // Core_sqlsrv_fetch sets this field when the statement goes beyond the last row
bool scrollable; // Determines if the statement was created with the Scrollable query attribute
// (don't have to use ODBC to find out)
bool scroll_is_dynamic; // if scrollable, is it a dynamic cursor.
sqlsrv_result_set* current_results; // Current result set
SQLULEN cursor_type; // Type of cursor for the current result set
bool has_rows; // Has_rows is set if there are actual rows in the row set
bool fetch_called; // Used by core_sqlsrv_get_field to return an informative error if fetch not yet called
int last_field_index; // last field retrieved by core_sqlsrv_get_field
bool past_next_result_end; // core_sqlsrv_next_result sets this to true when the statement goes beyond the
// last results
unsigned long query_timeout; // maximum allowed statement execution time
unsigned long buffered_query_limit; // maximum allowed memory for a buffered query (measured in KB)
// holds output pointers for SQLBindParameter
// We use a deque because it 1) provides the at/[] access in constant time, and 2) grows dynamically without moving
@ -1101,6 +1304,9 @@ const int SQLSRV_DEFAULT_SIZE = -1; // size given for an output parameter th
// uninitialized query timeout value
const unsigned int QUERY_TIMEOUT_INVALID = 0xffffffff;
// special buffered query constant
const size_t SQLSRV_CURSOR_BUFFERED = 0xfffffffeUL; // arbitrary number that doesn't map to any other SQL_CURSOR_* constant
// factory to create a statement
typedef sqlsrv_stmt* (*driver_stmt_factory)( sqlsrv_conn* conn, SQLHANDLE h, error_callback e, void* drv TSRMLS_DC );
@ -1117,42 +1323,181 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
__out void** field_value, __out SQLLEN* field_length, bool cache_field,
__out SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC );
bool core_sqlsrv_has_any_result( sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params = true );
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params = true, bool throw_on_errors = true );
void core_sqlsrv_post_param( sqlsrv_stmt* stmt, unsigned int paramno, zval* param_z TSRMLS_DC );
void core_sqlsrv_set_scrollable( sqlsrv_stmt* stmt, unsigned int cursor_type TSRMLS_DC );
void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, long timeout TSRMLS_DC );
void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
void core_sqlsrv_set_send_at_exec( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, long limit TSRMLS_DC );
//*********************************************************************************************************************************
// Logging
// Result Set
//*********************************************************************************************************************************
// log_callback
// a driver specific callback for logging messages
// severity - severity of the message: notice, warning, or error
// msg - the message to log in a FormatMessage style formatting
// print_args - args to the message
typedef void (*log_callback)( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
// each driver must register a log callback. This should be the first thing a driver does.
void core_sqlsrv_register_logger( log_callback );
// Abstract the result set so that a result set can either be used as is from ODBC or buffered.
// This is not a complete abstraction of a result set. Only enough is abstracted to allow for
// information and capabilities normally not available when a result set is not buffered
// (e.g., forward only vs buffered means row count is available and cursor movement is possible).
// Otherwise, normal ODBC calls are still valid and should be used to get information about the
// result set (e.g., SQLNumResultCols).
// a simple wrapper around a PHP error logging function.
void write_to_log( unsigned int severity TSRMLS_DC, const char* msg, ... );
struct sqlsrv_result_set {
// a macro to make it convenient to use the function.
#define LOG( severity, msg, ...) write_to_log( severity TSRMLS_CC, msg, __VA_ARGS__ )
sqlsrv_stmt* odbc;
// mask for filtering which severities are written to the log
enum logging_severity {
SEV_ERROR = 0x01,
SEV_WARNING = 0x02,
SEV_NOTICE = 0x04,
SEV_ALL = -1,
explicit sqlsrv_result_set( sqlsrv_stmt* );
virtual ~sqlsrv_result_set( void ) { }
virtual bool cached( int field_index ) = 0;
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC ) = 0;
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )= 0;
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC ) = 0;
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number ) = 0;
virtual SQLLEN row_count( TSRMLS_D ) = 0;
};
struct sqlsrv_odbc_result_set : public sqlsrv_result_set {
explicit sqlsrv_odbc_result_set( sqlsrv_stmt* );
virtual ~sqlsrv_odbc_result_set( void );
virtual bool cached( int field_index ) { return false; }
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC );
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC );
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC );
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number );
virtual SQLLEN row_count( TSRMLS_D );
private:
// prevent invalid instantiations and assignments
sqlsrv_odbc_result_set( void );
sqlsrv_odbc_result_set( sqlsrv_odbc_result_set& );
sqlsrv_odbc_result_set& operator=( sqlsrv_odbc_result_set& );
};
struct sqlsrv_buffered_result_set : public sqlsrv_result_set {
struct meta_data {
SQLSMALLINT type;
SQLSMALLINT c_type; // convenience
SQLULEN offset; // in bytes
SQLULEN length; // in bytes
SQLSMALLINT scale;
static const SQLULEN SIZE_UNKNOWN = 0;
};
// default maximum amount of memory that a buffered query can consume
#define INI_BUFFERED_QUERY_LIMIT_DEFAULT "10240" // default used by the php.ini settings
static const unsigned long BUFFERED_QUERY_LIMIT_DEFAULT = 10240; // measured in KB
static const long BUFFERED_QUERY_LIMIT_INVALID = 0;
explicit sqlsrv_buffered_result_set( sqlsrv_stmt* odbc TSRMLS_DC );
virtual ~sqlsrv_buffered_result_set( void );
virtual bool cached( int field_index ) { return true; }
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC );
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC );
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC );
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number );
virtual SQLLEN row_count( TSRMLS_D );
// buffered result set specific
SQLSMALLINT column_count( void )
{
return col_count;
}
struct meta_data& col_meta_data( SQLSMALLINT i )
{
return meta[i];
}
private:
// prevent invalid instantiations and assignments
sqlsrv_buffered_result_set( void );
sqlsrv_buffered_result_set( sqlsrv_buffered_result_set& );
sqlsrv_buffered_result_set& operator=( sqlsrv_buffered_result_set& );
HashTable* cache; // rows of data kept in index based hash table
SQLSMALLINT col_count; // number of columns in the current result set
meta_data* meta; // metadata for fields in the cache
SQLLEN current; // 1 based, 0 means before first row
sqlsrv_error_auto_ptr last_error; // if an error occurred, it is kept here
SQLUSMALLINT last_field_index; // the last field data retrieved from
SQLLEN read_so_far; // position within string to read from (for partial reads of strings)
sqlsrv_malloc_auto_ptr<SQLCHAR> temp_string; // temp buffer to hold a converted field while in use
SQLLEN temp_length; // number of bytes in the temp conversion buffer
typedef SQLRETURN (sqlsrv_buffered_result_set::*conv_fn)( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
typedef std::map< SQLINTEGER, std::map< SQLINTEGER, conv_fn > > conv_matrix_t;
// two dimentional sparse matrix that holds the [from][to] functions that do conversions
static conv_matrix_t conv_matrix;
// string conversion functions
SQLRETURN binary_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN binary_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN system_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN to_binary_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN to_same_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN wide_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
// long conversion functions
SQLRETURN to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length );
SQLRETURN long_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN long_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN long_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
// double conversion functions
SQLRETURN to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length );
SQLRETURN double_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN double_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN double_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
// string to number conversion functions
// Future: See if these can be converted directly to template member functions
SQLRETURN string_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN string_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN wstring_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN wstring_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
// utility functions for conversions
unsigned char* get_row( void );
};
//*********************************************************************************************************************************
// Utility
@ -1205,7 +1550,7 @@ enum SQLSRV_ERROR_CODES {
SQLSRV_ERROR_INVALID_CONNECTION_KEY,
SQLSRV_ERROR_MAX_PARAMS_EXCEEDED,
SQLSRV_ERROR_INVALID_OPTION_KEY,
SQLSRV_ERROR_INVALID_OPTION_VALUE,
SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE,
SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE,
SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE,
SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED,
@ -1215,6 +1560,8 @@ enum SQLSRV_ERROR_CODES {
SQLSRV_ERROR_STREAM_CREATE,
SQLSRV_ERROR_MARS_OFF,
SQLSRV_ERROR_FIELD_INDEX_ERROR,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED,
SQLSRV_ERROR_INVALID_BUFFER_LIMIT,
// Driver specific error codes starts from here.
SQLSRV_ERROR_DRIVER_SPECIFIC = 1000,
@ -1222,7 +1569,8 @@ enum SQLSRV_ERROR_CODES {
};
// the message returned by SQL Native Client
const char CONNECTION_BUSY_ODBC_ERROR[] = "[Microsoft][SQL Server Native Client 10.0]Connection is busy with results for another command";
const char CONNECTION_BUSY_ODBC_ERROR[] = "[Microsoft][SQL Server Native Client 11.0]Connection is busy with results for "
"another command";
// SQLSTATE for all internal errors
extern SQLCHAR IMSSP[];
@ -1244,11 +1592,12 @@ enum error_handling_flags {
// 2/code) driver specific error code
// 3/message) driver specific error message
// The fetch type determines if the indices are numeric, associative, or both.
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_error* error, logging_severity severity TSRMLS_DC );
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, __out sqlsrv_error_auto_ptr& error,
logging_severity severity TSRMLS_DC );
// format and return a driver specfic error
void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const const* custom_error,
sqlsrv_error* formatted_error, logging_severity severity TSRMLS_DC, va_list* args );
sqlsrv_error_auto_ptr& formatted_error, logging_severity severity TSRMLS_DC, va_list* args );
// return the message for the HRESULT returned by GetLastError. Some driver errors use this to
@ -1278,10 +1627,6 @@ inline bool call_error_handler( sqlsrv_context* ctx, unsigned int sqlsrv_error_c
return ignored;
}
// Kill the PHP process and log the message to PHP
void die( const char* msg, ... );
#define DIE( msg, ... ) { die( msg, __VA_ARGS__ ); }
// PHP equivalent of ASSERT. C asserts cause a dialog to show and halt the process which
// we don't want on a web server
@ -1300,7 +1645,6 @@ void die( const char* msg, ... );
#endif
// check to see if the sqlstate is 01004, truncated field retrieved. Used for retrieving large fields.
inline bool is_truncated_warning( SQLCHAR* state )
{

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use statement handles shared between sqlsrv and pdo_sqlsrv
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -28,8 +28,10 @@ struct field_cache {
void* value;
SQLLEN len;
sqlsrv_phptype type;
field_cache( void* field_value, SQLLEN field_len )
field_cache( void* field_value, SQLLEN field_len, sqlsrv_phptype t )
: type( t )
{
// if the value is NULL, then just record a NULL pointer
if( field_value != NULL ) {
@ -105,7 +107,6 @@ void send_param_streams( sqlsrv_stmt* stmt TSRMLS_DC );
void sqlsrv_output_param_dtor( void* data );
// called when a bound stream parameter is to be destroyed.
void sqlsrv_stream_dtor( void* data );
sqlsrv_phptype sql_type_to_php_type( sqlsrv_stmt const* stmt, SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string );
bool is_streamable_type( SQLINTEGER sql_type );
}
@ -116,7 +117,8 @@ sqlsrv_stmt::sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, vo
conn( c ),
executed( false ),
past_fetch_end( false ),
scrollable( false ),
current_results( NULL ),
cursor_type( SQL_CURSOR_FORWARD_ONLY ),
has_rows( false ),
fetch_called( false ),
last_field_index( -1 ),
@ -126,6 +128,7 @@ sqlsrv_stmt::sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, vo
current_stream( NULL, SQLSRV_ENCODING_DEFAULT ),
current_stream_read( 0 ),
query_timeout( QUERY_TIMEOUT_INVALID ),
buffered_query_limit( sqlsrv_buffered_result_set::BUFFERED_QUERY_LIMIT_INVALID ),
active_stream( NULL )
{
// initialize the input string parameters array (which holds zvals)
@ -165,6 +168,14 @@ sqlsrv_stmt::~sqlsrv_stmt( void )
TSRMLS_FETCH();
close_active_stream( this TSRMLS_CC );
}
// delete any current results
if( current_results ) {
current_results->~sqlsrv_result_set();
efree( current_results );
current_results = NULL;
}
invalidate();
zval_ptr_dtor( &param_input_strings );
zval_ptr_dtor( &output_params );
@ -192,13 +203,28 @@ void sqlsrv_stmt::free_param_data( TSRMLS_D )
// to be called whenever a new result set is created, such as after an
// execute or next_result. Resets the state variables.
void sqlsrv_stmt::new_result_set( void )
void sqlsrv_stmt::new_result_set( TSRMLS_D )
{
this->fetch_called = false;
this->has_rows = false;
this->past_next_result_end = false;
this->past_fetch_end = false;
this->last_field_index = -1;
// delete any current results
if( current_results ) {
current_results->~sqlsrv_result_set();
efree( current_results );
current_results = NULL;
}
// create a new result set
if( cursor_type == SQLSRV_CURSOR_BUFFERED ) {
current_results = new (sqlsrv_malloc( sizeof( sqlsrv_buffered_result_set ))) sqlsrv_buffered_result_set( this TSRMLS_CC );
}
else {
current_results = new (sqlsrv_malloc( sizeof( sqlsrv_odbc_result_set ))) sqlsrv_odbc_result_set( this );
}
}
// core_sqlsrv_create_stmt
@ -247,16 +273,15 @@ sqlsrv_stmt* core_sqlsrv_create_stmt( sqlsrv_conn* conn, driver_stmt_factory stm
int type = zend_hash_get_current_key_ex( options_ht, &key, &key_len, &index, 0, NULL );
// The driver layer should ensure a valid key.
SQLSRV_ASSERT( (type == HASH_KEY_IS_LONG), "allocate_stmt: Invalid statment option key provided" );
DEBUG_SQLSRV_ASSERT(( type == HASH_KEY_IS_LONG ), "allocate_stmt: Invalid statment option key provided." );
core::sqlsrv_zend_hash_get_current_data( *(stmt->conn), options_ht, (void**) &value_z TSRMLS_CC );
const stmt_option* stmt_opt = get_stmt_option( stmt->conn, index, valid_stmt_opts TSRMLS_CC );
// if the key didn't match, then return the error to the script
if( !stmt_opt ) {
THROW_CORE_ERROR( stmt->conn, SQLSRV_ERROR_INVALID_OPTION_KEY );
}
// if the key didn't match, then return the error to the script.
// The driver layer should ensure that the key is valid.
DEBUG_SQLSRV_ASSERT( stmt_opt != NULL, "allocate_stmt: unexpected null value for statement option." );
// perform the actions the statement option needs done.
(*stmt_opt->func)( stmt, stmt_opt, *value_z TSRMLS_CC );
@ -273,6 +298,8 @@ sqlsrv_stmt* core_sqlsrv_create_stmt( sqlsrv_conn* conn, driver_stmt_factory stm
catch( core::CoreException& )
{
if( stmt ) {
conn->set_last_error( stmt->last_error() );
stmt->~sqlsrv_stmt();
}
@ -321,7 +348,7 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
try {
// check is only < because params are 0 based
CHECK_CUSTOM_ERROR( param_num >= SQL_SERVER_MAX_PARAMS, stmt, SQLSRV_ERROR_MAX_PARAMS_EXCEEDED, param_num ) {
CHECK_CUSTOM_ERROR( param_num >= SQL_SERVER_MAX_PARAMS, stmt, SQLSRV_ERROR_MAX_PARAMS_EXCEEDED, param_num + 1 ) {
throw core::CoreException();
}
@ -498,6 +525,27 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
// save the parameter to be adjusted and/or converted after the results are processed
sqlsrv_output_param output_param( param_z, encoding, param_num, buffer_len );
save_output_param_for_later( stmt, output_param TSRMLS_CC );
// For output parameters, if we set the column_size to be same as the buffer_len,
// than if there is a truncation due to the data coming from the server being
// greater than the column_size, we don't get any truncation error. In order to
// avoid this silent truncation, we set the column_size to be "MAX" size for
// string types. This will guarantee that there is no silent truncation for
// output parameters.
if( direction == SQL_PARAM_OUTPUT ) {
switch( sql_type ) {
case SQL_VARBINARY:
case SQL_VARCHAR:
case SQL_WVARCHAR:
column_size = SQL_SS_LENGTH_UNLIMITED;
break;
default:
break;
}
}
}
break;
case IS_RESOURCE:
@ -516,22 +564,33 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
case IS_OBJECT:
{
SQLSRV_ASSERT( direction == SQL_PARAM_INPUT, "Invalid output param type. The driver layer should catch this." );
sqlsrv_malloc_auto_ptr<char> class_name;
zend_uint class_name_len;
zval_auto_ptr function_z;
zval_auto_ptr buffer_z;
zval_auto_ptr format_z;
zval* params[1];
bool valid_class_name_found = false;
int zr = zend_get_object_classname( param_z, &class_name, &class_name_len TSRMLS_CC );
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
CHECK_CUSTOM_ERROR( class_name_len != DateTime::DATETIME_CLASS_NAME_LEN ||
stricmp( class_name, DateTime::DATETIME_CLASS_NAME ),
stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
zend_class_entry *class_entry = zend_get_class_entry( param_z TSRMLS_CC );
while( class_entry != NULL ) {
if( class_entry->name_length == DateTime::DATETIME_CLASS_NAME_LEN && class_entry->name != NULL &&
stricmp( class_entry->name, DateTime::DATETIME_CLASS_NAME ) == 0 ) {
valid_class_name_found = true;
break;
}
else {
// Check the parent
class_entry = class_entry->parent;
}
}
CHECK_CUSTOM_ERROR( !valid_class_name_found, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
ALLOC_INIT_ZVAL( buffer_z );
ALLOC_INIT_ZVAL( function_z );
ALLOC_INIT_ZVAL( format_z );
@ -554,7 +613,7 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
params[0] = format_z;
// This is equivalent to the PHP code: $param_z->format( $format_z ); where param_z is the
// DateTime object and $format_z is the format string.
zr = call_user_function( EG( function_table ), &param_z, function_z, buffer_z, 1, params TSRMLS_CC );
int zr = call_user_function( EG( function_table ), &param_z, function_z, buffer_z, 1, params TSRMLS_CC );
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
@ -602,6 +661,8 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_len )
{
try {
// close the stream to release the resource
close_active_stream( stmt TSRMLS_CC );
@ -632,7 +693,7 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_
r = core::SQLExecute( stmt TSRMLS_CC );
}
stmt->new_result_set();
stmt->new_result_set( TSRMLS_C );
stmt->executed = true;
// if data is needed (streams were bound) and they should be sent at execute time, then do so now
@ -646,6 +707,19 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_
finalize_output_parameters( stmt TSRMLS_CC );
}
}
catch( core::CoreException& e ) {
// if the statement executed but failed in a subsequent operation before returning,
// we need to cancel the statement
if( stmt->executed ) {
SQLCancel( stmt->handle() );
// stmt->executed = false; should this be reset if something fails?
}
throw e;
}
}
@ -689,20 +763,19 @@ bool core_sqlsrv_fetch( sqlsrv_stmt* stmt, SQLSMALLINT fetch_orientation, SQLLEN
// if the statement has rows and is not scrollable but doesn't yet have
// fetch_called, this must be the first time we've called sqlsrv_fetch.
if( !stmt->scrollable && stmt->has_rows && !stmt->fetch_called ) {
if( stmt->cursor_type == SQL_CURSOR_FORWARD_ONLY && stmt->has_rows && !stmt->fetch_called ) {
stmt->fetch_called = true;
return true;
}
// move to the record requested. For absolute records, we use a 0 based offset, so +1 since
// SQLFetchScroll uses a 1 based offset, otherwise for relative, just use the fetch_offset provided.
SQLRETURN r = core::SQLFetchScroll( stmt, fetch_orientation,
( fetch_orientation == SQL_FETCH_RELATIVE ) ? fetch_offset : fetch_offset + 1
TSRMLS_CC );
SQLRETURN r = stmt->current_results->fetch( fetch_orientation,
( fetch_orientation == SQL_FETCH_RELATIVE ) ? fetch_offset : fetch_offset + 1
TSRMLS_CC );
if( r == SQL_NO_DATA ) {
// if this is a forward only cursor, mark that we've passed the end so future calls result in an error
if( !stmt->scrollable ) {
if( stmt->cursor_type == SQL_CURSOR_FORWARD_ONLY ) {
stmt->past_fetch_end = true;
}
return false;
@ -812,13 +885,18 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
if( cached->value == NULL ) {
*field_value = NULL;
*field_len = 0;
if( sqlsrv_php_type_out ) { *sqlsrv_php_type_out = SQLSRV_PHPTYPE_NULL; }
}
else {
*field_value = sqlsrv_malloc( cached->len + 1 );
*field_value = sqlsrv_malloc( cached->len, sizeof( char ), 1 );
memcpy( *field_value, cached->value, cached->len );
reinterpret_cast<char*>( *field_value )[ cached->len ] = '\0'; // prevent the 'string not null terminated' warning
if( cached->type.typeinfo.type == SQLSRV_PHPTYPE_STRING ) {
// prevent the 'string not null terminated' warning
reinterpret_cast<char*>( *field_value )[ cached->len ] = '\0';
}
*field_len = cached->len;
if( sqlsrv_php_type_out ) { *sqlsrv_php_type_out = static_cast<SQLSRV_PHPTYPE>( cached->type.typeinfo.type ); }
}
return;
}
@ -878,7 +956,7 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
// if the user wants us to cache the field, we'll do it
if( cache_field ) {
field_cache cache( *field_value, *field_len );
field_cache cache( *field_value, *field_len, sqlsrv_php_type );
core::sqlsrv_zend_hash_index_update( *stmt, Z_ARRVAL_P( stmt->field_cache ), field_index, &cache,
sizeof( field_cache ) TSRMLS_CC );
}
@ -913,7 +991,7 @@ bool core_sqlsrv_has_any_result( sqlsrv_stmt* stmt TSRMLS_DC )
// Returns
// Nothing, exception thrown if problem occurs
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params )
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params, bool throw_on_errors )
{
try {
@ -928,7 +1006,13 @@ void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_
close_active_stream( stmt TSRMLS_CC );
SQLRETURN r = core::SQLMoreResults( stmt TSRMLS_CC );
SQLRETURN r;
if( throw_on_errors ) {
r = core::SQLMoreResults( stmt TSRMLS_CC );
}
else {
r = SQLMoreResults( stmt->handle() );
}
if( r == SQL_NO_DATA ) {
@ -942,7 +1026,7 @@ void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_
return;
}
stmt->new_result_set();
stmt->new_result_set( TSRMLS_C );
}
catch( core::CoreException& e ) {
@ -991,42 +1075,62 @@ void core_sqlsrv_set_scrollable( sqlsrv_stmt* stmt, unsigned int cursor_type TSR
case SQL_CURSOR_STATIC:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_STATIC ), SQL_IS_UINTEGER TSRMLS_CC );
stmt->scrollable = true;
stmt->scroll_is_dynamic = false;
break;
case SQL_CURSOR_DYNAMIC:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_DYNAMIC ), SQL_IS_UINTEGER TSRMLS_CC );
stmt->scrollable = true;
stmt->scroll_is_dynamic = true; // this cursor is dynamic
break;
case SQL_CURSOR_KEYSET_DRIVEN:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_KEYSET_DRIVEN ), SQL_IS_UINTEGER TSRMLS_CC );
stmt->scrollable = true;
stmt->scroll_is_dynamic = false;
break;
case SQL_CURSOR_FORWARD_ONLY:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_FORWARD_ONLY ), SQL_IS_UINTEGER TSRMLS_CC );
stmt->scrollable = false; // reset since forward isn't scrollable
stmt->scroll_is_dynamic = false;
break;
case SQLSRV_CURSOR_BUFFERED:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_FORWARD_ONLY ), SQL_IS_UINTEGER TSRMLS_CC );
break;
default:
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE );
break;
}
stmt->cursor_type = cursor_type;
}
catch( core::CoreException& ) {
throw;
}
}
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
{
if( Z_TYPE_P( value_z ) != IS_LONG ) {
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_BUFFER_LIMIT );
}
core_sqlsrv_set_buffered_query_limit( stmt, Z_LVAL_P( value_z ) TSRMLS_CC );
}
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, long limit TSRMLS_DC )
{
if( limit <= 0 ) {
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_BUFFER_LIMIT );
}
stmt->buffered_query_limit = limit;
}
// Overloaded. Extracts the long value and calls the core_sqlsrv_set_query_timeout
// which accepts timeout parameter as a long. If the zval is not of type long
// than throws error.
@ -1038,7 +1142,7 @@ void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
if( Z_TYPE_P( value_z ) != IS_LONG || Z_LVAL_P( value_z ) < 0 ) {
convert_to_string( value_z );
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_OPTION_VALUE, Z_STRVAL_P( value_z ) );
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE, Z_STRVAL_P( value_z ) );
}
core_sqlsrv_set_query_timeout( stmt, Z_LVAL_P( value_z ) TSRMLS_CC );
@ -1214,6 +1318,11 @@ void stmt_option_send_at_exec:: operator()( sqlsrv_stmt* stmt, stmt_option const
core_sqlsrv_set_send_at_exec( stmt, value_z TSRMLS_CC );
}
void stmt_option_buffered_query_limit:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
{
core_sqlsrv_set_buffered_query_limit( stmt, value_z TSRMLS_CC );
}
// internal function to release the active stream. Called by each main API function
// that will alter the statement and cancel any retrieval of data from a stream.
@ -1382,9 +1491,13 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
sqlsrv_malloc_auto_ptr<long> field_value_temp;
field_value_temp = static_cast<long*>( sqlsrv_malloc( sizeof( long )));
SQLRETURN r = core::SQLGetData( stmt, field_index + 1, SQL_C_LONG, field_value_temp, 0,
field_len, true /*handle_warning*/ TSRMLS_CC );
SQLRETURN r = stmt->current_results->get_data(field_index + 1, SQL_C_LONG, field_value_temp, sizeof( long ),
field_len, true /*handle_warning*/ TSRMLS_CC );
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
throw core::CoreException();
}
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException();
}
@ -1404,9 +1517,13 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
sqlsrv_malloc_auto_ptr<double> field_value_temp;
field_value_temp = static_cast<double*>( sqlsrv_malloc( sizeof( double )));
SQLRETURN r = core::SQLGetData( stmt, field_index + 1, SQL_C_DOUBLE, field_value_temp, 0,
field_len, true /*handle_warning*/ TSRMLS_CC );
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_DOUBLE, field_value_temp, sizeof( double ),
field_len, true /*handle_warning*/ TSRMLS_CC );
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
throw core::CoreException();
}
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException ();
}
@ -1440,8 +1557,8 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
ALLOC_INIT_ZVAL( function_z );
ALLOC_INIT_ZVAL( return_value_z );
SQLRETURN r = core::SQLGetData( stmt, field_index + 1, SQL_C_CHAR, field_value_temp, MAX_DATETIME_STRING_LEN,
field_len, true TSRMLS_CC );
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_CHAR, field_value_temp,
MAX_DATETIME_STRING_LEN, field_len, true TSRMLS_CC );
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException ();
@ -1512,6 +1629,11 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
break;
}
case SQLSRV_PHPTYPE_NULL:
*field_value = NULL;
*field_len = 0;
break;
default:
DIE( "core_get_field_common: Unexpected sqlsrv_phptype provided" );
break;
@ -1630,7 +1752,7 @@ SQLSMALLINT default_c_type( sqlsrv_stmt* stmt, unsigned int paramno, zval const*
sql_c_type = SQL_C_CHAR;
break;
}
break;
break;
case IS_BOOL:
case IS_LONG:
sql_c_type = SQL_C_LONG;
@ -1951,8 +2073,8 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
field_value_temp = static_cast<char*>( sqlsrv_malloc( field_len_temp + extra + 1 ));
r = core::SQLGetData( stmt, field_index + 1, c_type, field_value_temp, ( field_len_temp + extra ),
&field_len_temp, false /*handle_warning*/ TSRMLS_CC );
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp, ( field_len_temp + extra ),
&field_len_temp, false /*handle_warning*/ TSRMLS_CC );
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException ();
@ -1969,7 +2091,7 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
SQLSMALLINT len;
core::SQLGetDiagField( stmt, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
stmt->current_results->get_diag_field( 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
if( is_truncated_warning( state ) ) {
@ -1993,8 +2115,9 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
field_len_temp -= initial_field_len;
// Get the rest of the data.
r = core::SQLGetData( stmt, field_index + 1, c_type, field_value_temp + initial_field_len,
field_len_temp + extra, &dummy_field_len, false /*handle_warning*/ TSRMLS_CC );
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp + initial_field_len,
field_len_temp + extra, &dummy_field_len,
false /*handle_warning*/ TSRMLS_CC );
// the last packet will contain the actual amount retrieved, not SQL_NO_TOTAL
// so we calculate the actual length of the string with that.
@ -2019,8 +2142,9 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
field_len_temp -= INITIAL_FIELD_STRING_LEN;
// Get the rest of the data.
r = core::SQLGetData( stmt, field_index + 1, c_type, field_value_temp + INITIAL_FIELD_STRING_LEN,
field_len_temp + extra, &dummy_field_len, true /*handle_warning*/ TSRMLS_CC );
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp + INITIAL_FIELD_STRING_LEN,
field_len_temp + extra, &dummy_field_len,
true /*handle_warning*/ TSRMLS_CC );
if( dummy_field_len == SQL_NULL_DATA ) {
*field_value = NULL;
@ -2072,9 +2196,11 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
field_value_temp = static_cast<char*>( sqlsrv_malloc( sql_display_size + extra + 1 ));
// get the data
r = core::SQLGetData( stmt, field_index + 1, c_type, field_value_temp, sql_display_size,
&field_len_temp, true /*handle_warning*/ TSRMLS_CC );
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp, sql_display_size,
&field_len_temp, true /*handle_warning*/ TSRMLS_CC );
CHECK_SQL_ERROR( r, stmt ) {
throw core::CoreException();
}
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException ();
}

View file

@ -3,7 +3,7 @@
//
// Contents: Implementation of PHP streams for reading SQL Server data
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -113,8 +113,9 @@ size_t sqlsrv_stream_read( php_stream* stream, __out_bcount(count) char* buf, si
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
SQLSMALLINT len;
core::SQLGetDiagField( ss->stmt, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
ss->stmt->current_results->get_diag_field( 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
if( read == SQL_NO_TOTAL ) {
SQLSRV_ASSERT( is_truncated_warning( state ), "sqlsrv_stream_read: truncation warning was expected but it "
"did not occur." );
@ -135,7 +136,7 @@ size_t sqlsrv_stream_read( php_stream* stream, __out_bcount(count) char* buf, si
read = count - 1;
break;
default:
DIE( "sqlsrv_stream_read: should have never reached in this switch case. ");
DIE( "sqlsrv_stream_read: should have never reached in this switch case.");
break;
}
}

View file

@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -147,7 +147,8 @@ wchar_t* utf16_string_from_mbcs_string( SQLSRV_ENCODING php_encoding, const char
// 3/message) driver specific error message
// The fetch type determines if the indices are numeric, associative, or both.
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_error* error, logging_severity severity TSRMLS_DC )
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_error_auto_ptr& error, logging_severity severity
TSRMLS_DC )
{
SQLHANDLE h = ctx.handle();
SQLSMALLINT h_type = ctx.handle_type();
@ -165,22 +166,50 @@ bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_
SQLINTEGER message_len = 0;
SQLWCHAR wsqlstate[ SQL_SQLSTATE_BUFSIZE ];
SQLWCHAR wnative_message[ SQL_MAX_MESSAGE_LENGTH + 1 ];
SQLSRV_ENCODING enc = ctx.encoding();
r = SQLGetDiagRecW( h_type, h, record_number, wsqlstate, &error->native_code, wnative_message,
SQL_MAX_MESSAGE_LENGTH + 1, &wmessage_len );
// don't use the CHECK* macros here since it will trigger reentry into the error handling system
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
return false;
}
switch( h_type ) {
case SQL_HANDLE_STMT:
{
sqlsrv_stmt* stmt = static_cast<sqlsrv_stmt*>( &ctx );
if( stmt->current_results != NULL ) {
error = stmt->current_results->get_diag_rec( record_number );
// don't use the CHECK* macros here since it will trigger reentry into the error handling system
if( error == NULL ) {
return false;
}
break;
}
// convert the error into the encoding of the context
if( enc == SQLSRV_ENCODING_DEFAULT ) {
enc = stmt->conn->encoding();
}
}
default:
error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error();
r = SQLGetDiagRecW( h_type, h, record_number, wsqlstate, &error->native_code, wnative_message,
SQL_MAX_MESSAGE_LENGTH + 1, &wmessage_len );
// don't use the CHECK* macros here since it will trigger reentry into the error handling system
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
return false;
}
error->sqlstate = reinterpret_cast<SQLCHAR*>( wsqlstate );
convert_string_from_utf16( enc, reinterpret_cast<char**>( &error->sqlstate ), sqlstate_len,
false /*no free*/ );
error->native_message = reinterpret_cast<SQLCHAR*>( wnative_message );
message_len = wmessage_len * sizeof( wchar_t );
convert_string_from_utf16( enc, reinterpret_cast<char**>( &error->native_message ), message_len,
false /*no free*/ );
break;
}
// convert the error into the encoding of the context
error->sqlstate = reinterpret_cast<SQLCHAR*>( wsqlstate );
convert_string_from_utf16( ctx.encoding(), reinterpret_cast<char**>( &error->sqlstate ), sqlstate_len,
false /*no free*/ );
error->native_message = reinterpret_cast<SQLCHAR*>( wnative_message );
message_len = wmessage_len * sizeof( wchar_t );
convert_string_from_utf16( ctx.encoding(), reinterpret_cast<char**>( &error->native_message ), message_len,
false /*no free*/ );
// log the error first
LOG( severity, "%1!s!: SQLSTATE = %2!s!", ctx.func(), error->sqlstate );
@ -194,9 +223,10 @@ bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_
// format and return a driver specfic error
void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const const* custom_error,
sqlsrv_error* formatted_error, logging_severity severity TSRMLS_DC, va_list* args )
sqlsrv_error_auto_ptr& formatted_error, logging_severity severity TSRMLS_DC, va_list* args )
{
// allocate space for the formatted message
formatted_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error();
formatted_error->sqlstate = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_SQLSTATE_BUFSIZE ));
formatted_error->native_message = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_MAX_MESSAGE_LENGTH + 1 ));

View file

@ -3,7 +3,7 @@
//
// Contents: Implements the PDO object for PDO_SQLSRV
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -52,12 +52,15 @@ namespace PDOConnOptionNames {
const char Server[] = "Server";
const char APP[] = "APP";
const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char ConnectionPooling[] = "ConnectionPooling";
const char Database[] = "Database";
const char Encrypt[] = "Encrypt";
const char Failover_Partner[] = "Failover_Partner";
const char LoginTimeout[] = "LoginTimeout";
const char MARS_Option[] = "MultipleActiveResultSets";
const char MultiSubnetFailover[] = "MultiSubnetFailover";
const char QuotedId[] = "QuotedId";
const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
@ -77,6 +80,9 @@ enum PDO_STMT_OPTIONS {
PDO_STMT_OPTION_ENCODING = SQLSRV_STMT_OPTION_DRIVER_SPECIFIC,
PDO_STMT_OPTION_DIRECT_QUERY,
PDO_STMT_OPTION_CURSOR_SCROLL_TYPE,
PDO_STMT_OPTION_CLIENT_BUFFER_MAX_KB_SIZE,
PDO_STMT_OPTION_EMULATE_PREPARES,
};
// List of all the statement options supported by this driver.
@ -86,6 +92,9 @@ const stmt_option PDO_STMT_OPTS[] = {
{ NULL, 0, SQLSRV_STMT_OPTION_SCROLLABLE, new stmt_option_scrollable },
{ NULL, 0, PDO_STMT_OPTION_ENCODING, new stmt_option_encoding },
{ NULL, 0, PDO_STMT_OPTION_DIRECT_QUERY, new stmt_option_direct_query },
{ NULL, 0, PDO_STMT_OPTION_CURSOR_SCROLL_TYPE, new stmt_option_cursor_scroll_type },
{ NULL, 0, PDO_STMT_OPTION_CLIENT_BUFFER_MAX_KB_SIZE, new stmt_option_buffered_query_limit },
{ NULL, 0, PDO_STMT_OPTION_EMULATE_PREPARES, new stmt_option_emulate_prepares },
{ NULL, 0, SQLSRV_STMT_OPTION_INVALID, NULL},
};
@ -163,6 +172,24 @@ const connection_option PDO_CONN_OPTS[] = {
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
PDOConnOptionNames::ApplicationIntent,
sizeof( PDOConnOptionNames::ApplicationIntent ),
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
ODBCConnOptions::ApplicationIntent,
sizeof( ODBCConnOptions::ApplicationIntent ),
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
PDOConnOptionNames::AttachDBFileName,
sizeof( PDOConnOptionNames::AttachDBFileName ),
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
ODBCConnOptions::AttachDBFileName,
sizeof( ODBCConnOptions::AttachDBFileName ),
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
PDOConnOptionNames::ConnectionPooling,
sizeof( PDOConnOptionNames::ConnectionPooling ),
@ -217,6 +244,15 @@ const connection_option PDO_CONN_OPTS[] = {
CONN_ATTR_BOOL,
pdo_bool_conn_str_func::func
},
{
PDOConnOptionNames::MultiSubnetFailover,
sizeof( PDOConnOptionNames::MultiSubnetFailover ),
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
ODBCConnOptions::MultiSubnetFailover,
sizeof( ODBCConnOptions::MultiSubnetFailover ),
CONN_ATTR_BOOL,
pdo_bool_conn_str_func::func
},
{
PDOConnOptionNames::QuotedId,
sizeof( PDOConnOptionNames::QuotedId ),
@ -333,6 +369,20 @@ struct pdo_dbh_methods pdo_sqlsrv_dbh_methods = {
LOG( SEV_NOTICE, __FUNCTION__ ## ": entering" ); \
}
// constructor for the internal object for connections
pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC ) :
sqlsrv_conn( h, e, driver, SQLSRV_ENCODING_UTF8 TSRMLS_CC ),
stmts( NULL ),
direct_query( false ),
query_timeout( QUERY_TIMEOUT_INVALID ),
client_buffer_max_size( PDO_SQLSRV_G( client_buffer_max_size ) )
{
if( client_buffer_max_size < 0 ) {
client_buffer_max_size = sqlsrv_buffered_result_set::BUFFERED_QUERY_LIMIT_DEFAULT;
LOG( SEV_WARNING, INI_PDO_SQLSRV_CLIENT_BUFFER_MAX_SIZE " set to a invalid value. Resetting to default value." );
}
}
// pdo_sqlsrv_db_handle_factory
// Maps to PDO::__construct.
// Factory method called by the PDO driver manager to create a SQLSRV PDO connection.
@ -481,29 +531,16 @@ int pdo_sqlsrv_dbh_prepare( pdo_dbh_t *dbh, const char *sql,
int sql_rewrite_len = 0;
sqlsrv_malloc_auto_ptr<pdo_sqlsrv_stmt> driver_stmt;
try {
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
SQLSRV_ASSERT(( driver_dbh != NULL ), "pdo_sqlsrv_dbh_prepare: dbh->driver_data was null");
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
SQLSRV_ASSERT(( driver_dbh != NULL ), "pdo_sqlsrv_dbh_prepare: dbh->driver_data was null");
try {
// assign the methods for the statement object. This is necessary even if the
// statement fails so the user can retrieve the error information.
stmt->methods = &pdo_sqlsrv_stmt_methods;
stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL; // we support parameterized queries with ?, not names
// rewrite the query to map named parameters to positional parameters. We do this rather than use the ODBC named
// parameters for consistency with the PDO MySQL and PDO ODBC drivers.
int zr = pdo_subst_params_named_to_positional( stmt, const_cast<char*>( sql ), sql_len,
&sql_rewrite, &sql_rewrite_len TSRMLS_CC );
CHECK_ZEND_ERROR( zr, driver_dbh, PDO_SQLSRV_ERROR_PARAM_PARSE ) {
throw core::CoreException();
}
// if parameter substitution happened, use that query instead of the original
if( sql_rewrite != NULL ) {
sql = sql_rewrite;
sql_len = sql_rewrite_len;
}
// Initialize the options array to be passed to the core layer
ALLOC_HASHTABLE( pdo_stmt_options_ht );
core::sqlsrv_zend_hash_init( *driver_dbh , pdo_stmt_options_ht, 3 /* # of buckets */, NULL /*hashfn*/,
@ -516,6 +553,13 @@ int pdo_sqlsrv_dbh_prepare( pdo_dbh_t *dbh, const char *sql,
pdo_stmt_options_ht, PDO_STMT_OPTS,
pdo_sqlsrv_handle_stmt_error, stmt TSRMLS_CC ));
// if the user didn't set anything in the prepare options, then set the buffer limit
// to the value set on the connection.
if( driver_stmt->buffered_query_limit== sqlsrv_buffered_result_set::BUFFERED_QUERY_LIMIT_INVALID ) {
driver_stmt->buffered_query_limit = driver_dbh->client_buffer_max_size;
}
// if the user didn't set anything in the prepare options, then set the query timeout
// to the value set on the connection.
if(( driver_stmt->query_timeout == QUERY_TIMEOUT_INVALID ) && ( driver_dbh->query_timeout != QUERY_TIMEOUT_INVALID )) {
@ -523,12 +567,24 @@ int pdo_sqlsrv_dbh_prepare( pdo_dbh_t *dbh, const char *sql,
core_sqlsrv_set_query_timeout( driver_stmt, driver_dbh->query_timeout TSRMLS_CC );
}
if( driver_stmt->direct_query ) {
// rewrite named parameters in the query to positional parameters if we aren't letting PDO do the
// parameter substitution for us
if( stmt->supports_placeholders != PDO_PLACEHOLDER_NONE ) {
driver_stmt->query = estrndup( sql, sql_len );
driver_stmt->query_len = sql_len;
// rewrite the query to map named parameters to positional parameters. We do this rather than use the ODBC named
// parameters for consistency with the PDO MySQL and PDO ODBC drivers.
int zr = pdo_subst_named_params( stmt, const_cast<char*>( sql ), sql_len, &sql_rewrite, &sql_rewrite_len TSRMLS_CC );
CHECK_ZEND_ERROR( zr, driver_dbh, PDO_SQLSRV_ERROR_PARAM_PARSE ) {
throw core::CoreException();
}
// if parameter substitution happened, use that query instead of the original
if( sql_rewrite != NULL ) {
sql = sql_rewrite;
sql_len = sql_rewrite_len;
}
}
else {
if( !driver_stmt->direct_query && stmt->supports_placeholders != PDO_PLACEHOLDER_NONE ) {
core_sqlsrv_prepare( driver_stmt, sql, sql_len TSRMLS_CC );
}
@ -545,6 +601,14 @@ int pdo_sqlsrv_dbh_prepare( pdo_dbh_t *dbh, const char *sql,
driver_stmt->~pdo_sqlsrv_stmt();
}
// in the event that the statement caused an error that was copied to the connection, update the
// connection with the error's SQLSTATE.
if( driver_dbh->last_error() ) {
strcpy_s( dbh->error_code, sizeof( dbh->error_code ),
reinterpret_cast<const char*>( driver_dbh->last_error()->sqlstate ));
}
return 0;
}
@ -819,17 +883,24 @@ int pdo_sqlsrv_dbh_set_attr( pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC )
case SQLSRV_ATTR_QUERY_TIMEOUT:
if( Z_TYPE_P( val ) != IS_LONG || Z_LVAL_P( val ) < 0 ) {
convert_to_string( val );
THROW_PDO_ERROR( driver_dbh, SQLSRV_ERROR_INVALID_OPTION_VALUE, Z_STRVAL_P( val ));
THROW_PDO_ERROR( driver_dbh, SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE, Z_STRVAL_P( val ));
}
driver_dbh->query_timeout = Z_LVAL_P( val );
break;
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
if( Z_TYPE_P( val ) != IS_LONG || Z_LVAL_P( val ) <= 0 ) {
convert_to_string( val );
THROW_PDO_ERROR( driver_dbh, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, Z_STRVAL_P( val ));
}
driver_dbh->client_buffer_max_size = Z_LVAL_P( val );
break;
// Not supported
case PDO_ATTR_FETCH_TABLE_NAMES:
case PDO_ATTR_FETCH_CATALOG_NAMES:
case PDO_ATTR_PREFETCH:
case PDO_ATTR_MAX_COLUMN_LEN:
case PDO_ATTR_EMULATE_PREPARES:
case PDO_ATTR_CURSOR_NAME:
case PDO_ATTR_AUTOCOMMIT:
case PDO_ATTR_PERSISTENT:
@ -849,7 +920,9 @@ int pdo_sqlsrv_dbh_set_attr( pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC )
}
// Statement level only
case PDO_ATTR_CURSOR:
case PDO_ATTR_EMULATE_PREPARES:
case PDO_ATTR_CURSOR:
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
{
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
}
@ -895,7 +968,6 @@ int pdo_sqlsrv_dbh_get_attr( pdo_dbh_t *dbh, long attr, zval *return_value TSRML
case PDO_ATTR_FETCH_CATALOG_NAMES:
case PDO_ATTR_PREFETCH:
case PDO_ATTR_MAX_COLUMN_LEN:
case PDO_ATTR_EMULATE_PREPARES:
case PDO_ATTR_CURSOR_NAME:
case PDO_ATTR_AUTOCOMMIT:
case PDO_ATTR_TIMEOUT:
@ -904,8 +976,10 @@ int pdo_sqlsrv_dbh_get_attr( pdo_dbh_t *dbh, long attr, zval *return_value TSRML
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_UNSUPPORTED_DBH_ATTR );
}
// Statement level only
case PDO_ATTR_CURSOR:
// Statement level only
case PDO_ATTR_EMULATE_PREPARES:
case PDO_ATTR_CURSOR:
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
{
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
}
@ -957,6 +1031,12 @@ int pdo_sqlsrv_dbh_get_attr( pdo_dbh_t *dbh, long attr, zval *return_value TSRML
break;
}
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
{
ZVAL_LONG( return_value, driver_dbh->client_buffer_max_size );
break;
}
default:
{
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_INVALID_DBH_ATTR );
@ -1113,8 +1193,8 @@ int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, int unquoted_len
}
}
*quoted_len = unquoted_len + quotes_needed; // length returned to the caller should not account for null terminator.
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len + 1 )); // include space for null terminator.
*quoted_len = unquoted_len + quotes_needed; // length returned to the caller should not account for null terminator.
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len, sizeof( char ), 1 )); // include space for null terminator.
unsigned int out_current = 0;
// insert initial quote
@ -1163,29 +1243,42 @@ void add_stmt_option_key( sqlsrv_context& ctx, unsigned long key, HashTable* opt
unsigned long option_key = -1;
switch( key ) {
case PDO_ATTR_CURSOR:
option_key = SQLSRV_STMT_OPTION_SCROLLABLE;
break;
case PDO_ATTR_CURSOR:
option_key = SQLSRV_STMT_OPTION_SCROLLABLE;
break;
case SQLSRV_ATTR_ENCODING:
option_key = PDO_STMT_OPTION_ENCODING;
break;
case SQLSRV_ATTR_ENCODING:
option_key = PDO_STMT_OPTION_ENCODING;
break;
case SQLSRV_ATTR_QUERY_TIMEOUT:
option_key = SQLSRV_STMT_OPTION_QUERY_TIMEOUT;
break;
case SQLSRV_ATTR_QUERY_TIMEOUT:
option_key = SQLSRV_STMT_OPTION_QUERY_TIMEOUT;
break;
case PDO_ATTR_STATEMENT_CLASS:
break;
case PDO_ATTR_STATEMENT_CLASS:
break;
case SQLSRV_ATTR_DIRECT_QUERY:
option_key = PDO_STMT_OPTION_DIRECT_QUERY;
break;
default:
CHECK_CUSTOM_ERROR( true, ctx, PDO_SQLSRV_ERROR_INVALID_STMT_OPTION ) {
throw core::CoreException();
}
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
option_key = PDO_STMT_OPTION_CURSOR_SCROLL_TYPE;
break;
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
option_key = PDO_STMT_OPTION_CLIENT_BUFFER_MAX_KB_SIZE;
break;
case PDO_ATTR_EMULATE_PREPARES:
option_key = PDO_STMT_OPTION_EMULATE_PREPARES;
break;
default:
CHECK_CUSTOM_ERROR( true, ctx, PDO_SQLSRV_ERROR_INVALID_STMT_OPTION ) {
throw core::CoreException();
}
break;
}
// if a PDO handled option makes it through (such as PDO_ATTR_STATEMENT_CLASS, just skip it

View file

@ -3,7 +3,7 @@
//
// Contents: initialization routines for PDO_SQLSRV
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -134,8 +134,8 @@ zend_module_entry g_pdo_sqlsrv_module_entry =
// functions dynamically linked from the PDO (or PHP) dll and called by other parts of the driver
zend_class_entry* (*pdo_get_exception_class)( void );
int (*pdo_subst_params_named_to_positional)(pdo_stmt_t *stmt, char *inquery, int inquery_len,
char **outquery, int *outquery_len TSRMLS_DC);
int (*pdo_subst_named_params)(pdo_stmt_t *stmt, char *inquery, int inquery_len,
char **outquery, int *outquery_len TSRMLS_DC);
// Module initialization
// This function is called once per execution of the Zend engine
@ -206,11 +206,11 @@ PHP_MINIT_FUNCTION(pdo_sqlsrv)
return FAILURE;
}
pdo_subst_params_named_to_positional =
pdo_subst_named_params =
reinterpret_cast<int (*)(pdo_stmt_t *stmt, char *inquery, int inquery_len,
char **outquery, int *outquery_len TSRMLS_DC)>(
GetProcAddress( pdo_hmodule, "pdo_parse_params" ));
if( pdo_subst_params_named_to_positional == NULL ) {
if( pdo_subst_named_params == NULL ) {
LOG( SEV_ERROR, "Failed to register driver." );
return FAILURE;
}
@ -243,16 +243,6 @@ PHP_MINIT_FUNCTION(pdo_sqlsrv)
}
// used for the size for output parameters: PDO::PARAM_INT and PDO::PARAM_BOOL use the default size of int,
// PDO::PARAM_STR uses the size of the string in the variable
REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( "SQLSRV_PARAM_OUT_DEFAULT_SIZE", -1 TSRMLS_CC );
// encoding attributes
REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( "SQLSRV_ENCODING_DEFAULT", SQLSRV_ENCODING_DEFAULT TSRMLS_CC );
REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( "SQLSRV_ENCODING_SYSTEM", SQLSRV_ENCODING_SYSTEM TSRMLS_CC );
REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( "SQLSRV_ENCODING_BINARY", SQLSRV_ENCODING_BINARY TSRMLS_CC );
REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( "SQLSRV_ENCODING_UTF8", SQLSRV_ENCODING_UTF8 TSRMLS_CC );
REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( "SQLSRV_TXN_READ_UNCOMMITTED", PDOTxnIsolationValues::READ_UNCOMMITTED TSRMLS_CC );
REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( "SQLSRV_TXN_READ_COMMITTED", PDOTxnIsolationValues::READ_COMMITTED TSRMLS_CC );
REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( "SQLSRV_TXN_REPEATABLE_READ", PDOTxnIsolationValues::REPEATABLE_READ TSRMLS_CC );
@ -383,10 +373,30 @@ namespace {
// array of pdo constants.
sqlsrv_attr_pdo_constant pdo_attr_constants[] = {
// driver specific attributes
{ "SQLSRV_ATTR_ENCODING" , SQLSRV_ATTR_ENCODING },
{ "SQLSRV_ATTR_QUERY_TIMEOUT" , SQLSRV_ATTR_QUERY_TIMEOUT },
{ "SQLSRV_ATTR_DIRECT_QUERY" , SQLSRV_ATTR_DIRECT_QUERY },
{ "SQLSRV_ATTR_CURSOR_SCROLL_TYPE" , SQLSRV_ATTR_CURSOR_SCROLL_TYPE },
{ "SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE", SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE },
// used for the size for output parameters: PDO::PARAM_INT and PDO::PARAM_BOOL use the default size of int,
// PDO::PARAM_STR uses the size of the string in the variable
{ "SQLSRV_PARAM_OUT_DEFAULT_SIZE" , -1 },
// encoding attributes
{ "SQLSRV_ENCODING_DEFAULT" , SQLSRV_ENCODING_DEFAULT },
{ "SQLSRV_ENCODING_SYSTEM" , SQLSRV_ENCODING_SYSTEM },
{ "SQLSRV_ENCODING_BINARY" , SQLSRV_ENCODING_BINARY },
{ "SQLSRV_ENCODING_UTF8" , SQLSRV_ENCODING_UTF8 },
// cursor types (can be assigned to SQLSRV_ATTR_CURSOR_SCROLL_TYPE
{ "SQLSRV_CURSOR_STATIC" , SQL_CURSOR_STATIC },
{ "SQLSRV_CURSOR_DYNAMIC" , SQL_CURSOR_DYNAMIC },
{ "SQLSRV_CURSOR_KEYSET" , SQL_CURSOR_KEYSET_DRIVEN },
{ "SQLSRV_CURSOR_BUFFERED" , SQLSRV_CURSOR_BUFFERED },
{ NULL , 0 } // terminate the table
};
}

View file

@ -3,7 +3,7 @@
//
// Contents: Implements a parser to parse the PDO DSN.
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View file

@ -6,7 +6,7 @@
//
// Contents: Declarations for the extension
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -32,6 +32,10 @@ extern "C" {
}
#include <vector>
#include <map>
//*********************************************************************************************************************************
// Constants and Types
//*********************************************************************************************************************************
@ -43,6 +47,8 @@ enum PDO_SQLSRV_ATTR {
SQLSRV_ATTR_ENCODING = PDO_ATTR_DRIVER_SPECIFIC,
SQLSRV_ATTR_QUERY_TIMEOUT,
SQLSRV_ATTR_DIRECT_QUERY,
SQLSRV_ATTR_CURSOR_SCROLL_TYPE,
SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE,
};
// valid set of values for TransactionIsolation connection option
@ -65,6 +71,7 @@ extern "C" {
ZEND_BEGIN_MODULE_GLOBALS(pdo_sqlsrv)
unsigned int log_severity;
long client_buffer_max_size;
ZEND_END_MODULE_GLOBALS(pdo_sqlsrv)
@ -81,12 +88,15 @@ ZEND_EXTERN_MODULE_GLOBALS(pdo_sqlsrv);
// INI settings and constants
// (these are defined as macros to allow concatenation as we do below)
#define INI_PDO_SQLSRV_CLIENT_BUFFER_MAX_SIZE "client_buffer_max_kb_size"
#define INI_PDO_SQLSRV_LOG "log_severity"
#define INI_PREFIX "pdo_sqlsrv."
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY( INI_PREFIX INI_PDO_SQLSRV_LOG , "0", PHP_INI_ALL, OnUpdateLong, log_severity,
zend_pdo_sqlsrv_globals, pdo_sqlsrv_globals )
STD_PHP_INI_ENTRY( INI_PREFIX INI_PDO_SQLSRV_CLIENT_BUFFER_MAX_SIZE , INI_BUFFERED_QUERY_LIMIT_DEFAULT, PHP_INI_ALL, OnUpdateLong,
client_buffer_max_size, zend_pdo_sqlsrv_globals, pdo_sqlsrv_globals )
PHP_INI_END()
// henv context for creating connections
@ -166,14 +176,9 @@ struct pdo_sqlsrv_dbh : public sqlsrv_conn {
zval* stmts;
bool direct_query;
long query_timeout;
long client_buffer_max_size;
pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC ) :
sqlsrv_conn( h, e, driver, SQLSRV_ENCODING_UTF8 TSRMLS_CC ),
stmts( NULL ),
direct_query( false ),
query_timeout( QUERY_TIMEOUT_INVALID )
{
}
pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC );
};
@ -196,6 +201,16 @@ struct stmt_option_direct_query : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
};
struct stmt_option_cursor_scroll_type : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
};
struct stmt_option_emulate_prepares : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
};
extern struct pdo_stmt_methods pdo_sqlsrv_stmt_methods;
// a core layer pdo stmt object. This object inherits and overrides the callbacks necessary
@ -204,28 +219,22 @@ struct pdo_sqlsrv_stmt : public sqlsrv_stmt {
pdo_sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC ) :
sqlsrv_stmt( c, handle, e, drv TSRMLS_CC ),
direct_query( false ),
query( NULL ),
query_len( 0 )
bound_column_param_types( NULL )
{
pdo_sqlsrv_dbh* db = static_cast<pdo_sqlsrv_dbh*>( c );
direct_query = db->direct_query;
}
virtual ~pdo_sqlsrv_stmt( void )
{
if( query ) {
sqlsrv_free( query );
query = NULL;
}
}
virtual ~pdo_sqlsrv_stmt( void );
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
// for PDO, everything is a string, so we return SQLSRV_PHPTYPE_STRING for all SQL types
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream );
bool direct_query; // flag set if the query should be executed directly or prepared
char* query; // if the query should be executed directly, this holds the query to execute
unsigned int query_len; // length of the query string.
// meta data for current result set
std::vector<field_meta_data*, sqlsrv_allocator< field_meta_data* > > current_meta_data;
pdo_param_type* bound_column_param_types;
};
@ -345,6 +354,8 @@ enum PDO_ERROR_CODES {
PDO_SQLSRV_ERROR_DQ_ATTR_AT_PREPARE_ONLY,
PDO_SQLSRV_ERROR_INVALID_COLUMN_INDEX,
PDO_SQLSRV_ERROR_INVALID_OUTPUT_PARAM_TYPE,
PDO_SQLSRV_ERROR_INVALID_CURSOR_WITH_SCROLL_TYPE,
};
extern pdo_error PDO_ERRORS[];
@ -368,8 +379,8 @@ namespace pdo {
// called pdo_parse_params in php_pdo_driver.h
// we renamed it for 2 reasons: 1) we can't have the same name since it would conflict with our dynamic linking, and
// 2) this is a more precise name
extern int (*pdo_subst_params_named_to_positional)(pdo_stmt_t *stmt, char *inquery, int inquery_len,
char **outquery, int *outquery_len TSRMLS_DC);
extern int (*pdo_subst_named_params)(pdo_stmt_t *stmt, char *inquery, int inquery_len,
char **outquery, int *outquery_len TSRMLS_DC);
// logger for pdo_sqlsrv called by the core layer when it wants to log something with the LOG macro
void pdo_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );

View file

@ -3,7 +3,7 @@
//
// Contents: Implements the PDOStatement object for the PDO_SQLSRV
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -39,7 +39,10 @@ SQLSMALLINT odbc_fetch_orientation[] =
const int SQL_SERVER_IDENT_SIZE_MAX = 128;
inline SQLSMALLINT pdo_fetch_ori_to_odbc_fetch_ori (enum pdo_fetch_orientation ori)
{
{
SQLSRV_ASSERT( ori >= PDO_FETCH_ORI_NEXT && ori <= PDO_FETCH_ORI_REL, "Fetch orientation out of range." );
OACR_WARNING_SUPPRESS( 26001, "Buffer length verified above" );
OACR_WARNING_SUPPRESS( 26000, "Buffer length verified above" );
return odbc_fetch_orientation[ori];
}
@ -60,7 +63,8 @@ SQLSRV_PHPTYPE pdo_type_to_sqlsrv_php_type( sqlsrv_stmt* driver_stmt, enum pdo_p
return SQLSRV_PHPTYPE_NULL;
case PDO_PARAM_LOB:
return SQLSRV_PHPTYPE_STREAM;
// TODO: This will eventually be changed to SQLSRV_PHPTYPE_STREAM when output streaming is implemented.
return SQLSRV_PHPTYPE_STRING;
case PDO_PARAM_STMT:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_PDO_STMT_UNSUPPORTED );
@ -72,31 +76,6 @@ SQLSRV_PHPTYPE pdo_type_to_sqlsrv_php_type( sqlsrv_stmt* driver_stmt, enum pdo_p
return SQLSRV_PHPTYPE_INVALID; // to prevent compiler warning
}
// Returns PDO type for a given SQLSRV type. See pdo_param_type
// for list of supported pdo types.
inline pdo_param_type sqlsrv_php_type_to_pdo_type( enum SQLSRV_PHPTYPE sqlsrv_php_type )
{
switch( sqlsrv_php_type ) {
case SQLSRV_PHPTYPE_INT:
case SQLSRV_PHPTYPE_FLOAT:
return PDO_PARAM_INT;
case SQLSRV_PHPTYPE_DATETIME:
case SQLSRV_PHPTYPE_STRING:
return PDO_PARAM_STR;
case SQLSRV_PHPTYPE_STREAM:
return PDO_PARAM_LOB;
case SQLSRV_PHPTYPE_NULL:
return PDO_PARAM_NULL;
default:
DIE( "sqlsrv_php_type_to_pdo_type: Unexpected sqlsrv_php_type encountered." );
}
}
// Returns a pdo type for a given SQL type. See pdo_param_type
// for list of supported pdo types.
@ -124,6 +103,7 @@ inline pdo_param_type sql_type_to_pdo_type( SQLSMALLINT sql_type )
case SQL_SS_TIME2:
case SQL_SS_TIMESTAMPOFFSET:
case SQL_SS_UDT:
case SQL_SS_VARIANT:
case SQL_SS_XML:
case SQL_TYPE_DATE:
case SQL_TYPE_TIMESTAMP:
@ -173,6 +153,25 @@ void set_stmt_cursors( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
core_sqlsrv_set_scrollable( stmt, odbc_cursor_type TSRMLS_CC );
}
void set_stmt_cursor_scroll_type( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
{
if( Z_TYPE_P( value_z ) != IS_LONG ) {
THROW_PDO_ERROR( stmt, PDO_SQLSRV_ERROR_INVALID_CURSOR_TYPE );
}
if( stmt->cursor_type == SQL_CURSOR_FORWARD_ONLY ) {
THROW_PDO_ERROR( stmt, PDO_SQLSRV_ERROR_INVALID_CURSOR_WITH_SCROLL_TYPE );
}
long odbc_cursor_type = Z_LVAL_P( value_z );
core_sqlsrv_set_scrollable( stmt, odbc_cursor_type TSRMLS_CC );
return;
}
// Sets the statement encoding. Default encoding on the statement
// implies use the connection's encoding.
void set_stmt_encoding( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
@ -201,17 +200,87 @@ void set_stmt_encoding( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
}
}
// internal helper function to free meta data structures allocated
void meta_data_free( field_meta_data* meta )
{
sqlsrv_free( meta );
}
zval* convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void** in_val, SQLLEN field_len )
{
zval* out_zval = NULL;
switch( sqlsrv_php_type ) {
case SQLSRV_PHPTYPE_INT:
case SQLSRV_PHPTYPE_FLOAT:
{
ALLOC_INIT_ZVAL( out_zval );
if( *in_val == NULL ) {
ZVAL_NULL( out_zval );
}
else {
if( sqlsrv_php_type == SQLSRV_PHPTYPE_INT ) {
ZVAL_LONG( out_zval, **( reinterpret_cast<long**>( in_val )));
}
else {
ZVAL_DOUBLE( out_zval, **( reinterpret_cast<double**>( in_val )));
}
}
if( *in_val ) {
sqlsrv_free( *in_val );
}
break;
}
case SQLSRV_PHPTYPE_STRING:
case SQLSRV_PHPTYPE_STREAM: // TODO: this will be moved when output streaming is implemented
{
ALLOC_INIT_ZVAL( out_zval );
if( *in_val == NULL ) {
ZVAL_NULL( out_zval );
}
else {
ZVAL_STRINGL( out_zval, reinterpret_cast<char*>( *in_val ), field_len, 0 /*duplicate*/ );
}
break;
}
case SQLSRV_PHPTYPE_DATETIME:
DIE( "Unsupported php type" );
out_zval = ( reinterpret_cast<zval*>( *in_val ));
break;
case SQLSRV_PHPTYPE_NULL:
ALLOC_INIT_ZVAL( out_zval );
ZVAL_NULL( out_zval );
break;
default:
DIE( "Unknown php type" );
break;
}
return out_zval;
}
} // namespace
int pdo_sqlsrv_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC);
int pdo_sqlsrv_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC);
int pdo_sqlsrv_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori,
long offset TSRMLS_DC);
long offset TSRMLS_DC);
int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC);
struct pdo_bound_param_data *param, enum pdo_param_event event_type TSRMLS_DC);
int pdo_sqlsrv_stmt_describe_col(pdo_stmt_t *stmt, int colno TSRMLS_DC);
int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC);
char **ptr, unsigned long *len, int *caller_frees TSRMLS_DC);
int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC);
int pdo_sqlsrv_stmt_get_attr(pdo_stmt_t *stmt, long attr, zval *return_value TSRMLS_DC);
int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, long colno, zval *return_value TSRMLS_DC);
@ -243,12 +312,25 @@ void stmt_option_encoding:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*
{
set_stmt_encoding( stmt, value_z TSRMLS_CC );
}
void stmt_option_direct_query:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
{
pdo_sqlsrv_stmt *pdo_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt );
pdo_stmt->direct_query = ( zend_is_true( value_z )) ? true : false;
}
void stmt_option_cursor_scroll_type:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
{
set_stmt_cursor_scroll_type( stmt, value_z TSRMLS_CC );
}
void stmt_option_emulate_prepares:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
{
pdo_stmt_t *pdo_stmt = static_cast<pdo_stmt_t*>( stmt->driver() );
pdo_stmt->supports_placeholders = ( zend_is_true( value_z )) ? PDO_PLACEHOLDER_NONE : PDO_PLACEHOLDER_POSITIONAL;
}
// log a function entry point
#define PDO_LOG_STMT_ENTRY \
{ \
@ -257,6 +339,19 @@ void stmt_option_direct_query:: operator()( sqlsrv_stmt* stmt, stmt_option const
LOG( SEV_NOTICE, __FUNCTION__ ## ": entering" ); \
}
// PDO SQLSRV statement destructor
pdo_sqlsrv_stmt::~pdo_sqlsrv_stmt( void )
{
std::for_each( current_meta_data.begin(), current_meta_data.end(), meta_data_free );
current_meta_data.clear();
if( bound_column_param_types ) {
sqlsrv_free( bound_column_param_types );
bound_column_param_types = NULL;
}
}
// pdo_sqlsrv_stmt_close_cursor
// Close any open cursors on the statement. Maps to PDO function PDOStatement::closeCursor.
// Parameters:
@ -337,7 +432,7 @@ int pdo_sqlsrv_stmt_describe_col(pdo_stmt_t *stmt, int colno TSRMLS_DC)
// Set the namelen
column_data->namelen = core_meta_data->field_name_len;
// Set the maxlen
column_data->maxlen = ( core_meta_data->field_precision > 0 ) ? core_meta_data->field_precision : core_meta_data->field_size;
@ -345,10 +440,14 @@ int pdo_sqlsrv_stmt_describe_col(pdo_stmt_t *stmt, int colno TSRMLS_DC)
column_data->precision = core_meta_data->field_scale;
// Set the param_type
column_data->param_type = sql_type_to_pdo_type( core_meta_data->field_type );
column_data->param_type = PDO_PARAM_ZVAL;
// always good to call destructor for allocations done through placement new operator.
core_meta_data->~field_meta_data();
// store the field data for use by pdo_sqlsrv_stmt_get_col_data
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
SQLSRV_ASSERT( driver_stmt != NULL, "Invalid driver statement in pdo_sqlsrv_stmt_describe_col" );
driver_stmt->current_meta_data.push_back( core_meta_data.get() );
SQLSRV_ASSERT( driver_stmt->current_meta_data.size() == colno + 1, "Meta data vector out of sync with column numbers" );
core_meta_data.transferred();
return 1;
}
@ -407,8 +506,24 @@ int pdo_sqlsrv_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC)
core_sqlsrv_next_result( driver_stmt TSRMLS_CC, false );
}
}
const char* query = NULL;
unsigned int query_len = 0;
core_sqlsrv_execute( driver_stmt TSRMLS_CC, driver_stmt->query, driver_stmt->query_len );
// if the user is doing a direct query (PDO::SQLSRV_ATTR_DIRECT_QUERY), set the query here
if( driver_stmt->direct_query ) {
query = stmt->query_string;
query_len = stmt->query_stringlen;
}
// if the user is using prepare emulation (PDO::ATTR_EMULATE_PREPARES), set the query to the
// subtituted query provided by PDO
if( stmt->supports_placeholders == PDO_PLACEHOLDER_NONE ) {
query = stmt->active_query_string;
query_len = stmt->active_query_stringlen;
}
core_sqlsrv_execute( driver_stmt TSRMLS_CC, query, query_len );
stmt->column_count = core::SQLNumResultCols( driver_stmt TSRMLS_CC );
@ -468,16 +583,48 @@ int pdo_sqlsrv_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori,
SQLSRV_ASSERT( stmt != NULL, "pdo_sqlsrv_stmt_fetch: pdo_stmt object was null" );
sqlsrv_stmt* driver_stmt = reinterpret_cast<sqlsrv_stmt*>( stmt->driver_data );
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_fetch: driver_data object was null" );
// set the types for bound columns to zval so that PDO does no conversion when the value
// is returned by pdo_sqlsrv_get_col_data. Remember the types that were bound by the user
// and use it to manually convert data types
if( stmt->bound_columns ) {
pdo_bound_param_data* bind_data = NULL;
if( !driver_stmt->bound_column_param_types ) {
driver_stmt->bound_column_param_types =
reinterpret_cast<pdo_param_type*>( sqlsrv_malloc( stmt->column_count, sizeof( pdo_param_type ), 0 ));
std::fill( driver_stmt->bound_column_param_types, driver_stmt->bound_column_param_types + stmt->column_count,
PDO_PARAM_ZVAL );
}
for( long i = 0; i < stmt->column_count; ++i ) {
if( zend_hash_index_find( stmt->bound_columns, i, (void**) &bind_data ) == FAILURE &&
zend_hash_find( stmt->bound_columns, stmt->columns[ i ].name, stmt->columns[ i ].namelen,
(void**) &bind_data ) == FAILURE ) {
driver_stmt->bound_column_param_types[ i ] = PDO_PARAM_ZVAL;
continue;
}
if( bind_data->param_type != PDO_PARAM_ZVAL ) {
driver_stmt->bound_column_param_types[ i ] = bind_data->param_type;
bind_data->param_type = PDO_PARAM_ZVAL;
}
}
}
SQLSMALLINT odbc_fetch_ori = pdo_fetch_ori_to_odbc_fetch_ori( ori );
bool data = core_sqlsrv_fetch( driver_stmt, odbc_fetch_ori, offset TSRMLS_CC );
// support for the PDO rowCount method. Since rowCount doesn't call a method, PDO relies on us to fill the
// pdo_stmt_t::row_count member
if( driver_stmt->past_fetch_end || driver_stmt->scrollable ) {
if( driver_stmt->past_fetch_end || driver_stmt->cursor_type != SQL_CURSOR_FORWARD_ONLY ) {
stmt->row_count = core::SQLRowCount( driver_stmt TSRMLS_CC );
@ -531,7 +678,7 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
SQLSRV_ASSERT( stmt != NULL, "pdo_sqlsrv_stmt_get_col_data: pdo_stmt object was null" );
sqlsrv_stmt* driver_stmt = reinterpret_cast<sqlsrv_stmt*>( stmt->driver_data );
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_get_col_data: driver_data object was null" );
@ -547,12 +694,21 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
// translate the pdo type to a type the core layer understands
sqlsrv_phptype sqlsrv_php_type;
sqlsrv_php_type.typeinfo.type = pdo_type_to_sqlsrv_php_type( driver_stmt, column_data->param_type TSRMLS_CC );
SQLSRV_ASSERT( colno >= 0 && colno < static_cast<int>( driver_stmt->current_meta_data.size()),
"Invalid column number in pdo_sqlsrv_stmt_get_col_data" );
sqlsrv_php_type = driver_stmt->sql_type_to_php_type( driver_stmt->current_meta_data[ colno ]->field_type,
driver_stmt->current_meta_data[ colno ]->field_size, true );
// set the encoding if the user specified one via bindColumn, otherwise use the statement's encoding
sqlsrv_php_type.typeinfo.encoding = driver_stmt->encoding();
if( stmt->bound_columns ) {
// if a column is bound to a type different than the column type, figure out a way to convert it to the
// type they want
if( stmt->bound_columns && driver_stmt->bound_column_param_types[ colno ] != PDO_PARAM_ZVAL ) {
sqlsrv_php_type.typeinfo.type = pdo_type_to_sqlsrv_php_type( driver_stmt,
driver_stmt->bound_column_param_types[ colno ]
TSRMLS_CC );
pdo_bound_param_data* bind_data = NULL;
int zr = zend_hash_index_find( stmt->bound_columns, colno, (void**) &bind_data );
@ -560,13 +716,15 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
if( bind_data != NULL && bind_data->driver_params != NULL ) {
CHECK_CUSTOM_ERROR( Z_TYPE_P( bind_data->driver_params ) != IS_LONG, driver_stmt,
PDO_SQLSRV_ERROR_INVALID_COLUMN_DRIVER_DATA, colno ) {
PDO_SQLSRV_ERROR_INVALID_COLUMN_DRIVER_DATA, colno + 1 ) {
throw pdo::PDOException();
}
CHECK_CUSTOM_ERROR( bind_data->param_type != PDO_PARAM_STR && bind_data->param_type != PDO_PARAM_LOB,
driver_stmt, PDO_SQLSRV_ERROR_COLUMN_TYPE_DOES_NOT_SUPPORT_ENCODING, colno ) {
throw pdo::PDOException();
CHECK_CUSTOM_ERROR( driver_stmt->bound_column_param_types[ colno ] != PDO_PARAM_STR
&& driver_stmt->bound_column_param_types[ colno ] != PDO_PARAM_LOB, driver_stmt,
PDO_SQLSRV_ERROR_COLUMN_TYPE_DOES_NOT_SUPPORT_ENCODING, colno + 1 ) {
throw pdo::PDOException();
}
sqlsrv_php_type.typeinfo.encoding = Z_LVAL_P( bind_data->driver_params );
@ -582,9 +740,15 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
}
}
}
SQLSRV_PHPTYPE sqlsrv_phptype_out = SQLSRV_PHPTYPE_INVALID;
core_sqlsrv_get_field( driver_stmt, colno, sqlsrv_php_type, false, reinterpret_cast<void**>( ptr ),
reinterpret_cast<SQLLEN*>( len ), true, NULL TSRMLS_CC );
reinterpret_cast<SQLLEN*>( len ), true, &sqlsrv_phptype_out TSRMLS_CC );
zval** zval_ptr = reinterpret_cast<zval**>( sqlsrv_malloc( sizeof( zval* )));
*zval_ptr = reinterpret_cast<zval*>( convert_to_zval( sqlsrv_phptype_out, reinterpret_cast<void**>( ptr ), *len ));
*ptr = reinterpret_cast<char*>( zval_ptr );
*len = sizeof( zval );
return 1;
}
@ -633,6 +797,14 @@ int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC)
core_sqlsrv_set_query_timeout( driver_stmt, val TSRMLS_CC );
break;
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_CURSOR_ATTR_AT_PREPARE_ONLY );
break;
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
core_sqlsrv_set_buffered_query_limit( driver_stmt, val TSRMLS_CC );
break;
default:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
break;
@ -685,9 +857,23 @@ int pdo_sqlsrv_stmt_get_attr( pdo_stmt_t *stmt, long attr, zval *return_value TS
case PDO_ATTR_CURSOR:
{
ZVAL_LONG( return_value, ( driver_stmt->scrollable ? PDO_CURSOR_SCROLL : PDO_CURSOR_FWDONLY ));
ZVAL_LONG( return_value, ( driver_stmt->cursor_type != SQL_CURSOR_FORWARD_ONLY ?
PDO_CURSOR_SCROLL : PDO_CURSOR_FWDONLY ));
break;
}
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
{
ZVAL_LONG( return_value, driver_stmt->cursor_type );
break;
}
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
{
ZVAL_LONG( return_value, driver_stmt->buffered_query_limit );
break;
}
case SQLSRV_ATTR_QUERY_TIMEOUT:
{
ZVAL_LONG( return_value, ( driver_stmt->query_timeout == QUERY_TIMEOUT_INVALID ? 0 : driver_stmt->query_timeout ));
@ -755,7 +941,8 @@ int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, long colno, zval *return_valu
// get the PHP type of the column. The types returned here mirror the types returned by debug_zval_dump when
// given a variable of the same type. However, debug_zval_dump also gives the length of a string, and we only
// say string, since the length is given in another field of the metadata array.
switch( sql_type_to_pdo_type( core_meta_data->field_type )) {
long pdo_type = sql_type_to_pdo_type( core_meta_data->field_type );
switch( pdo_type ) {
case PDO_PARAM_STR:
add_assoc_string( return_value, "native_type", "string", 1 );
break;
@ -770,7 +957,11 @@ int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, long colno, zval *return_valu
core::SQLColAttribute( driver_stmt, (SQLUSMALLINT) colno + 1, SQL_DESC_TABLE_NAME, table_name, SQL_SERVER_IDENT_SIZE_MAX,
&out_buff_len, &field_type_num TSRMLS_CC );
add_assoc_string( return_value, "table", table_name, 1 );
if( stmt->columns[ colno ].param_type == PDO_PARAM_ZVAL ) {
add_assoc_long( return_value, "pdo_type", pdo_type );
}
// this will ensure that the field_name field, which is an auto pointer gets freed.
(*core_meta_data).~field_meta_data();
}
@ -807,12 +998,16 @@ int pdo_sqlsrv_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
SQLSRV_ASSERT( stmt != NULL, "pdo_sqlsrv_stmt_next_rowset: pdo_stmt object was null" );
sqlsrv_stmt* driver_stmt = reinterpret_cast<sqlsrv_stmt*>( stmt->driver_data );
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_next_rowset: driver_data object was null" );
core_sqlsrv_next_result( static_cast<sqlsrv_stmt*>( stmt->driver_data ) TSRMLS_CC );
// clear the current meta data since the new result will generate new meta data
std::for_each( driver_stmt->current_meta_data.begin(), driver_stmt->current_meta_data.end(), meta_data_free );
driver_stmt->current_meta_data.clear();
// if there are no more result sets, return that it failed.
if( driver_stmt->past_next_result_end == true ) {
return 0;
@ -822,7 +1017,6 @@ int pdo_sqlsrv_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
// return the row count regardless if there are any rows or not
stmt->row_count = core::SQLRowCount( driver_stmt TSRMLS_CC );
}
catch( core::CoreException& ) {
@ -971,7 +1165,7 @@ int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
// 2.0 driver. To be consistent and avoid surprises of one object type working and others
// not, we block all objects here.
CHECK_CUSTOM_ERROR( direction != SQL_PARAM_OUTPUT && Z_TYPE_P( param->parameter ) == IS_OBJECT,
driver_stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE ) {
driver_stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param->paramno + 1 ) {
throw pdo::PDOException();
}
// the encoding by default is that set on the statement
@ -987,7 +1181,7 @@ int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
throw pdo::PDOException();
}
CHECK_CUSTOM_ERROR( pdo_type != PDO_PARAM_STR && pdo_type != PDO_PARAM_LOB, driver_stmt,
PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM_TYPE, param->paramno ) {
PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM_TYPE, param->paramno + 1 ) {
throw pdo::PDOException();
}
encoding = static_cast<SQLSRV_ENCODING>( Z_LVAL_P( param->driver_params ));
@ -999,7 +1193,7 @@ int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
break;
default:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM_ENCODING,
param->paramno );
param->paramno + 1 );
break;
}
}

View file

@ -3,7 +3,7 @@
//
// Contents: Utility functions used by both connection or statement functions
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -144,8 +144,8 @@ pdo_error PDO_ERRORS[] = {
},
{
SQLSRV_ERROR_UNESCAPED_RIGHT_BRACE_IN_DSN,
{ IMSSP, (SQLCHAR*) "An unescaped right brace (}) was found in the DSN string for keyword '%1!s!'. All right braces must be escaped "
"with another right brace (}}).", -22, true }
{ IMSSP, (SQLCHAR*) "An unescaped right brace (}) was found in the DSN string for keyword '%1!s!'. All right braces "
"must be escaped with another right brace (}}).", -22, true }
},
{
SQLSRV_ERROR_INVALID_OPTION_TYPE_INT,
@ -184,8 +184,8 @@ pdo_error PDO_ERRORS[] = {
{ IMSSP, (SQLCHAR*) "Invalid option key %1!s! specified.", -30, true }
},
{
SQLSRV_ERROR_INVALID_OPTION_VALUE,
{ IMSSP, (SQLCHAR*) "Invalid value specified for option %1!s!.", -31, true }
SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE,
{ IMSSP, (SQLCHAR*) "Invalid value %1!s! specified for option PDO::SQLSRV_ATTR_QUERY_TIMEOUT.", -31, true }
},
{
SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE,
@ -238,7 +238,8 @@ pdo_error PDO_ERRORS[] = {
},
{
PDO_SQLSRV_ERROR_INVALID_CURSOR_TYPE,
{ IMSSP, (SQLCHAR*) "An invalid cursor type was specified for the PDO cursor attribute", -44, false }
{ IMSSP, (SQLCHAR*) "An invalid cursor type was specified for either PDO::ATTR_CURSOR or "
"PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE", -44, false }
},
{
PDO_SQLSRV_ERROR_PARAM_PARSE,
@ -277,8 +278,8 @@ pdo_error PDO_ERRORS[] = {
},
{
PDO_SQLSRV_ERROR_CURSOR_ATTR_AT_PREPARE_ONLY,
{ IMSSP, (SQLCHAR*) "The PDO::ATTR_CURSOR attribute may only be set in the $driver_options array of PDO::prepare.",
-53, false }
{ IMSSP, (SQLCHAR*) "The PDO::ATTR_CURSOR and PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE attributes may only be set in the "
"$driver_options array of PDO::prepare.", -53, false }
},
{
SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED,
@ -340,17 +341,33 @@ pdo_error PDO_ERRORS[] = {
},
{
PDO_SQLSRV_ERROR_EXTRA_SEMI_COLON_IN_DSN_STRING,
{ IMSSP, (SQLCHAR*) "An extra semi-colon was encountered in the DSN string at character (byte-count) position '%1!d!' .", -66, true }
{ IMSSP, (SQLCHAR*) "An extra semi-colon was encountered in the DSN string at character (byte-count) position '%1!d!' .",
-66, true }
},
{
PDO_SQLSRV_ERROR_RCB_MISSING_IN_DSN_VALUE,
{ IMSSP, (SQLCHAR*) "An expected right brace (}) was not found in the DSN string for the value of the keyword '%1!s!'.", -67, true }
{ IMSSP, (SQLCHAR*) "An expected right brace (}) was not found in the DSN string for the value of the keyword '%1!s!'.",
-67, true }
},
{
PDO_SQLSRV_ERROR_DQ_ATTR_AT_PREPARE_ONLY,
{ IMSSP, (SQLCHAR*) "The PDO::SQLSRV_ATTR_DIRECT_QUERY attribute may only be set in the $driver_options array of "
"PDO::prepare.", -68, false }
},
{
PDO_SQLSRV_ERROR_INVALID_CURSOR_WITH_SCROLL_TYPE,
{ IMSSP, (SQLCHAR*) "The PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE attribute may only be set when PDO::ATTR_CURSOR is set to "
"PDO::CURSOR_SCROLL in the $driver_options array of PDO::prepare.", -69, false }
},
{
SQLSRV_ERROR_INVALID_BUFFER_LIMIT,
{ IMSSP, (SQLCHAR*) "The PDO::SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE attribute is not a number or the number is not "
"positive. Only positive numbers are valid for this attribute.", -70, false }
},
{
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED,
{ IMSSP, (SQLCHAR*) "Memory limit of %1!d! KB exceeded for buffered query", -71, true }
},
{ -1, {} }
};
@ -378,7 +395,6 @@ bool pdo_sqlsrv_handle_env_error( sqlsrv_context& ctx, unsigned int sqlsrv_error
SQLSRV_ASSERT(( dbh != NULL ), "pdo_sqlsrv_handle_env_error: pdo_dbh_t was null" );
sqlsrv_error_auto_ptr error;
error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error;
if( sqlsrv_error_code != SQLSRV_ERROR_ODBC ) {
@ -386,7 +402,8 @@ bool pdo_sqlsrv_handle_env_error( sqlsrv_context& ctx, unsigned int sqlsrv_error
}
else {
core_sqlsrv_get_odbc_error( ctx, 1, error, SEV_ERROR TSRMLS_CC );
bool err = core_sqlsrv_get_odbc_error( ctx, 1, error, SEV_ERROR TSRMLS_CC );
SQLSRV_ASSERT( err == true, "No ODBC error was found" );
}
strcpy_s( dbh->error_code, sizeof( pdo_error_type ), reinterpret_cast<const char*>( error->sqlstate ));
@ -420,14 +437,14 @@ bool pdo_sqlsrv_handle_dbh_error( sqlsrv_context& ctx, unsigned int sqlsrv_error
SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_handle_dbh_error: Null dbh passed" );
sqlsrv_error_auto_ptr error;
error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error;
if( sqlsrv_error_code != SQLSRV_ERROR_ODBC ) {
core_sqlsrv_format_driver_error( ctx, get_error_message( sqlsrv_error_code ), error, SEV_ERROR TSRMLS_CC, print_args );
}
else {
core_sqlsrv_get_odbc_error( ctx, 1, error, SEV_ERROR TSRMLS_CC );
bool err = core_sqlsrv_get_odbc_error( ctx, 1, error, SEV_ERROR TSRMLS_CC );
SQLSRV_ASSERT( err == true, "No ODBC error was found" );
}
SQLSRV_STATIC_ASSERT( sizeof( error->sqlstate ) <= sizeof( dbh->error_code ));
@ -474,13 +491,13 @@ bool pdo_sqlsrv_handle_stmt_error( sqlsrv_context& ctx, unsigned int sqlsrv_erro
SQLSRV_ASSERT( pdo_stmt != NULL && pdo_stmt->dbh != NULL, "pdo_sqlsrv_handle_stmt_error: Null statement or dbh passed" );
sqlsrv_error_auto_ptr error;
error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error;
if( sqlsrv_error_code != SQLSRV_ERROR_ODBC ) {
core_sqlsrv_format_driver_error( ctx, get_error_message( sqlsrv_error_code ), error, SEV_ERROR TSRMLS_CC, print_args );
}
else {
core_sqlsrv_get_odbc_error( ctx, 1, error, SEV_ERROR TSRMLS_CC );
bool err = core_sqlsrv_get_odbc_error( ctx, 1, error, SEV_ERROR TSRMLS_CC );
SQLSRV_ASSERT( err == true, "No ODBC error was found" );
}
SQLSRV_STATIC_ASSERT( sizeof( error->sqlstate ) <= sizeof( pdo_stmt->error_code ));

3043
pdo_sqlsrv/sqlncli.h Normal file
View file

@ -0,0 +1,3043 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 7.00.0474 */
/* Compiler settings for sqlncli.idl:
Oicf, W1, Zp8, env=Win32 (32b run)
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/
#ifndef __sqlncli_h__
#define __sqlncli_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
#ifndef __ICommandWithParameters_FWD_DEFINED__
#define __ICommandWithParameters_FWD_DEFINED__
typedef interface ICommandWithParameters ICommandWithParameters;
#endif /* __ICommandWithParameters_FWD_DEFINED__ */
#ifndef __IUMSInitialize_FWD_DEFINED__
#define __IUMSInitialize_FWD_DEFINED__
typedef interface IUMSInitialize IUMSInitialize;
#endif /* __IUMSInitialize_FWD_DEFINED__ */
#ifndef __ISQLServerErrorInfo_FWD_DEFINED__
#define __ISQLServerErrorInfo_FWD_DEFINED__
typedef interface ISQLServerErrorInfo ISQLServerErrorInfo;
#endif /* __ISQLServerErrorInfo_FWD_DEFINED__ */
#ifndef __IRowsetFastLoad_FWD_DEFINED__
#define __IRowsetFastLoad_FWD_DEFINED__
typedef interface IRowsetFastLoad IRowsetFastLoad;
#endif /* __IRowsetFastLoad_FWD_DEFINED__ */
#ifndef __ISchemaLock_FWD_DEFINED__
#define __ISchemaLock_FWD_DEFINED__
typedef interface ISchemaLock ISchemaLock;
#endif /* __ISchemaLock_FWD_DEFINED__ */
#ifndef __IBCPSession_FWD_DEFINED__
#define __IBCPSession_FWD_DEFINED__
typedef interface IBCPSession IBCPSession;
#endif /* __IBCPSession_FWD_DEFINED__ */
#ifndef __ISSAbort_FWD_DEFINED__
#define __ISSAbort_FWD_DEFINED__
typedef interface ISSAbort ISSAbort;
#endif /* __ISSAbort_FWD_DEFINED__ */
#ifndef __ISSCommandWithParameters_FWD_DEFINED__
#define __ISSCommandWithParameters_FWD_DEFINED__
typedef interface ISSCommandWithParameters ISSCommandWithParameters;
#endif /* __ISSCommandWithParameters_FWD_DEFINED__ */
#ifndef __IDBAsynchStatus_FWD_DEFINED__
#define __IDBAsynchStatus_FWD_DEFINED__
typedef interface IDBAsynchStatus IDBAsynchStatus;
#endif /* __IDBAsynchStatus_FWD_DEFINED__ */
#ifndef __ISSAsynchStatus_FWD_DEFINED__
#define __ISSAsynchStatus_FWD_DEFINED__
typedef interface ISSAsynchStatus ISSAsynchStatus;
#endif /* __ISSAsynchStatus_FWD_DEFINED__ */
/* header files for imported files */
#include "unknwn.h"
#include "oaidl.h"
#ifdef __cplusplus
extern "C"{
#endif
/* interface __MIDL_itf_sqlncli_0000_0000 */
/* [local] */
//-----------------------------------------------------------------------------
// File: sqlncli.h
//
// Copyright: Copyright (c) Microsoft Corporation
//
// Contents: SQL Server Native Client OLEDB provider and ODBC driver specific
// definitions.
//
//-----------------------------------------------------------------------------
#if !defined(SQLNCLI_VER)
#define SQLNCLI_VER 1000
#endif
#if SQLNCLI_VER >= 1000
#define SQLNCLI_PRODUCT_NAME_FULL_VER_ANSI "Microsoft SQL Server Native Client 10.0"
#define SQLNCLI_PRODUCT_NAME_FULL_ANSI "Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_VER_ANSI "SQL Server Native Client 10.0"
#define SQLNCLI_PRODUCT_NAME_SHORT_ANSI "SQL Server Native Client"
#define SQLNCLI_FILE_NAME_ANSI "sqlncli"
#define SQLNCLI_FILE_NAME_VER_ANSI "sqlncli10"
#define SQLNCLI_FILE_NAME_FULL_ANSI "sqlncli10.dll"
#define SQLNCLI_PRODUCT_NAME_FULL_VER_UNICODE L"Microsoft SQL Server Native Client 10.0"
#define SQLNCLI_PRODUCT_NAME_FULL_UNICODE L"Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_VER_UNICODE L"SQL Server Native Client 10.0"
#define SQLNCLI_PRODUCT_NAME_SHORT_UNICODE L"SQL Server Native Client"
#define SQLNCLI_FILE_NAME_UNICODE L"sqlncli"
#define SQLNCLI_FILE_NAME_VER_UNICODE L"sqlncli10"
#define SQLNCLI_FILE_NAME_FULL_UNICODE L"sqlncli10.dll"
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#define SQLNCLI_VI_PROG_ID_ANSI "SQLNCLI10"
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_ANSI "SQLNCLI10 ErrorLookup"
#define SQLNCLI_VI_ENUMERATOR_PROG_ID_ANSI "SQLNCLI10 Enumerator"
#define SQLNCLI_PROG_ID_ANSI "SQLNCLI10.1"
#define SQLNCLI_ERROR_LOOKUP_PROG_ID_ANSI "SQLNCLI10 ErrorLookup.1"
#define SQLNCLI_ENUMERATOR_PROG_ID_ANSI "SQLNCLI10 Enumerator.1"
#define SQLNCLI_VI_PROG_ID_UNICODE L"SQLNCLI10"
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_UNICODE L"SQLNCLI10 ErrorLookup"
#define SQLNCLI_VI_ENUMERATOR_PROG_ID_UNICODE L"SQLNCLI10 Enumerator"
#define SQLNCLI_PROG_ID_UNICODE L"SQLNCLI10.1"
#define SQLNCLI_ERROR_LOOKUP_PROG_ID_UNICODE L"SQLNCLI10 ErrorLookup.1"
#define SQLNCLI_ENUMERATOR_PROG_ID_UNICODE L"SQLNCLI10 Enumerator.1"
#define SQLNCLI_CLSID CLSID_SQLNCLI10
#define SQLNCLI_ERROR_CLSID CLSID_SQLNCLI10_ERROR
#define SQLNCLI_ENUMERATOR_CLSID CLSID_SQLNCLI10_ENUMERATOR
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#else // SQLNCLI_VER >= 1000
#define SQLNCLI_PRODUCT_NAME_FULL_VER_ANSI "Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_FULL_ANSI "Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_VER_ANSI "SQL Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_ANSI "SQL Native Client"
#define SQLNCLI_FILE_NAME_ANSI "sqlncli"
#define SQLNCLI_FILE_NAME_VER_ANSI "sqlncli"
#define SQLNCLI_FILE_NAME_FULL_ANSI "sqlncli.dll"
#define SQLNCLI_PRODUCT_NAME_FULL_VER_UNICODE L"Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_FULL_UNICODE L"Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_VER_UNICODE L"SQL Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_UNICODE L"SQL Native Client"
#define SQLNCLI_FILE_NAME_UNICODE L"sqlncli"
#define SQLNCLI_FILE_NAME_VER_UNICODE L"sqlncli"
#define SQLNCLI_FILE_NAME_FULL_UNICODE L"sqlncli.dll"
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#define SQLNCLI_VI_PROG_ID_ANSI "SQLNCLI"
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_ANSI "SQLNCLI ErrorLookup"
#define SQLNCLI_VI_ENUMERATOR_PROG_ID_ANSI "SQLNCLI Enumerator"
#define SQLNCLI_PROG_ID_ANSI "SQLNCLI.1"
#define SQLNCLI_ERROR_LOOKUP_PROG_ID_ANSI "SQLNCLI ErrorLookup.1"
#define SQLNCLI_ENUMERATOR_PROG_ID_ANSI "SQLNCLI Enumerator.1"
#define SQLNCLI_VI_PROG_ID_UNICODE L"SQLNCLI"
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_UNICODE L"SQLNCLI ErrorLookup"
#define SQLNCLI_VI_ENUMERATOR_PROG_ID_UNICODE L"SQLNCLI Enumerator"
#define SQLNCLI_PROG_ID_UNICODE L"SQLNCLI.1"
#define SQLNCLI_ERROR_LOOKUP_PROG_ID_UNICODE L"SQLNCLI ErrorLookup.1"
#define SQLNCLI_ENUMERATOR_PROG_ID_UNICODE L"SQLNCLI Enumerator.1"
#define SQLNCLI_CLSID CLSID_SQLNCLI
#define SQLNCLI_ERROR_CLSID CLSID_SQLNCLI_ERROR
#define SQLNCLI_ENUMERATOR_CLSID CLSID_SQLNCLI_ENUMERATOR
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#endif // SQLNCLI_VER >= 1000
// define the character type agnostic constants
#if defined(_UNICODE) || defined(UNICODE)
#define SQLNCLI_PRODUCT_NAME_FULL_VER SQLNCLI_PRODUCT_NAME_FULL_VER_UNICODE
#define SQLNCLI_PRODUCT_NAME_FULL SQLNCLI_PRODUCT_NAME_FULL_UNICODE
#define SQLNCLI_PRODUCT_NAME_SHORT_VER SQLNCLI_PRODUCT_NAME_SHORT_VER_UNICODE
#define SQLNCLI_PRODUCT_NAME_SHORT SQLNCLI_PRODUCT_NAME_SHORT_UNICODE
#define SQLNCLI_FILE_NAME SQLNCLI_FILE_NAME_UNICODE
#define SQLNCLI_FILE_NAME_VER SQLNCLI_FILE_NAME_VER_UNICODE
#define SQLNCLI_FILE_NAME_FULL SQLNCLI_FILE_NAME_FULL_UNICODE
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#define SQLNCLI_VI_PROG_ID SQLNCLI_VI_PROG_ID_UNICODE
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_UNICODE
#define SQLNCLI_VI_ENUMERATOR_PROG_ID SQLNCLI_VI_ENUMERATOR_PROG_ID_UNICODE
#define SQLNCLI_PROG_ID SQLNCLI_PROG_ID_UNICODE
#define SQLNCLI_ERROR_LOOKUP_PROG_ID SQLNCLI_ERROR_LOOKUP_PROG_ID_UNICODE
#define SQLNCLI_ENUMERATOR_PROG_ID SQLNCLI_ENUMERATOR_PROG_ID_UNICODE
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#else // _UNICODE || UNICODE
#define SQLNCLI_PRODUCT_NAME_FULL_VER SQLNCLI_PRODUCT_NAME_FULL_VER_ANSI
#define SQLNCLI_PRODUCT_NAME_FULL SQLNCLI_PRODUCT_NAME_FULL_ANSI
#define SQLNCLI_PRODUCT_NAME_SHORT_VER SQLNCLI_PRODUCT_NAME_SHORT_VER_ANSI
#define SQLNCLI_PRODUCT_NAME_SHORT SQLNCLI_PRODUCT_NAME_SHORT_ANSI
#define SQLNCLI_FILE_NAME SQLNCLI_FILE_NAME_ANSI
#define SQLNCLI_FILE_NAME_VER SQLNCLI_FILE_NAME_VER_ANSI
#define SQLNCLI_FILE_NAME_FULL SQLNCLI_FILE_NAME_FULL_ANSI
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#define SQLNCLI_VI_PROG_ID SQLNCLI_VI_PROG_ID_ANSI
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_ANSI
#define SQLNCLI_VI_ENUMERATOR_PROG_ID SQLNCLI_VI_ENUMERATOR_PROG_ID_ANSI
#define SQLNCLI_PROG_ID SQLNCLI_PROG_ID_ANSI
#define SQLNCLI_ERROR_LOOKUP_PROG_ID SQLNCLI_ERROR_LOOKUP_PROG_ID_ANSI
#define SQLNCLI_ENUMERATOR_PROG_ID SQLNCLI_ENUMERATOR_PROG_ID_ANSI
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#endif // _UNICODE || UNICODE
#if defined(_SQLNCLI_ODBC_) || !defined(_SQLNCLI_OLEDB_)
#define SQLNCLI_DRIVER_NAME SQLNCLI_PRODUCT_NAME_SHORT_VER
#endif
// OLEDB part of SQL Server Native Client header - begin here
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#ifndef __oledb_h__
#include <oledb.h>
#endif /*__oledb_h__*/
#if 0 // This is already defined in oledb.h
#ifdef _WIN64
// Length of a non-character object, size
typedef ULONGLONG DBLENGTH;
// Offset within a rowset
typedef LONGLONG DBROWOFFSET;
// Number of rows
typedef LONGLONG DBROWCOUNT;
typedef ULONGLONG DBCOUNTITEM;
// Ordinal (column number, etc.)
typedef ULONGLONG DBORDINAL;
typedef LONGLONG DB_LORDINAL;
// Bookmarks
typedef ULONGLONG DBBKMARK;
// Offset in the buffer
typedef ULONGLONG DBBYTEOFFSET;
// Reference count of each row/accessor handle
typedef ULONG DBREFCOUNT;
// Parameters
typedef ULONGLONG DB_UPARAMS;
typedef LONGLONG DB_LPARAMS;
// hash values corresponding to the elements (bookmarks)
typedef DWORDLONG DBHASHVALUE;
// For reserve
typedef DWORDLONG DB_DWRESERVE;
typedef LONGLONG DB_LRESERVE;
typedef ULONGLONG DB_URESERVE;
#else //_WIN64
// Length of a non-character object, size
typedef ULONG DBLENGTH;
// Offset within a rowset
typedef LONG DBROWOFFSET;
// Number of rows
typedef LONG DBROWCOUNT;
typedef ULONG DBCOUNTITEM;
// Ordinal (column number, etc.)
typedef ULONG DBORDINAL;
typedef LONG DB_LORDINAL;
// Bookmarks
typedef ULONG DBBKMARK;
// Offset in the buffer
typedef ULONG DBBYTEOFFSET;
// Reference count of each row handle
typedef ULONG DBREFCOUNT;
// Parameters
typedef ULONG DB_UPARAMS;
typedef LONG DB_LPARAMS;
// hash values corresponding to the elements (bookmarks)
typedef DWORD DBHASHVALUE;
// For reserve
typedef DWORD DB_DWRESERVE;
typedef LONG DB_LRESERVE;
typedef ULONG DB_URESERVE;
#endif // _WIN64
typedef DWORD DBKIND;
enum DBKINDENUM
{ DBKIND_GUID_NAME = 0,
DBKIND_GUID_PROPID = ( DBKIND_GUID_NAME + 1 ) ,
DBKIND_NAME = ( DBKIND_GUID_PROPID + 1 ) ,
DBKIND_PGUID_NAME = ( DBKIND_NAME + 1 ) ,
DBKIND_PGUID_PROPID = ( DBKIND_PGUID_NAME + 1 ) ,
DBKIND_PROPID = ( DBKIND_PGUID_PROPID + 1 ) ,
DBKIND_GUID = ( DBKIND_PROPID + 1 )
} ;
typedef struct tagDBID
{
union
{
GUID guid;
GUID *pguid;
/* Empty union arm */
} uGuid;
DBKIND eKind;
union
{
LPOLESTR pwszName;
ULONG ulPropid;
/* Empty union arm */
} uName;
} DBID;
typedef struct tagDB_NUMERIC
{
BYTE precision;
BYTE scale;
BYTE sign;
BYTE val[ 16 ];
} DB_NUMERIC;
typedef struct tagDBDATE
{
SHORT year;
USHORT month;
USHORT day;
} DBDATE;
typedef struct tagDBTIME
{
USHORT hour;
USHORT minute;
USHORT second;
} DBTIME;
typedef struct tagDBTIMESTAMP
{
SHORT year;
USHORT month;
USHORT day;
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
} DBTIMESTAMP;
typedef struct tagDBOBJECT
{
DWORD dwFlags;
IID iid;
} DBOBJECT;
typedef WORD DBTYPE;
typedef ULONG_PTR HACCESSOR;
typedef ULONG_PTR HCHAPTER;
typedef DWORD DBPARAMFLAGS;
typedef struct tagDBPARAMINFO
{
DBPARAMFLAGS dwFlags;
DBORDINAL iOrdinal;
LPOLESTR pwszName;
ITypeInfo *pTypeInfo;
DBLENGTH ulParamSize;
DBTYPE wType;
BYTE bPrecision;
BYTE bScale;
} DBPARAMINFO;
typedef DWORD DBPROPID;
typedef struct tagDBPROPIDSET
{
DBPROPID *rgPropertyIDs;
ULONG cPropertyIDs;
GUID guidPropertySet;
} DBPROPIDSET;
typedef DWORD DBPROPFLAGS;
typedef DWORD DBPROPOPTIONS;
typedef DWORD DBPROPSTATUS;
typedef struct tagDBPROP
{
DBPROPID dwPropertyID;
DBPROPOPTIONS dwOptions;
DBPROPSTATUS dwStatus;
DBID colid;
VARIANT vValue;
} DBPROP;
typedef struct tagDBPROPSET
{
DBPROP *rgProperties;
ULONG cProperties;
GUID guidPropertySet;
} DBPROPSET;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0000_v0_0_s_ifspec;
#ifndef __ICommandWithParameters_INTERFACE_DEFINED__
#define __ICommandWithParameters_INTERFACE_DEFINED__
/* interface ICommandWithParameters */
/* [unique][uuid][object][local] */
typedef struct tagDBPARAMBINDINFO
{
LPOLESTR pwszDataSourceType;
LPOLESTR pwszName;
DBLENGTH ulParamSize;
DBPARAMFLAGS dwFlags;
BYTE bPrecision;
BYTE bScale;
} DBPARAMBINDINFO;
EXTERN_C const IID IID_ICommandWithParameters;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("0c733a64-2a1c-11ce-ade5-00aa0044773d")
ICommandWithParameters : public IUnknown
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetParameterInfo(
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ DBPARAMINFO **prgParamInfo,
/* [out] */ OLECHAR **ppNamesBuffer) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE MapParameterNames(
/* [in] */ DB_UPARAMS cParamNames,
/* [size_is][in] */ const OLECHAR *rgParamNames[ ],
/* [size_is][out] */ DB_LPARAMS rgParamOrdinals[ ]) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE SetParameterInfo(
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ const DB_UPARAMS rgParamOrdinals[ ],
/* [size_is][unique][in] */ const DBPARAMBINDINFO rgParamBindInfo[ ]) = 0;
};
#else /* C style interface */
typedef struct ICommandWithParametersVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ICommandWithParameters * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ICommandWithParameters * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ICommandWithParameters * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetParameterInfo )(
ICommandWithParameters * This,
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ DBPARAMINFO **prgParamInfo,
/* [out] */ OLECHAR **ppNamesBuffer);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *MapParameterNames )(
ICommandWithParameters * This,
/* [in] */ DB_UPARAMS cParamNames,
/* [size_is][in] */ const OLECHAR *rgParamNames[ ],
/* [size_is][out] */ DB_LPARAMS rgParamOrdinals[ ]);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetParameterInfo )(
ICommandWithParameters * This,
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ const DB_UPARAMS rgParamOrdinals[ ],
/* [size_is][unique][in] */ const DBPARAMBINDINFO rgParamBindInfo[ ]);
END_INTERFACE
} ICommandWithParametersVtbl;
interface ICommandWithParameters
{
CONST_VTBL struct ICommandWithParametersVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ICommandWithParameters_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ICommandWithParameters_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ICommandWithParameters_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ICommandWithParameters_GetParameterInfo(This,pcParams,prgParamInfo,ppNamesBuffer) \
( (This)->lpVtbl -> GetParameterInfo(This,pcParams,prgParamInfo,ppNamesBuffer) )
#define ICommandWithParameters_MapParameterNames(This,cParamNames,rgParamNames,rgParamOrdinals) \
( (This)->lpVtbl -> MapParameterNames(This,cParamNames,rgParamNames,rgParamOrdinals) )
#define ICommandWithParameters_SetParameterInfo(This,cParams,rgParamOrdinals,rgParamBindInfo) \
( (This)->lpVtbl -> SetParameterInfo(This,cParams,rgParamOrdinals,rgParamBindInfo) )
#endif /* COBJMACROS */
#endif /* C style interface */
/* [call_as] */ HRESULT STDMETHODCALLTYPE ICommandWithParameters_RemoteGetParameterInfo_Proxy(
ICommandWithParameters * This,
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ DBPARAMINFO **prgParamInfo,
/* [size_is][size_is][out] */ DBBYTEOFFSET **prgNameOffsets,
/* [out][in] */ DBLENGTH *pcbNamesBuffer,
/* [size_is][size_is][unique][out][in] */ OLECHAR **ppNamesBuffer,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB ICommandWithParameters_RemoteGetParameterInfo_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
/* [call_as] */ HRESULT STDMETHODCALLTYPE ICommandWithParameters_RemoteMapParameterNames_Proxy(
ICommandWithParameters * This,
/* [in] */ DB_UPARAMS cParamNames,
/* [size_is][in] */ LPCOLESTR *rgParamNames,
/* [size_is][out] */ DB_LPARAMS *rgParamOrdinals,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB ICommandWithParameters_RemoteMapParameterNames_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
/* [call_as] */ HRESULT STDMETHODCALLTYPE ICommandWithParameters_RemoteSetParameterInfo_Proxy(
ICommandWithParameters * This,
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ const DB_UPARAMS *rgParamOrdinals,
/* [size_is][unique][in] */ const DBPARAMBINDINFO *rgParamBindInfo,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB ICommandWithParameters_RemoteSetParameterInfo_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __ICommandWithParameters_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0001 */
/* [local] */
typedef DWORD DBASYNCHOP;
typedef DWORD DBASYNCHPHASE;
#endif // This is already defined in oledb.h
//-------------------------------------------------------------------
// Variant Access macros, similar to ole automation.
//-------------------------------------------------------------------
#define V_SS_VT(X) ((X)->vt)
#define V_SS_UNION(X, Y) ((X)->Y)
#define V_SS_UI1(X) V_SS_UNION(X, bTinyIntVal)
#define V_SS_I2(X) V_SS_UNION(X, sShortIntVal)
#define V_SS_I4(X) V_SS_UNION(X, lIntVal)
#define V_SS_I8(X) V_SS_UNION(X, llBigIntVal)
#define V_SS_R4(X) V_SS_UNION(X, fltRealVal)
#define V_SS_R8(X) V_SS_UNION(X, dblFloatVal)
#define V_SS_UI4(X) V_SS_UNION(X, ulVal)
#define V_SS_MONEY(X) V_SS_UNION(X, cyMoneyVal)
#define V_SS_SMALLMONEY(X) V_SS_UNION(X, cyMoneyVal)
#define V_SS_WSTRING(X) V_SS_UNION(X, NCharVal)
#define V_SS_WVARSTRING(X) V_SS_UNION(X, NCharVal)
#define V_SS_STRING(X) V_SS_UNION(X, CharVal)
#define V_SS_VARSTRING(X) V_SS_UNION(X, CharVal)
#define V_SS_BIT(X) V_SS_UNION(X, fBitVal)
#define V_SS_GUID(X) V_SS_UNION(X, rgbGuidVal)
#define V_SS_NUMERIC(X) V_SS_UNION(X, numNumericVal)
#define V_SS_DECIMAL(X) V_SS_UNION(X, numNumericVal)
#define V_SS_BINARY(X) V_SS_UNION(X, BinaryVal)
#define V_SS_VARBINARY(X) V_SS_UNION(X, BinaryVal)
#define V_SS_DATETIME(X) V_SS_UNION(X, tsDateTimeVal)
#define V_SS_SMALLDATETIME(X) V_SS_UNION(X, tsDateTimeVal)
#define V_SS_UNKNOWN(X) V_SS_UNION(X, UnknownType)
//Text and image types.
#define V_SS_IMAGE(X) V_SS_UNION(X, ImageVal)
#define V_SS_TEXT(X) V_SS_UNION(X, TextVal)
#define V_SS_NTEXT(X) V_SS_UNION(X, NTextVal)
//Microsoft SQL Server 2008 datetime.
#define V_SS_DATE(X) V_SS_UNION(X, dDateVal)
#define V_SS_TIME2(X) V_SS_UNION(X, Time2Val)
#define V_SS_DATETIME2(X) V_SS_UNION(X, DateTimeVal)
#define V_SS_DATETIMEOFFSET(X) V_SS_UNION(X, DateTimeOffsetVal)
//-------------------------------------------------------------------
// define SQL Server specific types.
//-------------------------------------------------------------------
typedef enum DBTYPEENUM EOledbTypes;
#define DBTYPE_XML ((EOledbTypes) 141) // introduced in SQL 2005
#define DBTYPE_TABLE ((EOledbTypes) 143) // introduced in SQL 2008
#define DBTYPE_DBTIME2 ((EOledbTypes) 145) // introduced in SQL 2008
#define DBTYPE_DBTIMESTAMPOFFSET ((EOledbTypes) 146) // introduced in SQL 2008
#ifdef _SQLOLEDB_H_
#undef DBTYPE_SQLVARIANT
#endif //_SQLOLEDB_H_
#define DBTYPE_SQLVARIANT ((EOledbTypes) 144) // introduced in MDAC 2.5
#ifndef _SQLOLEDB_H_
enum SQLVARENUM
{
VT_SS_EMPTY = DBTYPE_EMPTY,
VT_SS_NULL = DBTYPE_NULL,
VT_SS_UI1 = DBTYPE_UI1,
VT_SS_I2 = DBTYPE_I2,
VT_SS_I4 = DBTYPE_I4,
VT_SS_I8 = DBTYPE_I8,
//Floats
VT_SS_R4 = DBTYPE_R4,
VT_SS_R8 = DBTYPE_R8,
//Money
VT_SS_MONEY = DBTYPE_CY,
VT_SS_SMALLMONEY = 200,
//Strings
VT_SS_WSTRING = 201,
VT_SS_WVARSTRING = 202,
VT_SS_STRING = 203,
VT_SS_VARSTRING = 204,
//Bit
VT_SS_BIT = DBTYPE_BOOL,
//Guid
VT_SS_GUID = DBTYPE_GUID,
//Exact precision
VT_SS_NUMERIC = DBTYPE_NUMERIC,
VT_SS_DECIMAL = 205,
//Datetime
VT_SS_DATETIME = DBTYPE_DBTIMESTAMP,
VT_SS_SMALLDATETIME =206,
//Binary
VT_SS_BINARY =207,
VT_SS_VARBINARY = 208,
//Future
VT_SS_UNKNOWN = 209,
//Additional datetime
VT_SS_DATE = DBTYPE_DBDATE,
VT_SS_TIME2 = DBTYPE_DBTIME2,
VT_SS_DATETIME2 = 212,
VT_SS_DATETIMEOFFSET = DBTYPE_DBTIMESTAMPOFFSET,
};
typedef unsigned short SSVARTYPE;
enum DBPARAMFLAGSENUM_SS_100
{ DBPARAMFLAGS_SS_ISVARIABLESCALE = 0x40000000
} ;
enum DBCOLUMNFLAGSENUM_SS_100
{ DBCOLUMNFLAGS_SS_ISVARIABLESCALE = 0x40000000,
DBCOLUMNFLAGS_SS_ISCOLUMNSET = 0x80000000
} ;
//-------------------------------------------------------------------
// Class Factory Interface used to initialize pointer to UMS.
//-------------------------------------------------------------------
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0001_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0001_v0_0_s_ifspec;
#ifndef __IUMSInitialize_INTERFACE_DEFINED__
#define __IUMSInitialize_INTERFACE_DEFINED__
/* interface IUMSInitialize */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_IUMSInitialize;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5cf4ca14-ef21-11d0-97e7-00c04fc2ad98")
IUMSInitialize : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE Initialize(
/* [in] */ void *pUMS) = 0;
};
#else /* C style interface */
typedef struct IUMSInitializeVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUMSInitialize * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IUMSInitialize * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IUMSInitialize * This);
HRESULT ( STDMETHODCALLTYPE *Initialize )(
IUMSInitialize * This,
/* [in] */ void *pUMS);
END_INTERFACE
} IUMSInitializeVtbl;
interface IUMSInitialize
{
CONST_VTBL struct IUMSInitializeVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IUMSInitialize_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IUMSInitialize_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IUMSInitialize_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IUMSInitialize_Initialize(This,pUMS) \
( (This)->lpVtbl -> Initialize(This,pUMS) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __IUMSInitialize_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0002 */
/* [local] */
// the structure returned by ISQLServerErrorInfo::GetSQLServerInfo
typedef struct tagSSErrorInfo
{
LPOLESTR pwszMessage;
LPOLESTR pwszServer;
LPOLESTR pwszProcedure;
LONG lNative;
BYTE bState;
BYTE bClass;
WORD wLineNumber;
} SSERRORINFO;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0002_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0002_v0_0_s_ifspec;
#ifndef __ISQLServerErrorInfo_INTERFACE_DEFINED__
#define __ISQLServerErrorInfo_INTERFACE_DEFINED__
/* interface ISQLServerErrorInfo */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISQLServerErrorInfo;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5CF4CA12-EF21-11d0-97E7-00C04FC2AD98")
ISQLServerErrorInfo : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetErrorInfo(
/* [out] */ SSERRORINFO **ppErrorInfo,
/* [out] */ OLECHAR **ppStringsBuffer) = 0;
};
#else /* C style interface */
typedef struct ISQLServerErrorInfoVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISQLServerErrorInfo * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISQLServerErrorInfo * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISQLServerErrorInfo * This);
HRESULT ( STDMETHODCALLTYPE *GetErrorInfo )(
ISQLServerErrorInfo * This,
/* [out] */ SSERRORINFO **ppErrorInfo,
/* [out] */ OLECHAR **ppStringsBuffer);
END_INTERFACE
} ISQLServerErrorInfoVtbl;
interface ISQLServerErrorInfo
{
CONST_VTBL struct ISQLServerErrorInfoVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISQLServerErrorInfo_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISQLServerErrorInfo_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISQLServerErrorInfo_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISQLServerErrorInfo_GetErrorInfo(This,ppErrorInfo,ppStringsBuffer) \
( (This)->lpVtbl -> GetErrorInfo(This,ppErrorInfo,ppStringsBuffer) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISQLServerErrorInfo_INTERFACE_DEFINED__ */
#ifndef __IRowsetFastLoad_INTERFACE_DEFINED__
#define __IRowsetFastLoad_INTERFACE_DEFINED__
/* interface IRowsetFastLoad */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_IRowsetFastLoad;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5CF4CA13-EF21-11d0-97E7-00C04FC2AD98")
IRowsetFastLoad : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE InsertRow(
/* [in] */ HACCESSOR hAccessor,
/* [in] */ void *pData) = 0;
virtual HRESULT STDMETHODCALLTYPE Commit(
/* [in] */ BOOL fDone) = 0;
};
#else /* C style interface */
typedef struct IRowsetFastLoadVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IRowsetFastLoad * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IRowsetFastLoad * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IRowsetFastLoad * This);
HRESULT ( STDMETHODCALLTYPE *InsertRow )(
IRowsetFastLoad * This,
/* [in] */ HACCESSOR hAccessor,
/* [in] */ void *pData);
HRESULT ( STDMETHODCALLTYPE *Commit )(
IRowsetFastLoad * This,
/* [in] */ BOOL fDone);
END_INTERFACE
} IRowsetFastLoadVtbl;
interface IRowsetFastLoad
{
CONST_VTBL struct IRowsetFastLoadVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IRowsetFastLoad_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IRowsetFastLoad_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IRowsetFastLoad_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IRowsetFastLoad_InsertRow(This,hAccessor,pData) \
( (This)->lpVtbl -> InsertRow(This,hAccessor,pData) )
#define IRowsetFastLoad_Commit(This,fDone) \
( (This)->lpVtbl -> Commit(This,fDone) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __IRowsetFastLoad_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0004 */
/* [local] */
#include <pshpack8.h> // 8-byte structure packing
typedef struct tagDBTIME2
{
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
} DBTIME2;
typedef struct tagDBTIMESTAMPOFFSET
{
SHORT year;
USHORT month;
USHORT day;
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
SHORT timezone_hour;
SHORT timezone_minute;
} DBTIMESTAMPOFFSET;
#include <poppack.h> // restore original structure packing
struct SSVARIANT
{
SSVARTYPE vt;
DWORD dwReserved1;
DWORD dwReserved2;
union
{
BYTE bTinyIntVal;
SHORT sShortIntVal;
LONG lIntVal;
LONGLONG llBigIntVal;
FLOAT fltRealVal;
DOUBLE dblFloatVal;
CY cyMoneyVal;
VARIANT_BOOL fBitVal;
BYTE rgbGuidVal[ 16 ];
DB_NUMERIC numNumericVal;
DBDATE dDateVal;
DBTIMESTAMP tsDateTimeVal;
struct _Time2Val
{
DBTIME2 tTime2Val;
BYTE bScale;
} Time2Val;
struct _DateTimeVal
{
DBTIMESTAMP tsDateTimeVal;
BYTE bScale;
} DateTimeVal;
struct _DateTimeOffsetVal
{
DBTIMESTAMPOFFSET tsoDateTimeOffsetVal;
BYTE bScale;
} DateTimeOffsetVal;
struct _NCharVal
{
SHORT sActualLength;
SHORT sMaxLength;
WCHAR *pwchNCharVal;
BYTE rgbReserved[ 5 ];
DWORD dwReserved;
WCHAR *pwchReserved;
} NCharVal;
struct _CharVal
{
SHORT sActualLength;
SHORT sMaxLength;
CHAR *pchCharVal;
BYTE rgbReserved[ 5 ];
DWORD dwReserved;
WCHAR *pwchReserved;
} CharVal;
struct _BinaryVal
{
SHORT sActualLength;
SHORT sMaxLength;
BYTE *prgbBinaryVal;
DWORD dwReserved;
} BinaryVal;
struct _UnknownType
{
DWORD dwActualLength;
BYTE rgMetadata[ 16 ];
BYTE *pUnknownData;
} UnknownType;
struct _BLOBType
{
DBOBJECT dbobj;
IUnknown *pUnk;
} BLOBType;
} ;
} ;
typedef DWORD LOCKMODE;
enum LOCKMODEENUM
{ LOCKMODE_INVALID = 0,
LOCKMODE_EXCLUSIVE = ( LOCKMODE_INVALID + 1 ) ,
LOCKMODE_SHARED = ( LOCKMODE_EXCLUSIVE + 1 )
} ;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0004_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0004_v0_0_s_ifspec;
#ifndef __ISchemaLock_INTERFACE_DEFINED__
#define __ISchemaLock_INTERFACE_DEFINED__
/* interface ISchemaLock */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISchemaLock;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("4C2389FB-2511-11d4-B258-00C04F7971CE")
ISchemaLock : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetSchemaLock(
/* [in] */ DBID *pTableID,
/* [in] */ LOCKMODE lmMode,
/* [out] */ HANDLE *phLockHandle,
/* [out] */ ULONGLONG *pTableVersion) = 0;
virtual HRESULT STDMETHODCALLTYPE ReleaseSchemaLock(
/* [in] */ HANDLE hLockHandle) = 0;
};
#else /* C style interface */
typedef struct ISchemaLockVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISchemaLock * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISchemaLock * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISchemaLock * This);
HRESULT ( STDMETHODCALLTYPE *GetSchemaLock )(
ISchemaLock * This,
/* [in] */ DBID *pTableID,
/* [in] */ LOCKMODE lmMode,
/* [out] */ HANDLE *phLockHandle,
/* [out] */ ULONGLONG *pTableVersion);
HRESULT ( STDMETHODCALLTYPE *ReleaseSchemaLock )(
ISchemaLock * This,
/* [in] */ HANDLE hLockHandle);
END_INTERFACE
} ISchemaLockVtbl;
interface ISchemaLock
{
CONST_VTBL struct ISchemaLockVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISchemaLock_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISchemaLock_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISchemaLock_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISchemaLock_GetSchemaLock(This,pTableID,lmMode,phLockHandle,pTableVersion) \
( (This)->lpVtbl -> GetSchemaLock(This,pTableID,lmMode,phLockHandle,pTableVersion) )
#define ISchemaLock_ReleaseSchemaLock(This,hLockHandle) \
( (This)->lpVtbl -> ReleaseSchemaLock(This,hLockHandle) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISchemaLock_INTERFACE_DEFINED__ */
#ifndef __IBCPSession_INTERFACE_DEFINED__
#define __IBCPSession_INTERFACE_DEFINED__
/* interface IBCPSession */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_IBCPSession;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("88352D80-42D1-42f0-A170-AB0F8B45B939")
IBCPSession : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE BCPColFmt(
/* [in] */ DBORDINAL idxUserDataCol,
/* [in] */ int eUserDataType,
/* [in] */ int cbIndicator,
/* [in] */ int cbUserData,
/* [size_is][in] */ BYTE *pbUserDataTerm,
/* [in] */ int cbUserDataTerm,
/* [in] */ DBORDINAL idxServerCol) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPColumns(
/* [in] */ DBCOUNTITEM nColumns) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPControl(
/* [in] */ int eOption,
/* [in] */ void *iValue) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPDone( void) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPExec(
/* [out] */ DBROWCOUNT *pRowsCopied) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPInit(
/* [string][in] */ const wchar_t *pwszTable,
/* [string][in] */ const wchar_t *pwszDataFile,
/* [string][in] */ const wchar_t *pwszErrorFile,
/* [in] */ int eDirection) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPReadFmt(
/* [string][in] */ const wchar_t *pwszFormatFile) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPWriteFmt(
/* [string][in] */ const wchar_t *pwszFormatFile) = 0;
};
#else /* C style interface */
typedef struct IBCPSessionVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IBCPSession * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IBCPSession * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IBCPSession * This);
HRESULT ( STDMETHODCALLTYPE *BCPColFmt )(
IBCPSession * This,
/* [in] */ DBORDINAL idxUserDataCol,
/* [in] */ int eUserDataType,
/* [in] */ int cbIndicator,
/* [in] */ int cbUserData,
/* [size_is][in] */ BYTE *pbUserDataTerm,
/* [in] */ int cbUserDataTerm,
/* [in] */ DBORDINAL idxServerCol);
HRESULT ( STDMETHODCALLTYPE *BCPColumns )(
IBCPSession * This,
/* [in] */ DBCOUNTITEM nColumns);
HRESULT ( STDMETHODCALLTYPE *BCPControl )(
IBCPSession * This,
/* [in] */ int eOption,
/* [in] */ void *iValue);
HRESULT ( STDMETHODCALLTYPE *BCPDone )(
IBCPSession * This);
HRESULT ( STDMETHODCALLTYPE *BCPExec )(
IBCPSession * This,
/* [out] */ DBROWCOUNT *pRowsCopied);
HRESULT ( STDMETHODCALLTYPE *BCPInit )(
IBCPSession * This,
/* [string][in] */ const wchar_t *pwszTable,
/* [string][in] */ const wchar_t *pwszDataFile,
/* [string][in] */ const wchar_t *pwszErrorFile,
/* [in] */ int eDirection);
HRESULT ( STDMETHODCALLTYPE *BCPReadFmt )(
IBCPSession * This,
/* [string][in] */ const wchar_t *pwszFormatFile);
HRESULT ( STDMETHODCALLTYPE *BCPWriteFmt )(
IBCPSession * This,
/* [string][in] */ const wchar_t *pwszFormatFile);
END_INTERFACE
} IBCPSessionVtbl;
interface IBCPSession
{
CONST_VTBL struct IBCPSessionVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IBCPSession_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IBCPSession_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IBCPSession_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IBCPSession_BCPColFmt(This,idxUserDataCol,eUserDataType,cbIndicator,cbUserData,pbUserDataTerm,cbUserDataTerm,idxServerCol) \
( (This)->lpVtbl -> BCPColFmt(This,idxUserDataCol,eUserDataType,cbIndicator,cbUserData,pbUserDataTerm,cbUserDataTerm,idxServerCol) )
#define IBCPSession_BCPColumns(This,nColumns) \
( (This)->lpVtbl -> BCPColumns(This,nColumns) )
#define IBCPSession_BCPControl(This,eOption,iValue) \
( (This)->lpVtbl -> BCPControl(This,eOption,iValue) )
#define IBCPSession_BCPDone(This) \
( (This)->lpVtbl -> BCPDone(This) )
#define IBCPSession_BCPExec(This,pRowsCopied) \
( (This)->lpVtbl -> BCPExec(This,pRowsCopied) )
#define IBCPSession_BCPInit(This,pwszTable,pwszDataFile,pwszErrorFile,eDirection) \
( (This)->lpVtbl -> BCPInit(This,pwszTable,pwszDataFile,pwszErrorFile,eDirection) )
#define IBCPSession_BCPReadFmt(This,pwszFormatFile) \
( (This)->lpVtbl -> BCPReadFmt(This,pwszFormatFile) )
#define IBCPSession_BCPWriteFmt(This,pwszFormatFile) \
( (This)->lpVtbl -> BCPWriteFmt(This,pwszFormatFile) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __IBCPSession_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0006 */
/* [local] */
#endif //_SQLOLEDB_H_
#define ISOLATIONLEVEL_SNAPSHOT ((ISOLATIONLEVEL)(0x01000000)) // Changes made in other transactions can not be seen.
#define DBPROPVAL_TI_SNAPSHOT 0x01000000L
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0006_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0006_v0_0_s_ifspec;
#ifndef __ISSAbort_INTERFACE_DEFINED__
#define __ISSAbort_INTERFACE_DEFINED__
/* interface ISSAbort */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISSAbort;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5CF4CA15-EF21-11d0-97E7-00C04FC2AD98")
ISSAbort : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0;
};
#else /* C style interface */
typedef struct ISSAbortVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISSAbort * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISSAbort * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISSAbort * This);
HRESULT ( STDMETHODCALLTYPE *Abort )(
ISSAbort * This);
END_INTERFACE
} ISSAbortVtbl;
interface ISSAbort
{
CONST_VTBL struct ISSAbortVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISSAbort_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISSAbort_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISSAbort_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISSAbort_Abort(This) \
( (This)->lpVtbl -> Abort(This) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISSAbort_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0007 */
/* [local] */
enum DBBINDFLAGENUM90
{ DBBINDFLAG_OBJECT = 0x2
} ;
enum SSACCESSORFLAGS
{ SSACCESSOR_ROWDATA = 0x100
} ;
enum DBPROPFLAGSENUM90
{ DBPROPFLAGS_PARAMETER = 0x10000
} ;
typedef struct tagSSPARAMPROPS
{
DBORDINAL iOrdinal;
ULONG cPropertySets;
DBPROPSET *rgPropertySets;
} SSPARAMPROPS;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0007_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0007_v0_0_s_ifspec;
#ifndef __ISSCommandWithParameters_INTERFACE_DEFINED__
#define __ISSCommandWithParameters_INTERFACE_DEFINED__
/* interface ISSCommandWithParameters */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISSCommandWithParameters;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("eec30162-6087-467c-b995-7c523ce96561")
ISSCommandWithParameters : public ICommandWithParameters
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetParameterProperties(
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ SSPARAMPROPS **prgParamProperties) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE SetParameterProperties(
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ SSPARAMPROPS rgParamProperties[ ]) = 0;
};
#else /* C style interface */
typedef struct ISSCommandWithParametersVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISSCommandWithParameters * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISSCommandWithParameters * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISSCommandWithParameters * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetParameterInfo )(
ISSCommandWithParameters * This,
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ DBPARAMINFO **prgParamInfo,
/* [out] */ OLECHAR **ppNamesBuffer);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *MapParameterNames )(
ISSCommandWithParameters * This,
/* [in] */ DB_UPARAMS cParamNames,
/* [size_is][in] */ const OLECHAR *rgParamNames[ ],
/* [size_is][out] */ DB_LPARAMS rgParamOrdinals[ ]);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetParameterInfo )(
ISSCommandWithParameters * This,
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ const DB_UPARAMS rgParamOrdinals[ ],
/* [size_is][unique][in] */ const DBPARAMBINDINFO rgParamBindInfo[ ]);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetParameterProperties )(
ISSCommandWithParameters * This,
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ SSPARAMPROPS **prgParamProperties);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetParameterProperties )(
ISSCommandWithParameters * This,
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ SSPARAMPROPS rgParamProperties[ ]);
END_INTERFACE
} ISSCommandWithParametersVtbl;
interface ISSCommandWithParameters
{
CONST_VTBL struct ISSCommandWithParametersVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISSCommandWithParameters_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISSCommandWithParameters_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISSCommandWithParameters_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISSCommandWithParameters_GetParameterInfo(This,pcParams,prgParamInfo,ppNamesBuffer) \
( (This)->lpVtbl -> GetParameterInfo(This,pcParams,prgParamInfo,ppNamesBuffer) )
#define ISSCommandWithParameters_MapParameterNames(This,cParamNames,rgParamNames,rgParamOrdinals) \
( (This)->lpVtbl -> MapParameterNames(This,cParamNames,rgParamNames,rgParamOrdinals) )
#define ISSCommandWithParameters_SetParameterInfo(This,cParams,rgParamOrdinals,rgParamBindInfo) \
( (This)->lpVtbl -> SetParameterInfo(This,cParams,rgParamOrdinals,rgParamBindInfo) )
#define ISSCommandWithParameters_GetParameterProperties(This,pcParams,prgParamProperties) \
( (This)->lpVtbl -> GetParameterProperties(This,pcParams,prgParamProperties) )
#define ISSCommandWithParameters_SetParameterProperties(This,cParams,rgParamProperties) \
( (This)->lpVtbl -> SetParameterProperties(This,cParams,rgParamProperties) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISSCommandWithParameters_INTERFACE_DEFINED__ */
#ifndef __IDBAsynchStatus_INTERFACE_DEFINED__
#define __IDBAsynchStatus_INTERFACE_DEFINED__
/* interface IDBAsynchStatus */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_IDBAsynchStatus;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("0c733a95-2a1c-11ce-ade5-00aa0044773d")
IDBAsynchStatus : public IUnknown
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Abort(
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetStatus(
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [out] */ DBCOUNTITEM *pulProgress,
/* [out] */ DBCOUNTITEM *pulProgressMax,
/* [out] */ DBASYNCHPHASE *peAsynchPhase,
/* [out] */ LPOLESTR *ppwszStatusText) = 0;
};
#else /* C style interface */
typedef struct IDBAsynchStatusVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IDBAsynchStatus * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IDBAsynchStatus * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IDBAsynchStatus * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Abort )(
IDBAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetStatus )(
IDBAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [out] */ DBCOUNTITEM *pulProgress,
/* [out] */ DBCOUNTITEM *pulProgressMax,
/* [out] */ DBASYNCHPHASE *peAsynchPhase,
/* [out] */ LPOLESTR *ppwszStatusText);
END_INTERFACE
} IDBAsynchStatusVtbl;
interface IDBAsynchStatus
{
CONST_VTBL struct IDBAsynchStatusVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IDBAsynchStatus_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IDBAsynchStatus_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IDBAsynchStatus_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IDBAsynchStatus_Abort(This,hChapter,eOperation) \
( (This)->lpVtbl -> Abort(This,hChapter,eOperation) )
#define IDBAsynchStatus_GetStatus(This,hChapter,eOperation,pulProgress,pulProgressMax,peAsynchPhase,ppwszStatusText) \
( (This)->lpVtbl -> GetStatus(This,hChapter,eOperation,pulProgress,pulProgressMax,peAsynchPhase,ppwszStatusText) )
#endif /* COBJMACROS */
#endif /* C style interface */
/* [call_as] */ HRESULT STDMETHODCALLTYPE IDBAsynchStatus_RemoteAbort_Proxy(
IDBAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB IDBAsynchStatus_RemoteAbort_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
/* [call_as] */ HRESULT STDMETHODCALLTYPE IDBAsynchStatus_RemoteGetStatus_Proxy(
IDBAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [unique][out][in] */ DBCOUNTITEM *pulProgress,
/* [unique][out][in] */ DBCOUNTITEM *pulProgressMax,
/* [unique][out][in] */ DBASYNCHPHASE *peAsynchPhase,
/* [unique][out][in] */ LPOLESTR *ppwszStatusText,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB IDBAsynchStatus_RemoteGetStatus_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __IDBAsynchStatus_INTERFACE_DEFINED__ */
#ifndef __ISSAsynchStatus_INTERFACE_DEFINED__
#define __ISSAsynchStatus_INTERFACE_DEFINED__
/* interface ISSAsynchStatus */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISSAsynchStatus;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("1FF1F743-8BB0-4c00-ACC4-C10E43B08FC1")
ISSAsynchStatus : public IDBAsynchStatus
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE WaitForAsynchCompletion(
/* [in] */ DWORD dwMillisecTimeOut) = 0;
};
#else /* C style interface */
typedef struct ISSAsynchStatusVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISSAsynchStatus * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISSAsynchStatus * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISSAsynchStatus * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Abort )(
ISSAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetStatus )(
ISSAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [out] */ DBCOUNTITEM *pulProgress,
/* [out] */ DBCOUNTITEM *pulProgressMax,
/* [out] */ DBASYNCHPHASE *peAsynchPhase,
/* [out] */ LPOLESTR *ppwszStatusText);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *WaitForAsynchCompletion )(
ISSAsynchStatus * This,
/* [in] */ DWORD dwMillisecTimeOut);
END_INTERFACE
} ISSAsynchStatusVtbl;
interface ISSAsynchStatus
{
CONST_VTBL struct ISSAsynchStatusVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISSAsynchStatus_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISSAsynchStatus_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISSAsynchStatus_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISSAsynchStatus_Abort(This,hChapter,eOperation) \
( (This)->lpVtbl -> Abort(This,hChapter,eOperation) )
#define ISSAsynchStatus_GetStatus(This,hChapter,eOperation,pulProgress,pulProgressMax,peAsynchPhase,ppwszStatusText) \
( (This)->lpVtbl -> GetStatus(This,hChapter,eOperation,pulProgress,pulProgressMax,peAsynchPhase,ppwszStatusText) )
#define ISSAsynchStatus_WaitForAsynchCompletion(This,dwMillisecTimeOut) \
( (This)->lpVtbl -> WaitForAsynchCompletion(This,dwMillisecTimeOut) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISSAsynchStatus_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0010 */
/* [local] */
//----------------------------------------------------------------------------
// Values for STATUS bitmask for DBSCHEMA_TABLES & DBSCHEMA_TABLES_INFO
#define TABLE_HAS_UPDATE_INSTEAD_OF_TRIGGER 0x00000001 //table has IOT defined
#define TABLE_HAS_DELETE_INSTEAD_OF_TRIGGER 0x00000002 //table has IOT defined
#define TABLE_HAS_INSERT_INSTEAD_OF_TRIGGER 0x00000004 //table has IOT defined
#define TABLE_HAS_AFTER_UPDATE_TRIGGER 0x00000008 //table has update trigger
#define TABLE_HAS_AFTER_DELETE_TRIGGER 0x00000010 //table has delete trigger
#define TABLE_HAS_AFTER_INSERT_TRIGGER 0x00000020 //table has insert trigger
#define TABLE_HAS_CASCADE_UPDATE 0x00000040 //table has cascade update
#define TABLE_HAS_CASCADE_DELETE 0x00000080 //table has cascade delete
//----------------------------------------------------------------------------
// PropIds for DBPROP_INIT_GENERALTIMEOUT
#if (OLEDBVER >= 0x0210)
#define DBPROP_INIT_GENERALTIMEOUT 0x11cL
#endif
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERDATASOURCE
#define SSPROP_ENABLEFASTLOAD 2
#define SSPROP_ENABLEBULKCOPY 3
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERDATASOURCEINFO
#define SSPROP_UNICODELCID 2
#define SSPROP_UNICODECOMPARISONSTYLE 3
#define SSPROP_COLUMNLEVELCOLLATION 4
#define SSPROP_CHARACTERSET 5
#define SSPROP_SORTORDER 6
#define SSPROP_CURRENTCOLLATION 7
#define SSPROP_INTEGRATEDAUTHENTICATIONMETHOD 8
#define SSPROP_MUTUALLYAUTHENTICATED 9
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERDBINIT
#define SSPROP_INIT_CURRENTLANGUAGE 4
#define SSPROP_INIT_NETWORKADDRESS 5
#define SSPROP_INIT_NETWORKLIBRARY 6
#define SSPROP_INIT_USEPROCFORPREP 7
#define SSPROP_INIT_AUTOTRANSLATE 8
#define SSPROP_INIT_PACKETSIZE 9
#define SSPROP_INIT_APPNAME 10
#define SSPROP_INIT_WSID 11
#define SSPROP_INIT_FILENAME 12
#define SSPROP_INIT_ENCRYPT 13
#define SSPROP_AUTH_REPL_SERVER_NAME 14
#define SSPROP_INIT_TAGCOLUMNCOLLATION 15
#define SSPROP_INIT_MARSCONNECTION 16
#define SSPROP_INIT_FAILOVERPARTNER 18
#define SSPROP_AUTH_OLD_PASSWORD 19
#define SSPROP_INIT_DATATYPECOMPATIBILITY 20
#define SSPROP_INIT_TRUST_SERVER_CERTIFICATE 21
#define SSPROP_INIT_SERVERSPN 22
#define SSPROP_INIT_FAILOVERPARTNERSPN 23
//-----------------------------------------------------------------------------
// Values for SSPROP_INIT_USEPROCFORPREP
#define SSPROPVAL_USEPROCFORPREP_OFF 0
#define SSPROPVAL_USEPROCFORPREP_ON 1
#define SSPROPVAL_USEPROCFORPREP_ON_DROP 2
//-----------------------------------------------------------------------------
// Values for SSPROP_INIT_DATATYPECOMPATIBILITY
#define SSPROPVAL_DATATYPECOMPATIBILITY_SQL2000 80
#define SSPROPVAL_DATATYPECOMPATIBILITY_DEFAULT 0
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERSESSION
#define SSPROP_QUOTEDCATALOGNAMES 2
#define SSPROP_ALLOWNATIVEVARIANT 3
#define SSPROP_SQLXMLXPROGID 4
#define SSPROP_ASYNCH_BULKCOPY 5
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERROWSET
#define SSPROP_MAXBLOBLENGTH 8
#define SSPROP_FASTLOADOPTIONS 9
#define SSPROP_FASTLOADKEEPNULLS 10
#define SSPROP_FASTLOADKEEPIDENTITY 11
#define SSPROP_CURSORAUTOFETCH 12
#define SSPROP_DEFERPREPARE 13
#define SSPROP_IRowsetFastLoad 14
#define SSPROP_QP_NOTIFICATION_TIMEOUT 17
#define SSPROP_QP_NOTIFICATION_MSGTEXT 18
#define SSPROP_QP_NOTIFICATION_OPTIONS 19
#define SSPROP_NOCOUNT_STATUS 20
#define SSPROP_COMPUTE_ID 21
#define SSPROP_COLUMN_ID 22
#define SSPROP_COMPUTE_BYLIST 23
#define SSPROP_ISSAsynchStatus 24
//-----------------------------------------------------------------------------
// Values for SSPROP_QP_NOTIFICATION_TIMEOUT
#define SSPROPVAL_DEFAULT_NOTIFICATION_TIMEOUT 432000 /* in sec */
#define SSPROPVAL_MAX_NOTIFICATION_TIMEOUT 0x7FFFFFFF /* in sec */
#define MAX_NOTIFICATION_LEN 2000 /* NVARCHAR [2000] for both ID & DELIVERY_QUEUE */
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERCOLUMN
#define SSPROP_COL_COLLATIONNAME 14
#define SSPROP_COL_UDT_CATALOGNAME 31
#define SSPROP_COL_UDT_SCHEMANAME 32
#define SSPROP_COL_UDT_NAME 33
#define SSPROP_COL_XML_SCHEMACOLLECTION_CATALOGNAME 34
#define SSPROP_COL_XML_SCHEMACOLLECTION_SCHEMANAME 35
#define SSPROP_COL_XML_SCHEMACOLLECTIONNAME 36
#define SSPROP_COL_COMPUTED 37
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERSTREAM
#define SSPROP_STREAM_XMLROOT 19
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERPARAMETER
#define SSPROP_PARAM_XML_SCHEMACOLLECTION_CATALOGNAME 24
#define SSPROP_PARAM_XML_SCHEMACOLLECTION_SCHEMANAME 25
#define SSPROP_PARAM_XML_SCHEMACOLLECTIONNAME 26
#define SSPROP_PARAM_UDT_CATALOGNAME 27
#define SSPROP_PARAM_UDT_SCHEMANAME 28
#define SSPROP_PARAM_UDT_NAME 29
#define SSPROP_PARAM_TYPE_CATALOGNAME 38
#define SSPROP_PARAM_TYPE_SCHEMANAME 39
#define SSPROP_PARAM_TYPE_TYPENAME 40
#define SSPROP_PARAM_TABLE_DEFAULT_COLUMNS 41
#define SSPROP_PARAM_TABLE_COLUMN_SORT_ORDER 42
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERINDEX
#define SSPROP_INDEX_XML 1
//-----------------------------------------------------------------------------
//
#define BCP_TYPE_DEFAULT 0x00
#define BCP_TYPE_SQLTEXT 0x23
#define BCP_TYPE_SQLVARBINARY 0x25
#define BCP_TYPE_SQLINTN 0x26
#define BCP_TYPE_SQLVARCHAR 0x27
#define BCP_TYPE_SQLBINARY 0x2d
#define BCP_TYPE_SQLIMAGE 0x22
#define BCP_TYPE_SQLCHARACTER 0x2f
#define BCP_TYPE_SQLINT1 0x30
#define BCP_TYPE_SQLBIT 0x32
#define BCP_TYPE_SQLINT2 0x34
#define BCP_TYPE_SQLINT4 0x38
#define BCP_TYPE_SQLMONEY 0x3c
#define BCP_TYPE_SQLDATETIME 0x3d
#define BCP_TYPE_SQLFLT8 0x3e
#define BCP_TYPE_SQLFLTN 0x6d
#define BCP_TYPE_SQLMONEYN 0x6e
#define BCP_TYPE_SQLDATETIMN 0x6f
#define BCP_TYPE_SQLFLT4 0x3b
#define BCP_TYPE_SQLMONEY4 0x7a
#define BCP_TYPE_SQLDATETIM4 0x3a
#define BCP_TYPE_SQLDECIMAL 0x6a
#define BCP_TYPE_SQLNUMERIC 0x6c
#define BCP_TYPE_SQLUNIQUEID 0x24
#define BCP_TYPE_SQLBIGCHAR 0xaf
#define BCP_TYPE_SQLBIGVARCHAR 0xa7
#define BCP_TYPE_SQLBIGBINARY 0xad
#define BCP_TYPE_SQLBIGVARBINARY 0xa5
#define BCP_TYPE_SQLBITN 0x68
#define BCP_TYPE_SQLNCHAR 0xef
#define BCP_TYPE_SQLNVARCHAR 0xe7
#define BCP_TYPE_SQLNTEXT 0x63
#define BCP_TYPE_SQLDECIMALN 0x6a
#define BCP_TYPE_SQLNUMERICN 0x6c
#define BCP_TYPE_SQLINT8 0x7f
#define BCP_TYPE_SQLVARIANT 0x62
#define BCP_TYPE_SQLUDT 0xf0
#define BCP_TYPE_SQLXML 0xf1
#define BCP_TYPE_SQLDATE 0x28
#define BCP_TYPE_SQLTIME 0x29
#define BCP_TYPE_SQLDATETIME2 0x2a
#define BCP_TYPE_SQLDATETIMEOFFSET 0x2b
#define BCP_DIRECTION_IN 1
#define BCP_DIRECTION_OUT 2
#define BCP_OPTION_MAXERRS 1
#define BCP_OPTION_FIRST 2
#define BCP_OPTION_LAST 3
#define BCP_OPTION_BATCH 4
#define BCP_OPTION_KEEPNULLS 5
#define BCP_OPTION_ABORT 6
#define BCP_OPTION_KEEPIDENTITY 8
#define BCP_OPTION_HINTSA 10
#define BCP_OPTION_HINTSW 11
#define BCP_OPTION_FILECP 12
#define BCP_OPTION_UNICODEFILE 13
#define BCP_OPTION_TEXTFILE 14
#define BCP_OPTION_FILEFMT 15
#define BCP_OPTION_FMTXML 16
#define BCP_OPTION_FIRSTEX 17
#define BCP_OPTION_LASTEX 18
#define BCP_OPTION_ROWCOUNT 19
#define BCP_FILECP_ACP 0
#define BCP_FILECP_OEMCP 1
#define BCP_FILECP_RAW (-1)
#ifdef UNICODE
#define BCP_OPTION_HINTS BCP_OPTION_HINTSW
#else
#define BCP_OPTION_HINTS BCP_OPTION_HINTSA
#endif
#define BCP_PREFIX_DEFAULT (-10)
#define BCP_LENGTH_NULL (-1)
#define BCP_LENGTH_VARIABLE (-10)
//
//-----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Provider-specific Class Ids
//
#if SQLNCLI_VER >= 1000
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI10 = {0x8F4A6B68L,0x4F36,0x4e3c,{0xBE,0x81,0xBC,0x7C,0xA4,0xE9,0xC4,0x5C}};
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI10_ERROR = {0x53F9C3BCL,0x275F,0x4FA5,{0xB3,0xE6,0x25,0xED,0xCD,0x51,0x20,0x23}};
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI10_ENUMERATOR = {0x91E4F2A5L,0x1B07,0x45f6,{0x86,0xBF,0x92,0x03,0xC7,0xC7,0x2B,0xE3}};
#endif
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI = {0x85ecafccL,0xbdd9,0x4b03,{0x97,0xa8,0xfa,0x65,0xcb,0xe3,0x85,0x9b}};
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI_ERROR = {0xe8bc0a7aL,0xea71,0x4263,{0x8c,0xda,0x94,0xf3,0x88,0xb8,0xed,0x10}};
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI_ENUMERATOR = {0x4898ad37L,0xfe05,0x42df,{0x92,0xf9,0xe8,0x57,0xdd,0xfe,0xe7,0x30}};
extern const GUID OLEDBDECLSPEC CLSID_ROWSET_TVP = {0xc7ef28d5L,0x7bee,0x443f,{0x86,0xda,0xe3,0x98,0x4f,0xcd,0x4d,0xf9}};
//----------------------------------------------------------------------------
// Provider-specific Interface Ids
//
#ifndef _SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC IID_ISQLServerErrorInfo = {0x5cf4ca12,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC IID_IRowsetFastLoad = {0x5cf4ca13,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC IID_IUMSInitialize = {0x5cf4ca14,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC IID_ISchemaLock = {0x4c2389fb,0x2511,0x11d4,{0xb2,0x58,0x0,0xc0,0x4f,0x79,0x71,0xce}};
extern const GUID OLEDBDECLSPEC IID_ISQLXMLHelper = {0xd22a7678L,0xf860,0x40cd,{0xa5,0x67,0x15,0x63,0xde,0xb4,0x6d,0x49}};
#endif //_SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC IID_ISSAbort = {0x5cf4ca15,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC IID_IBCPSession = {0x88352D80,0x42D1,0x42f0,{0xA1,0x70,0xAB,0x0F,0x8B,0x45,0xB9,0x39}};
extern const GUID OLEDBDECLSPEC IID_ISSCommandWithParameters = {0xeec30162,0x6087,0x467c,{0xb9,0x95,0x7c,0x52,0x3c,0xe9,0x65,0x61}};
extern const GUID OLEDBDECLSPEC IID_ISSAsynchStatus = {0x1FF1F743,0x8BB0, 0x4c00,{0xAC,0xC4,0xC1,0x0E,0x43,0xB0,0x8F,0xC1}};
//----------------------------------------------------------------------------
// Provider-specific schema rowsets
//
#ifndef _SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC DBSCHEMA_LINKEDSERVERS = {0x9093caf4,0x2eac,0x11d1,{0x98,0x9,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
#endif //_SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_ASSEMBLIES = {0x7c1112c8, 0xc2d3, 0x4f6e, {0x94, 0x9a, 0x98, 0x3d, 0x38, 0xa5, 0x8f, 0x46}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_ASSEMBLY_DEPENDENCIES = {0xcb0f837b, 0x974c, 0x41b8, {0x90, 0x9d, 0x64, 0x9c, 0xaf, 0x45, 0xad, 0x2f}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_USER_TYPES = {0xf1198bd8, 0xa424, 0x4ea3, {0x8d, 0x4c, 0x60, 0x7e, 0xee, 0x2b, 0xab, 0x60}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_XML_COLLECTIONS = {0x56bfad8c, 0x6e8f, 0x480d, {0x91, 0xde, 0x35, 0x16, 0xd9, 0x9a, 0x5d, 0x10}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_TABLE_TYPES = {0x4e26cde7, 0xaaa4, 0x41ed, {0x93, 0xdd, 0x37, 0x6e, 0x6d, 0x40, 0x9c, 0x17}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_TABLE_TYPE_PRIMARY_KEYS = {0x9738faea, 0x31e8, 0x4f63, {0xae, 0xd, 0x61, 0x33, 0x16, 0x41, 0x8c, 0xdd}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_TABLE_TYPE_COLUMNS = {0xa663d94b, 0xddf7, 0x4a7f, {0xa5, 0x37, 0xd6, 0x1f, 0x12, 0x36, 0x5d, 0x7c}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_COLUMNS_EXTENDED = {0x66462f01, 0x633a, 0x44d9, {0xb0, 0xd0, 0xfe, 0x66, 0xf2, 0x1a, 0x0d, 0x24}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SPARSE_COLUMN_SET = {0x31a4837c, 0xf9ff, 0x405f, {0x89, 0x82, 0x02, 0x19, 0xaa, 0xaa, 0x4a, 0x12}};
#ifndef CRESTRICTIONS_DBSCHEMA_LINKEDSERVERS
#define CRESTRICTIONS_DBSCHEMA_LINKEDSERVERS 1
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_ASSEMBLIES
#define CRESTRICTIONS_DBSCHEMA_SQL_ASSEMBLIES 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_ASSEMBLY_DEPENDENCIES
#define CRESTRICTIONS_DBSCHEMA_SQL_ASSEMBLY_DEPENDENCIES 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_USER_TYPES
#define CRESTRICTIONS_DBSCHEMA_SQL_USER_TYPES 3
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_XML_COLLECTIONS
#define CRESTRICTIONS_DBSCHEMA_XML_COLLECTIONS 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPES
#define CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPES 3
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPE_PRIMARY_KEYS
#define CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPE_PRIMARY_KEYS 3
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPE_COLUMNS
#define CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPE_COLUMNS 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_COLUMNS_EXTENDED
#define CRESTRICTIONS_DBSCHEMA_COLUMNS_EXTENDED 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_SPARSE_COLUMN_SET
#define CRESTRICTIONS_DBSCHEMA_SPARSE_COLUMN_SET 4
#endif
//----------------------------------------------------------------------------
// Provider-specific property sets
//
#ifndef _SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERDATASOURCE = {0x28efaee4,0x2d2c,0x11d1,{0x98,0x7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERDATASOURCEINFO= {0xdf10cb94,0x35f6,0x11d2,{0x9c,0x54,0x0,0xc0,0x4f,0x79,0x71,0xd3}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERDBINIT = {0x5cf4ca10,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERROWSET = {0x5cf4ca11,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERSESSION = {0x28efaee5,0x2d2c,0x11d1,{0x98,0x7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERCOLUMN = {0x3b63fb5e,0x3fbb,0x11d3,{0x9f,0x29,0x0,0xc0,0x4f,0x8e,0xe9,0xdc}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERSTREAM = {0x9f79c073,0x8a6d,0x4bca,{0xa8,0xa8,0xc9,0xb7,0x9a,0x9b,0x96,0x2d}};
#endif //_SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERPARAMETER = {0xfee09128,0xa67d,0x47ea,{0x8d,0x40,0x24,0xa1,0xd4,0x73,0x7e,0x8d}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERINDEX = {0xE428B84E,0xA6B7,0x413a,{0x94,0x65,0x56,0x23,0x2E,0x0D,0x2B,0xEB}};
extern const GUID OLEDBDECLSPEC DBPROPSET_PARAMETERALL = {0x2cd2b7d8,0xe7c2,0x4f6c,{0x9b,0x30,0x75,0xe2,0x58,0x46,0x10,0x97}};
//----------------------------------------------------------------------------
// Provider-specific columns for IColumnsRowset
//
#define DBCOLUMN_SS_X_GUID {0x627bd890,0xed54,0x11d2,{0xb9,0x94,0x0,0xc0,0x4f,0x8c,0xa8,0x2c}}
//
#ifndef _SQLOLEDB_H_
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_COMPFLAGS = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)100};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_SORTID = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)101};
extern const DBID OLEDBDECLSPEC DBCOLUMN_BASETABLEINSTANCE = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)102};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_TDSCOLLATION = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)103};
#endif //_SQLOLEDB_H_
extern const DBID OLEDBDECLSPEC DBCOLUMN_BASESERVERNAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)104};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_XML_SCHEMACOLLECTION_CATALOGNAME= {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)105};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_XML_SCHEMACOLLECTION_SCHEMANAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)106};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_XML_SCHEMACOLLECTIONNAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)107};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_UDT_CATALOGNAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)108};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_UDT_SCHEMANAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)109};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_UDT_NAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)110};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_ASSEMBLY_TYPENAME= {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)111};
// OLEDB part of SQL Server Native Client header - end here!
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
// ODBC part of SQL Server Native Client header - begin here!
#if defined(_SQLNCLI_ODBC_) || !defined(_SQLNCLI_OLEDB_)
#ifdef ODBCVER
// max SQL Server identifier length
#define SQL_MAX_SQLSERVERNAME 128
// SQLSetConnectAttr driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server Native Client driver usage.
// Connection attributes
#define SQL_COPT_SS_BASE 1200
#define SQL_COPT_SS_REMOTE_PWD (SQL_COPT_SS_BASE+1) // dbrpwset SQLSetConnectOption only
#define SQL_COPT_SS_USE_PROC_FOR_PREP (SQL_COPT_SS_BASE+2) // Use create proc for SQLPrepare
#define SQL_COPT_SS_INTEGRATED_SECURITY (SQL_COPT_SS_BASE+3) // Force integrated security on login
#define SQL_COPT_SS_PRESERVE_CURSORS (SQL_COPT_SS_BASE+4) // Preserve server cursors after SQLTransact
#define SQL_COPT_SS_USER_DATA (SQL_COPT_SS_BASE+5) // dbgetuserdata/dbsetuserdata
#define SQL_COPT_SS_ENLIST_IN_DTC SQL_ATTR_ENLIST_IN_DTC // Enlist in a DTC transaction
#define SQL_COPT_SS_ENLIST_IN_XA SQL_ATTR_ENLIST_IN_XA // Enlist in a XA transaction
#define SQL_COPT_SS_FALLBACK_CONNECT (SQL_COPT_SS_BASE+10) // Enables FallBack connections
#define SQL_COPT_SS_PERF_DATA (SQL_COPT_SS_BASE+11) // Used to access SQL Server ODBC driver performance data
#define SQL_COPT_SS_PERF_DATA_LOG (SQL_COPT_SS_BASE+12) // Used to set the logfile name for the Performance data
#define SQL_COPT_SS_PERF_QUERY_INTERVAL (SQL_COPT_SS_BASE+13) // Used to set the query logging threshold in milliseconds.
#define SQL_COPT_SS_PERF_QUERY_LOG (SQL_COPT_SS_BASE+14) // Used to set the logfile name for saving queryies.
#define SQL_COPT_SS_PERF_QUERY (SQL_COPT_SS_BASE+15) // Used to start and stop query logging.
#define SQL_COPT_SS_PERF_DATA_LOG_NOW (SQL_COPT_SS_BASE+16) // Used to make a statistics log entry to disk.
#define SQL_COPT_SS_QUOTED_IDENT (SQL_COPT_SS_BASE+17) // Enable/Disable Quoted Identifiers
#define SQL_COPT_SS_ANSI_NPW (SQL_COPT_SS_BASE+18) // Enable/Disable ANSI NULL, Padding and Warnings
#define SQL_COPT_SS_BCP (SQL_COPT_SS_BASE+19) // Allow BCP usage on connection
#define SQL_COPT_SS_TRANSLATE (SQL_COPT_SS_BASE+20) // Perform code page translation
#define SQL_COPT_SS_ATTACHDBFILENAME (SQL_COPT_SS_BASE+21) // File name to be attached as a database
#define SQL_COPT_SS_CONCAT_NULL (SQL_COPT_SS_BASE+22) // Enable/Disable CONCAT_NULL_YIELDS_NULL
#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_FAILOVER_PARTNER (SQL_COPT_SS_BASE+25) // Failover partner server
#define SQL_COPT_SS_OLDPWD (SQL_COPT_SS_BASE+26) // Old Password, used when changing password during login
#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
#define SQL_COPT_SS_SERVER_SPN (SQL_COPT_SS_BASE+29) // Server SPN
#define SQL_COPT_SS_FAILOVER_PARTNER_SPN (SQL_COPT_SS_BASE+30) // Failover partner server SPN
#define SQL_COPT_SS_INTEGRATED_AUTHENTICATION_METHOD (SQL_COPT_SS_BASE+31) // The integrated authentication method used for the connection
#define SQL_COPT_SS_MUTUALLY_AUTHENTICATED (SQL_COPT_SS_BASE+32) // Used to decide if the connection is mutually authenticated
#define SQL_COPT_SS_MAX_USED SQL_COPT_SS_MUTUALLY_AUTHENTICATED
// Define old names
#define SQL_REMOTE_PWD SQL_COPT_SS_REMOTE_PWD
#define SQL_USE_PROCEDURE_FOR_PREPARE SQL_COPT_SS_USE_PROC_FOR_PREP
#define SQL_INTEGRATED_SECURITY SQL_COPT_SS_INTEGRATED_SECURITY
#define SQL_PRESERVE_CURSORS SQL_COPT_SS_PRESERVE_CURSORS
// SQLSetStmtAttr SQL Server Native Client driver 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_CURRENT_COMMAND (SQL_SOPT_SS_BASE+1) // dbcurcmd SQLGetStmtOption only
#define SQL_SOPT_SS_HIDDEN_COLUMNS (SQL_SOPT_SS_BASE+2) // Expose FOR BROWSE hidden columns
#define SQL_SOPT_SS_NOBROWSETABLE (SQL_SOPT_SS_BASE+3) // Set NOBROWSETABLE option
#define SQL_SOPT_SS_REGIONALIZE (SQL_SOPT_SS_BASE+4) // Regionalize output character conversions
#define SQL_SOPT_SS_CURSOR_OPTIONS (SQL_SOPT_SS_BASE+5) // Server cursor options
#define SQL_SOPT_SS_NOCOUNT_STATUS (SQL_SOPT_SS_BASE+6) // Real vs. Not Real row count indicator
#define SQL_SOPT_SS_DEFER_PREPARE (SQL_SOPT_SS_BASE+7) // Defer prepare until necessary
#define SQL_SOPT_SS_QUERYNOTIFICATION_TIMEOUT (SQL_SOPT_SS_BASE+8) // Notification timeout
#define SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT (SQL_SOPT_SS_BASE+9) // Notification message text
#define SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS (SQL_SOPT_SS_BASE+10)// SQL service broker name
#define SQL_SOPT_SS_PARAM_FOCUS (SQL_SOPT_SS_BASE+11)// Direct subsequent calls to parameter related methods to set properties on constituent columns/parameters of container types
#define SQL_SOPT_SS_NAME_SCOPE (SQL_SOPT_SS_BASE+12)// Sets name scope for subsequent catalog function calls
#define SQL_SOPT_SS_MAX_USED SQL_SOPT_SS_NAME_SCOPE
// Define old names
#define SQL_TEXTPTR_LOGGING SQL_SOPT_SS_TEXTPTR_LOGGING
#define SQL_COPT_SS_BASE_EX 1240
#define SQL_COPT_SS_BROWSE_CONNECT (SQL_COPT_SS_BASE_EX+1) // Browse connect mode of operation
#define SQL_COPT_SS_BROWSE_SERVER (SQL_COPT_SS_BASE_EX+2) // Single Server browse request.
#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_BROWSE_CACHE_DATA (SQL_COPT_SS_BASE_EX+5) // Determines if we should cache browse info. Used when returned buffer is greater then ODBC limit (32K)
#define SQL_COPT_SS_RESET_CONNECTION (SQL_COPT_SS_BASE_EX+6) // When this option is set, we will perform connection reset on next packet
#define SQL_COPT_SS_EX_MAX_USED SQL_COPT_SS_RESET_CONNECTION
// SQLColAttributes driver specific defines.
// SQLSetDescField/SQLGetDescField driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server Native Client driver 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_DESC_BASE_COLUMN_NAME_OLD (SQL_CA_SS_BASE+13) // This is defined at another location.
#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_UDT_ASSEMBLY_TYPE_NAME (SQL_CA_SS_BASE+21) // Qualified name of the assembly containing the UDT class
#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
// 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
#define SQL_CA_SS_MAX_USED (SQL_CA_SS_BASE+36)
// Defines returned by SQL_ATTR_CURSOR_TYPE/SQL_CURSOR_TYPE
#define SQL_CURSOR_FAST_FORWARD_ONLY 8 // Only returned by SQLGetStmtAttr/Option
// Defines for use with SQL_COPT_SS_USE_PROC_FOR_PREP
#define SQL_UP_OFF 0L // Procedures won't be used for prepare
#define SQL_UP_ON 1L // Procedures will be used for prepare
#define SQL_UP_ON_DROP 2L // Temp procedures will be explicitly dropped
#define SQL_UP_DEFAULT SQL_UP_ON
// 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_PRESERVE_CURSORS
#define SQL_PC_OFF 0L // Cursors are closed on SQLTransact
#define SQL_PC_ON 1L // Cursors remain open on SQLTransact
#define SQL_PC_DEFAULT SQL_PC_OFF
// Defines for use with SQL_COPT_SS_USER_DATA
#define SQL_UD_NOTSET NULL // No user data pointer set
// 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_COPT_SS_FALLBACK_CONNECT - Pre-Connect Option only
#define SQL_FB_OFF 0L // FallBack connections are disabled
#define SQL_FB_ON 1L // FallBack connections are enabled
#define SQL_FB_DEFAULT SQL_FB_OFF
// Defines for use with SQL_COPT_SS_BCP - Pre-Connect Option only
#define SQL_BCP_OFF 0L // BCP is not allowed on connection
#define SQL_BCP_ON 1L // BCP is allowed on connection
#define SQL_BCP_DEFAULT SQL_BCP_OFF
// Defines for use with SQL_COPT_SS_QUOTED_IDENT
#define SQL_QI_OFF 0L // Quoted identifiers are enable
#define SQL_QI_ON 1L // Quoted identifiers are disabled
#define SQL_QI_DEFAULT SQL_QI_ON
// Defines for use with SQL_COPT_SS_ANSI_NPW - Pre-Connect Option only
#define SQL_AD_OFF 0L // ANSI NULLs, Padding and Warnings are enabled
#define SQL_AD_ON 1L // ANSI NULLs, Padding and Warnings are disabled
#define SQL_AD_DEFAULT SQL_AD_ON
// Defines for use with SQL_COPT_SS_CONCAT_NULL - Pre-Connect Option only
#define SQL_CN_OFF 0L // CONCAT_NULL_YIELDS_NULL is off
#define SQL_CN_ON 1L // CONCAT_NULL_YIELDS_NULL is on
#define SQL_CN_DEFAULT SQL_CN_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
#define SQL_TL_DEFAULT SQL_TL_ON
// Defines for use with SQL_SOPT_SS_HIDDEN_COLUMNS
#define SQL_HC_OFF 0L // FOR BROWSE columns are hidden
#define SQL_HC_ON 1L // FOR BROWSE columns are exposed
#define SQL_HC_DEFAULT SQL_HC_OFF
// 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_REGIONALIZE
#define SQL_RE_OFF 0L // No regionalization occurs on output character conversions
#define SQL_RE_ON 1L // Regionalization occurs on output character conversions
#define SQL_RE_DEFAULT SQL_RE_OFF
// Defines for use with SQL_SOPT_SS_CURSOR_OPTIONS
#define SQL_CO_OFF 0L // Clear all cursor options
#define SQL_CO_FFO 1L // Fast-forward cursor will be used
#define SQL_CO_AF 2L // Autofetch on cursor open
#define SQL_CO_FFO_AF (SQL_CO_FFO|SQL_CO_AF) // Fast-forward cursor with autofetch
#define SQL_CO_FIREHOSE_AF 4L // Auto fetch on fire-hose cursors
#define SQL_CO_DEFAULT SQL_CO_OFF
//SQL_SOPT_SS_NOCOUNT_STATUS
#define SQL_NC_OFF 0L
#define SQL_NC_ON 1L
//SQL_SOPT_SS_DEFER_PREPARE
#define SQL_DP_OFF 0L
#define SQL_DP_ON 1L
//SQL_SOPT_SS_NAME_SCOPE
#define SQL_SS_NAME_SCOPE_TABLE 0L
#define SQL_SS_NAME_SCOPE_TABLE_TYPE 1L
#define SQL_SS_NAME_SCOPE_EXTENDED 2L
#define SQL_SS_NAME_SCOPE_SPARSE_COLUMN_SET 3L
#define SQL_SS_NAME_SCOPE_DEFAULT SQL_SS_NAME_SCOPE_TABLE
//SQL_COPT_SS_ENCRYPT
#define SQL_EN_OFF 0L
#define SQL_EN_ON 1L
//SQL_COPT_SS_TRUST_SERVER_CERTIFICATE
#define SQL_TRUST_SERVER_CERTIFICATE_NO 0L
#define SQL_TRUST_SERVER_CERTIFICATE_YES 1L
//SQL_COPT_SS_BROWSE_CONNECT
#define SQL_MORE_INFO_NO 0L
#define SQL_MORE_INFO_YES 1L
//SQL_COPT_SS_BROWSE_CACHE_DATA
#define SQL_CACHE_DATA_NO 0L
#define SQL_CACHE_DATA_YES 1L
//SQL_COPT_SS_RESET_CONNECTION
#define SQL_RESET_YES 1L
//SQL_COPT_SS_WARN_ON_CP_ERROR
#define SQL_WARN_NO 0L
#define SQL_WARN_YES 1L
//SQL_COPT_SS_MARS_ENABLED
#define SQL_MARS_ENABLED_NO 0L
#define SQL_MARS_ENABLED_YES 1L
/* SQL_TXN_ISOLATION_OPTION bitmasks */
#define SQL_TXN_SS_SNAPSHOT 0x00000020L
// 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 SQL Server Native Client driver usage.
#define SQL_SS_VARIANT (-150)
#define SQL_SS_UDT (-151)
#define SQL_SS_XML (-152)
#define SQL_SS_TABLE (-153)
#define SQL_SS_TIME2 (-154)
#define SQL_SS_TIMESTAMPOFFSET (-155)
// 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
#ifndef SQLNCLI_NO_BCP
// Define the symbol SQLNCLI_NO_BCP if you are not using BCP in your application
// and you want to exclude the BCP-related definitions in this header file.
// SQL Server Data Type defines.
// New types for SQL 6.0 and later servers
#define SQLTEXT 0x23
#define SQLVARBINARY 0x25
#define SQLINTN 0x26
#define SQLVARCHAR 0x27
#define SQLBINARY 0x2d
#define SQLIMAGE 0x22
#define SQLCHARACTER 0x2f
#define SQLINT1 0x30
#define SQLBIT 0x32
#define SQLINT2 0x34
#define SQLINT4 0x38
#define SQLMONEY 0x3c
#define SQLDATETIME 0x3d
#define SQLFLT8 0x3e
#define SQLFLTN 0x6d
#define SQLMONEYN 0x6e
#define SQLDATETIMN 0x6f
#define SQLFLT4 0x3b
#define SQLMONEY4 0x7a
#define SQLDATETIM4 0x3a
// New types for SQL 6.0 and later servers
#define SQLDECIMAL 0x6a
#define SQLNUMERIC 0x6c
// New types for SQL 7.0 and later servers
#define SQLUNIQUEID 0x24
#define SQLBIGCHAR 0xaf
#define SQLBIGVARCHAR 0xa7
#define SQLBIGBINARY 0xad
#define SQLBIGVARBINARY 0xa5
#define SQLBITN 0x68
#define SQLNCHAR 0xef
#define SQLNVARCHAR 0xe7
#define SQLNTEXT 0x63
// New types for SQL 2000 and later servers
#define SQLINT8 0x7f
#define SQLVARIANT 0x62
// New types for SQL 2005 and later servers
#define SQLUDT 0xf0
#define SQLXML 0xf1
// New types for SQL 2008 and later servers
#define SQLTABLE 0xf3
#define SQLDATEN 0x28
#define SQLTIMEN 0x29
#define SQLDATETIME2N 0x2a
#define SQLDATETIMEOFFSETN 0x2b
// Define old names
#define SQLDECIMALN 0x6a
#define SQLNUMERICN 0x6c
#endif // SQLNCLI_NO_BCP
// 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.
#define SQLudtBINARY 3
#define SQLudtBIT 16
#define SQLudtBITN 0
#define SQLudtCHAR 1
#define SQLudtDATETIM4 22
#define SQLudtDATETIME 12
#define SQLudtDATETIMN 15
#define SQLudtDECML 24
#define SQLudtDECMLN 26
#define SQLudtFLT4 23
#define SQLudtFLT8 8
#define SQLudtFLTN 14
#define SQLudtIMAGE 20
#define SQLudtINT1 5
#define SQLudtINT2 6
#define SQLudtINT4 7
#define SQLudtINTN 13
#define SQLudtMONEY 11
#define SQLudtMONEY4 21
#define SQLudtMONEYN 17
#define SQLudtNUM 10
#define SQLudtNUMN 25
#define SQLudtSYSNAME 18
#define SQLudtTEXT 19
#define SQLudtTIMESTAMP 80
#define SQLudtUNIQUEIDENTIFIER 0
#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
// SQLGetInfo driver specific defines.
// Microsoft has 1151 thru 1200 reserved for Microsoft SQL Server Native Client driver usage.
#define SQL_INFO_SS_FIRST 1199
#define SQL_INFO_SS_NETLIB_NAMEW (SQL_INFO_SS_FIRST+0) // dbprocinfo
#define SQL_INFO_SS_NETLIB_NAMEA (SQL_INFO_SS_FIRST+1) // dbprocinfo
#define SQL_INFO_SS_MAX_USED SQL_INFO_SS_NETLIB_NAMEA
#ifdef UNICODE
#define SQL_INFO_SS_NETLIB_NAME SQL_INFO_SS_NETLIB_NAMEW
#else
#define SQL_INFO_SS_NETLIB_NAME SQL_INFO_SS_NETLIB_NAMEA
#endif
// SQLGetDiagField driver specific defines.
// Microsoft has -1150 thru -1199 reserved for Microsoft SQL Server Native Client driver 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 SQL Server Native Client driver 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)
#define SQL_DIAG_DFC_SS_CONDITION (SQL_DIAG_DFC_SS_BASE-2)
#define SQL_DIAG_DFC_SS_CREATE_DATABASE (SQL_DIAG_DFC_SS_BASE-3)
#define SQL_DIAG_DFC_SS_CREATE_DEFAULT (SQL_DIAG_DFC_SS_BASE-4)
#define SQL_DIAG_DFC_SS_CREATE_PROCEDURE (SQL_DIAG_DFC_SS_BASE-5)
#define SQL_DIAG_DFC_SS_CREATE_RULE (SQL_DIAG_DFC_SS_BASE-6)
#define SQL_DIAG_DFC_SS_CREATE_TRIGGER (SQL_DIAG_DFC_SS_BASE-7)
#define SQL_DIAG_DFC_SS_CURSOR_DECLARE (SQL_DIAG_DFC_SS_BASE-8)
#define SQL_DIAG_DFC_SS_CURSOR_OPEN (SQL_DIAG_DFC_SS_BASE-9)
#define SQL_DIAG_DFC_SS_CURSOR_FETCH (SQL_DIAG_DFC_SS_BASE-10)
#define SQL_DIAG_DFC_SS_CURSOR_CLOSE (SQL_DIAG_DFC_SS_BASE-11)
#define SQL_DIAG_DFC_SS_DEALLOCATE_CURSOR (SQL_DIAG_DFC_SS_BASE-12)
#define SQL_DIAG_DFC_SS_DBCC (SQL_DIAG_DFC_SS_BASE-13)
#define SQL_DIAG_DFC_SS_DISK (SQL_DIAG_DFC_SS_BASE-14)
#define SQL_DIAG_DFC_SS_DROP_DATABASE (SQL_DIAG_DFC_SS_BASE-15)
#define SQL_DIAG_DFC_SS_DROP_DEFAULT (SQL_DIAG_DFC_SS_BASE-16)
#define SQL_DIAG_DFC_SS_DROP_PROCEDURE (SQL_DIAG_DFC_SS_BASE-17)
#define SQL_DIAG_DFC_SS_DROP_RULE (SQL_DIAG_DFC_SS_BASE-18)
#define SQL_DIAG_DFC_SS_DROP_TRIGGER (SQL_DIAG_DFC_SS_BASE-19)
#define SQL_DIAG_DFC_SS_DUMP_DATABASE (SQL_DIAG_DFC_SS_BASE-20)
#define SQL_DIAG_DFC_SS_BACKUP_DATABASE (SQL_DIAG_DFC_SS_BASE-20)
#define SQL_DIAG_DFC_SS_DUMP_TABLE (SQL_DIAG_DFC_SS_BASE-21)
#define SQL_DIAG_DFC_SS_DUMP_TRANSACTION (SQL_DIAG_DFC_SS_BASE-22)
#define SQL_DIAG_DFC_SS_BACKUP_TRANSACTION (SQL_DIAG_DFC_SS_BASE-22)
#define SQL_DIAG_DFC_SS_GOTO (SQL_DIAG_DFC_SS_BASE-23)
#define SQL_DIAG_DFC_SS_INSERT_BULK (SQL_DIAG_DFC_SS_BASE-24)
#define SQL_DIAG_DFC_SS_KILL (SQL_DIAG_DFC_SS_BASE-25)
#define SQL_DIAG_DFC_SS_LOAD_DATABASE (SQL_DIAG_DFC_SS_BASE-26)
#define SQL_DIAG_DFC_SS_RESTORE_DATABASE (SQL_DIAG_DFC_SS_BASE-26)
#define SQL_DIAG_DFC_SS_LOAD_HEADERONLY (SQL_DIAG_DFC_SS_BASE-27)
#define SQL_DIAG_DFC_SS_RESTORE_HEADERONLY (SQL_DIAG_DFC_SS_BASE-27)
#define SQL_DIAG_DFC_SS_LOAD_TABLE (SQL_DIAG_DFC_SS_BASE-28)
#define SQL_DIAG_DFC_SS_LOAD_TRANSACTION (SQL_DIAG_DFC_SS_BASE-29)
#define SQL_DIAG_DFC_SS_RESTORE_TRANSACTION (SQL_DIAG_DFC_SS_BASE-29)
#define SQL_DIAG_DFC_SS_PRINT (SQL_DIAG_DFC_SS_BASE-30)
#define SQL_DIAG_DFC_SS_RAISERROR (SQL_DIAG_DFC_SS_BASE-31)
#define SQL_DIAG_DFC_SS_READTEXT (SQL_DIAG_DFC_SS_BASE-32)
#define SQL_DIAG_DFC_SS_RECONFIGURE (SQL_DIAG_DFC_SS_BASE-33)
#define SQL_DIAG_DFC_SS_RETURN (SQL_DIAG_DFC_SS_BASE-34)
#define SQL_DIAG_DFC_SS_SELECT_INTO (SQL_DIAG_DFC_SS_BASE-35)
#define SQL_DIAG_DFC_SS_SET (SQL_DIAG_DFC_SS_BASE-36)
#define SQL_DIAG_DFC_SS_SET_IDENTITY_INSERT (SQL_DIAG_DFC_SS_BASE-37)
#define SQL_DIAG_DFC_SS_SET_ROW_COUNT (SQL_DIAG_DFC_SS_BASE-38)
#define SQL_DIAG_DFC_SS_SET_STATISTICS (SQL_DIAG_DFC_SS_BASE-39)
#define SQL_DIAG_DFC_SS_SET_TEXTSIZE (SQL_DIAG_DFC_SS_BASE-40)
#define SQL_DIAG_DFC_SS_SETUSER (SQL_DIAG_DFC_SS_BASE-41)
#define SQL_DIAG_DFC_SS_SHUTDOWN (SQL_DIAG_DFC_SS_BASE-42)
#define SQL_DIAG_DFC_SS_TRANS_BEGIN (SQL_DIAG_DFC_SS_BASE-43)
#define SQL_DIAG_DFC_SS_TRANS_COMMIT (SQL_DIAG_DFC_SS_BASE-44)
#define SQL_DIAG_DFC_SS_TRANS_PREPARE (SQL_DIAG_DFC_SS_BASE-45)
#define SQL_DIAG_DFC_SS_TRANS_ROLLBACK (SQL_DIAG_DFC_SS_BASE-46)
#define SQL_DIAG_DFC_SS_TRANS_SAVE (SQL_DIAG_DFC_SS_BASE-47)
#define SQL_DIAG_DFC_SS_TRUNCATE_TABLE (SQL_DIAG_DFC_SS_BASE-48)
#define SQL_DIAG_DFC_SS_UPDATE_STATISTICS (SQL_DIAG_DFC_SS_BASE-49)
#define SQL_DIAG_DFC_SS_UPDATETEXT (SQL_DIAG_DFC_SS_BASE-50)
#define SQL_DIAG_DFC_SS_USE (SQL_DIAG_DFC_SS_BASE-51)
#define SQL_DIAG_DFC_SS_WAITFOR (SQL_DIAG_DFC_SS_BASE-52)
#define SQL_DIAG_DFC_SS_WRITETEXT (SQL_DIAG_DFC_SS_BASE-53)
#define SQL_DIAG_DFC_SS_DENY (SQL_DIAG_DFC_SS_BASE-54)
#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
#define EX_ANY 0
#define EX_INFO 10
#define EX_MAXISEVERITY EX_INFO
#define EX_MISSING 11
#define EX_TYPE 12
#define EX_DEADLOCK 13
#define EX_PERMIT 14
#define EX_SYNTAX 15
#define EX_USER 16
#define EX_RESOURCE 17
#define EX_INTOK 18
#define MAXUSEVERITY EX_INTOK
#define EX_LIMIT 19
#define EX_CMDFATAL 20
#define MINFATALERR EX_CMDFATAL
#define EX_DBFATAL 21
#define EX_TABCORRUPT 22
#define EX_DBCORRUPT 23
#define EX_HARDWARE 24
#define EX_CONTROL 25
// Internal server datatypes - used when binding to SQL_C_BINARY
#ifndef MAXNUMERICLEN // Resolve ODS/DBLib conflicts
// DB-Library datatypes
#define DBMAXCHAR (8000+1) // Max length of DBVARBINARY and DBVARCHAR, etc. +1 for zero byte
#define MAXNAME (SQL_MAX_SQLSERVERNAME+1) // Max server identifier length including zero byte
#ifdef UNICODE
typedef wchar_t DBCHAR;
#else
typedef char DBCHAR;
#endif
typedef short SQLSMALLINT;
typedef unsigned short SQLUSMALLINT;
typedef long SQLINTEGER;
typedef unsigned long SQLUINTEGER;
typedef unsigned char DBBINARY;
typedef unsigned char DBTINYINT;
typedef short DBSMALLINT;
typedef unsigned short DBUSMALLINT;
typedef double DBFLT8;
typedef unsigned char DBBIT;
typedef unsigned char DBBOOL;
typedef float DBFLT4;
typedef DBFLT4 DBREAL;
typedef UINT DBUBOOL;
typedef struct dbmoney
{
LONG mnyhigh;
ULONG mnylow;
} DBMONEY;
typedef struct dbdatetime
{
LONG dtdays;
ULONG dttime;
} DBDATETIME;
typedef struct dbdatetime4
{
USHORT numdays;
USHORT nummins;
} DBDATETIM4;
typedef LONG DBMONEY4;
#include <pshpack8.h> // 8-byte structure packing
// New Date Time Structures
// New Structure for TIME2
typedef struct tagSS_TIME2_STRUCT
{
SQLUSMALLINT hour;
SQLUSMALLINT minute;
SQLUSMALLINT second;
SQLUINTEGER fraction;
} SQL_SS_TIME2_STRUCT;
// New Structure for TIMESTAMPOFFSET
typedef struct tagSS_TIMESTAMPOFFSET_STRUCT
{
SQLSMALLINT year;
SQLUSMALLINT month;
SQLUSMALLINT day;
SQLUSMALLINT hour;
SQLUSMALLINT minute;
SQLUSMALLINT second;
SQLUINTEGER fraction;
SQLSMALLINT timezone_hour;
SQLSMALLINT timezone_minute;
} SQL_SS_TIMESTAMPOFFSET_STRUCT;
#include <poppack.h> // restore original structure packing
// Money value *10,000
#define DBNUM_PREC_TYPE BYTE
#define DBNUM_SCALE_TYPE BYTE
#define DBNUM_VAL_TYPE BYTE
#if (ODBCVER < 0x0300)
#define MAXNUMERICLEN 16
typedef struct dbnumeric // Internal representation of NUMERIC data type
{
DBNUM_PREC_TYPE precision; // Precision
DBNUM_SCALE_TYPE scale; // Scale
BYTE sign; // Sign (1 if positive, 0 if negative)
DBNUM_VAL_TYPE val[MAXNUMERICLEN];// Value
} DBNUMERIC;
typedef DBNUMERIC DBDECIMAL;// Internal representation of DECIMAL data type
#else // Use ODBC 3.0 definitions since same as DBLib
#define MAXNUMERICLEN SQL_MAX_NUMERIC_LEN
typedef SQL_NUMERIC_STRUCT DBNUMERIC;
typedef SQL_NUMERIC_STRUCT DBDECIMAL;
#endif // ODCBVER
#endif // MAXNUMERICLEN
#ifndef INT
typedef int INT;
typedef long DBINT;
typedef DBINT * LPDBINT;
#ifndef _LPCBYTE_DEFINED
#define _LPCBYTE_DEFINED
typedef BYTE const* LPCBYTE;
#endif //_LPCBYTE_DEFINED
#endif // INT
/**************************************************************************
This struct is a global used for gathering statistical data on the driver.
Access to this structure is controlled via the pStatCrit;
***************************************************************************/
typedef struct sqlperf
{
// Application Profile Statistics
DWORD TimerResolution;
DWORD SQLidu;
DWORD SQLiduRows;
DWORD SQLSelects;
DWORD SQLSelectRows;
DWORD Transactions;
DWORD SQLPrepares;
DWORD ExecDirects;
DWORD SQLExecutes;
DWORD CursorOpens;
DWORD CursorSize;
DWORD CursorUsed;
LDOUBLE PercentCursorUsed;
LDOUBLE AvgFetchTime;
LDOUBLE AvgCursorSize;
LDOUBLE AvgCursorUsed;
DWORD SQLFetchTime;
DWORD SQLFetchCount;
DWORD CurrentStmtCount;
DWORD MaxOpenStmt;
DWORD SumOpenStmt;
// Connection Statistics
DWORD CurrentConnectionCount;
DWORD MaxConnectionsOpened;
DWORD SumConnectionsOpened;
DWORD SumConnectiontime;
LDOUBLE AvgTimeOpened;
// Network Statistics
DWORD ServerRndTrips;
DWORD BuffersSent;
DWORD BuffersRec;
DWORD BytesSent;
DWORD BytesRec;
// Time Statistics;
DWORD msExecutionTime;
DWORD msNetWorkServerTime;
} SQLPERF;
// The following are options for SQL_COPT_SS_PERF_DATA and SQL_COPT_SS_PERF_QUERY
#define SQL_PERF_START 1 // Starts the driver sampling performance data.
#define SQL_PERF_STOP 2 // Stops the counters from sampling performance data.
// The following are defines for SQL_COPT_SS_PERF_DATA_LOG
#define SQL_SS_DL_DEFAULT TEXT("STATS.LOG")
// The following are defines for SQL_COPT_SS_PERF_QUERY_LOG
#define SQL_SS_QL_DEFAULT TEXT("QUERY.LOG")
// The following are defines for SQL_COPT_SS_PERF_QUERY_INTERVAL
#define SQL_SS_QI_DEFAULT 30000 // 30,000 milliseconds
#ifndef SQLNCLI_NO_BCP
// Define the symbol SQLNCLI_NO_BCP if you are not using BCP in your application
// and you want to exclude the BCP-related definitions in this header file.
// ODBC BCP prototypes and defines
// Return codes
#define SUCCEED 1
#define FAIL 0
#define SUCCEED_ABORT 2
#define SUCCEED_ASYNC 3
// Transfer directions
#define DB_IN 1 // Transfer from client to server
#define DB_OUT 2 // Transfer from server to client
// bcp_control option
#define BCPMAXERRS 1 // Sets max errors allowed
#define BCPFIRST 2 // Sets first row to be copied out
#define BCPLAST 3 // Sets number of rows to be copied out
#define BCPBATCH 4 // Sets input batch size
#define BCPKEEPNULLS 5 // Sets to insert NULLs for empty input values
#define BCPABORT 6 // Sets to have bcpexec return SUCCEED_ABORT
#define BCPODBC 7 // Sets ODBC canonical character output
#define BCPKEEPIDENTITY 8 // Sets IDENTITY_INSERT on
#if SQLNCLI_VER < 1000
#define BCP6xFILEFMT 9 // DEPRECATED: Sets 6x file format on
#endif
#define BCPHINTSA 10 // Sets server BCP hints (ANSI string)
#define BCPHINTSW 11 // Sets server BCP hints (UNICODE string)
#define BCPFILECP 12 // Sets clients code page for the file
#define BCPUNICODEFILE 13 // Sets that the file contains unicode header
#define BCPTEXTFILE 14 // Sets BCP mode to expect a text file and to detect Unicode or ANSI automatically
#define BCPFILEFMT 15 // Sets file format version
#define BCPFMTXML 16 // Sets the format file type to xml
#define BCPFIRSTEX 17 // Starting Row for BCP operation (64 bit)
#define BCPLASTEX 18 // Ending Row for BCP operation (64 bit)
#define BCPROWCOUNT 19 // Total Number of Rows Copied (64 bit)
// BCPFILECP values
// Any valid code page that is installed on the client can be passed plus:
#define BCPFILECP_ACP 0 // Data in file is in Windows code page
#define BCPFILECP_OEMCP 1 // Data in file is in OEM code page (default)
#define BCPFILECP_RAW (-1)// Data in file is in Server code page (no conversion)
// bcp_collen definition
#define SQL_VARLEN_DATA (-10) // Use default length for column
// BCP column format properties
#define BCP_FMT_TYPE 0x01
#define BCP_FMT_INDICATOR_LEN 0x02
#define BCP_FMT_DATA_LEN 0x03
#define BCP_FMT_TERMINATOR 0x04
#define BCP_FMT_SERVER_COL 0x05
#define BCP_FMT_COLLATION 0x06
#define BCP_FMT_COLLATION_ID 0x07
// BCP functions
DBINT SQL_API bcp_batch (HDBC);
RETCODE SQL_API bcp_bind (HDBC, LPCBYTE, INT, DBINT, LPCBYTE, INT, INT, INT);
RETCODE SQL_API bcp_colfmt (HDBC, INT, BYTE, INT, DBINT, LPCBYTE, INT, INT);
RETCODE SQL_API bcp_collen (HDBC, DBINT, INT);
RETCODE SQL_API bcp_colptr (HDBC, LPCBYTE, INT);
RETCODE SQL_API bcp_columns (HDBC, INT);
RETCODE SQL_API bcp_control (HDBC, INT, void *);
DBINT SQL_API bcp_done (HDBC);
RETCODE SQL_API bcp_exec (HDBC, LPDBINT);
RETCODE SQL_API bcp_getcolfmt (HDBC, INT, INT, void *, INT, INT *);
RETCODE SQL_API bcp_initA (HDBC, LPCSTR, LPCSTR, LPCSTR, INT);
RETCODE SQL_API bcp_initW (HDBC, LPCWSTR, LPCWSTR, LPCWSTR, INT);
RETCODE SQL_API bcp_moretext (HDBC, DBINT, LPCBYTE);
RETCODE SQL_API bcp_readfmtA (HDBC, LPCSTR);
RETCODE SQL_API bcp_readfmtW (HDBC, LPCWSTR);
RETCODE SQL_API bcp_sendrow (HDBC);
RETCODE SQL_API bcp_setcolfmt (HDBC, INT, INT, void *, INT);
RETCODE SQL_API bcp_writefmtA (HDBC, LPCSTR);
RETCODE SQL_API bcp_writefmtW (HDBC, LPCWSTR);
CHAR* SQL_API dbprtypeA (INT);
WCHAR* SQL_API dbprtypeW (INT);
CHAR* SQL_API bcp_gettypenameA (INT, DBBOOL);
WCHAR* SQL_API bcp_gettypenameW (INT, DBBOOL);
#ifdef UNICODE
#define bcp_init bcp_initW
#define bcp_readfmt bcp_readfmtW
#define bcp_writefmt bcp_writefmtW
#define dbprtype dbprtypeW
#define bcp_gettypename bcp_gettypenameW
#define BCPHINTS BCPHINTSW
#else
#define bcp_init bcp_initA
#define bcp_readfmt bcp_readfmtA
#define bcp_writefmt bcp_writefmtA
#define dbprtype dbprtypeA
#define bcp_gettypename bcp_gettypenameA
#define BCPHINTS BCPHINTSA
#endif // UNICODE
#endif // SQLNCLI_NO_BCP
// The following options have been deprecated
#define SQL_FAST_CONNECT (SQL_COPT_SS_BASE+0)
// Defines for use with SQL_FAST_CONNECT - only useable before connecting
#define SQL_FC_OFF 0L // Fast connect is off
#define SQL_FC_ON 1L // Fast connect is on
#define SQL_FC_DEFAULT SQL_FC_OFF
#define SQL_COPT_SS_ANSI_OEM (SQL_COPT_SS_BASE+6)
#define SQL_AO_OFF 0L
#define SQL_AO_ON 1L
#define SQL_AO_DEFAULT SQL_AO_OFF
#define SQL_CA_SS_BASE_COLUMN_NAME SQL_DESC_BASE_COLUMN_NAME
#endif // ODBCVER
#endif // defined(_SQLNCLI_ODBC_) || !defined(_SQLNCLI_OLEDB_)
// ODBC part of SQL Server Native Client header - end here!
//The following facilitates opening a handle to a SQL filestream
typedef enum _SQL_FILESTREAM_DESIRED_ACCESS {
SQL_FILESTREAM_READ = 0,
SQL_FILESTREAM_WRITE = 1,
SQL_FILESTREAM_READWRITE = 2
} SQL_FILESTREAM_DESIRED_ACCESS;
#define SQL_FILESTREAM_OPEN_FLAG_ASYNC 0x00000001L
#define SQL_FILESTREAM_OPEN_FLAG_NO_BUFFERING 0x00000002L
#define SQL_FILESTREAM_OPEN_FLAG_NO_WRITE_THROUGH 0x00000004L
#define SQL_FILESTREAM_OPEN_FLAG_SEQUENTIAL_SCAN 0x00000008L
#define SQL_FILESTREAM_OPEN_FLAG_RANDOM_ACCESS 0x00000010L
HANDLE __stdcall OpenSqlFilestream (
LPCWSTR FilestreamPath,
SQL_FILESTREAM_DESIRED_ACCESS DesiredAccess,
ULONG OpenOptions,
LPBYTE FilestreamTransactionContext,
SSIZE_T FilestreamTransactionContextLength,
PLARGE_INTEGER AllocationSize);
#define FSCTL_SQL_FILESTREAM_FETCH_OLD_CONTENT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2392, METHOD_BUFFERED, FILE_ANY_ACCESS)
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0010_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0010_v0_0_s_ifspec;
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -3,7 +3,7 @@
//
// Contents: Version resource
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -65,7 +65,7 @@ BEGIN
VALUE "FileDescription", "Microsoft Drivers for PHP for SQL Server (PDO Driver)\0"
VALUE "FileVersion", STRVER4(SQLVERSION_MAJOR,SQLVERSION_MINOR, SQLVERSION_MMDD, SQLVERSION_REVISION)
VALUE "InternalName", FILE_NAME "\0"
VALUE "LegalCopyright", "Copyright 2010 Microsoft Corporation.\0"
VALUE "LegalCopyright", "Copyright Microsoft Corporation.\0"
VALUE "OriginalFilename", FILE_NAME "\0"
VALUE "ProductName", "Microsoft Drivers for PHP for SQL Server\0"
VALUE "ProductVersion", STRVER3(SQLVERSION_MAJOR,SQLVERSION_MINOR, SQLVERSION_MMDD)

View file

@ -1,9 +1,9 @@
//---------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
// File: version.h
//
// Contents: Version information for compile and resources
//
// Copyright 2010 Microsoft Corporation
// Contents: Version number constants
//
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -16,11 +16,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//---------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
#define VER_FILEVERSION_STR "2.0.0.200"
#define _FILEVERSION 2,0,0,200
#define SQLVERSION_MAJOR 2
#define VER_FILEVERSION_STR "3.0.0.0"
#define _FILEVERSION 3,0,0,0
#define SQLVERSION_MAJOR 3
#define SQLVERSION_MINOR 0
#define SQLVERSION_MMDD 0
#define SQLVERSION_REVISION 200
#define SQLVERSION_REVISION 0

View file

@ -1 +1 @@
Microsoft Drivers for PHP for SQL Server 2.0 Cumulative Update 1
Microsoft Drivers 3.0 for PHP for SQL Server (SQLSRV driver)

View file

@ -1,6 +1,6 @@
* Copyright and License Information *
Copyright 2010 Microsoft Corporation
Copyright Microsoft Corporation
Licensed under the Apache License, Version 2.0 (the "License"); you
may not use this file except in compliance with the License.
@ -14,33 +14,25 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.
* Notes about changes to the Microsoft Drivers for PHP for SQL Server
Driver 2.0 *
* Notes about changes to the Microsoft Drivers 3.0 for PHP for SQL Server *
For details about the changes included in this release, please see our blog at
http://blogs.msdn.com/sqlphp or see the SQLSRV20_Readme.htm
http://blogs.msdn.com/sqlphp or see the SQLSRV_Readme.htm
file that is part of the download package.
* Notes about compiling the Microsoft Drivers for PHP for SQL Server 2.0 *
* Notes about compiling the Microsoft Drivers 3.0 for PHP for SQL Server *
Prerequisites:
* You must first be able to build PHP without including these
extensions. For help with doing this, see xthe official PHP website,
extensions. For help with doing this, see the official PHP website,
http://php.net.
* The header file sqlncli.h is required to build these extensions. It
may be installed with the Microsoft SQL Server® 2008 R2 Native Client
(found at Microsoft.com)
To compile the SQLSRV20 and PDO_SQLSRV20:
To compile the SQLSRV30 and PDO_SQLSRV30:
1) Copy the source code directories from this repository into the ext
subdirectory.
1a) Make sure that sqlncli.h is either on the INCLUDE file path or
copied locally to the extension directories.
2) run buildconf.bat to rebuild the configure.js script to include the
new drivers.
@ -61,8 +53,8 @@ wish to do so, run "nmake clean" first.
php_sqlsrv.dll and php_pdo_sqlsrv.dll to your PHP extension directory.
Also enable them within your PHP installation's php.ini file.
This software has been compiled and tested under PHP 5.2.10 and PHP 5.3.0
using the Visual C++ 2008 Express and Standard compilers.
This software has been compiled and tested under PHP 5.3.6 and later
using the Visual C++ 2008 and 2010, Express and Standard compilers.
* Note about version.h *

View file

@ -3,7 +3,7 @@
//
// Contents: JScript build configuration used by buildconf.bat
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -18,18 +18,20 @@
// limitations under the License.
//----------------------------------------------------------------------------------------------------------------------------------
ARG_ENABLE("sqlsrv", "enable MS SQL Server extension", "no");
ARG_ENABLE("sqlsrv", "enable Microsoft Drivers for PHP for SQL Server (SQLSRV driver)", "no");
if( PHP_SQLSRV != "no" ) {
if (CHECK_LIB("odbc32.lib", "sqlsrv") && CHECK_LIB("odbccp32.lib", "sqlsrv") &&
CHECK_LIB("version.lib", "sqlsrv") && CHECK_LIB("psapi.lib", "sqlsrv")) {
EXTENSION("sqlsrv", "conn.cpp init.cpp stmt.cpp util.cpp core_init.cpp core_conn.cpp core_stmt.cpp core_util.cpp core_stream.cpp" )
EXTENSION("sqlsrv", "conn.cpp init.cpp stmt.cpp util.cpp core_init.cpp core_conn.cpp core_stmt.cpp core_util.cpp core_stream.cpp core_results.cpp" )
CHECK_HEADER_ADD_INCLUDE('sql.h', 'CFLAGS_SQLSRV_ODBC');
CHECK_HEADER_ADD_INCLUDE('sqlext.h', 'CFLAGS_SQLSRV_ODBC');
ADD_FLAG( 'LDFLAGS_SQLSRV', '/NXCOMPAT /DYNAMICBASE' );
ADD_FLAG( 'CFLAGS_SQLSRV', '/D ZEND_WIN32_FORCE_INLINE' );
ADD_FLAG( 'CFLAGS_SQLSRV', '/D _HAS_CPP0X=0' );
ADD_FLAG( 'CFLAGS_SQLSRV', '/EHsc' );
ADD_FLAG( 'CFLAGS_SQLSRV', '/GS' );
}

View file

@ -3,7 +3,7 @@
//
// Contents: Routines that use connection handles
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -162,6 +162,7 @@ namespace SSStmtOptionNames {
const char QUERY_TIMEOUT[]= "QueryTimeout";
const char SEND_STREAMS_AT_EXEC[] = "SendStreamParamsAtExec";
const char SCROLLABLE[] = "Scrollable";
const char CLIENT_BUFFER_MAX_SIZE[] = INI_BUFFERED_QUERY_LIMIT;
}
namespace SSConnOptionNames {
@ -169,6 +170,8 @@ namespace SSConnOptionNames {
// most of these strings are the same for both the sqlsrv_connect connection option
// and the name put into the connection string. MARS is the only one that's different.
const char APP[] = "APP";
const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char CharacterSet[] = "CharacterSet";
const char ConnectionPooling[] = "ConnectionPooling";
const char Database[] = "Database";
@ -177,6 +180,7 @@ const char Encrypt[] = "Encrypt";
const char Failover_Partner[] = "Failover_Partner";
const char LoginTimeout[] = "LoginTimeout";
const char MARS_Option[] = "MultipleActiveResultSets";
const char MultiSubnetFailover[] = "MultiSubnetFailover";
const char PWD[] = "PWD";
const char QuotedId[] = "QuotedId";
const char TraceFile[] = "TraceFile";
@ -213,6 +217,12 @@ const stmt_option SS_STMT_OPTS[] = {
SQLSRV_STMT_OPTION_SCROLLABLE,
new stmt_option_scrollable
},
{
SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE,
sizeof( SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE ),
SQLSRV_STMT_OPTION_CLIENT_BUFFER_MAX_SIZE,
new stmt_option_buffered_query_limit
},
{ NULL, 0, SQLSRV_STMT_OPTION_INVALID, NULL },
};
@ -228,6 +238,24 @@ const connection_option SS_CONN_OPTS[] = {
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
SSConnOptionNames::ApplicationIntent,
sizeof( SSConnOptionNames::ApplicationIntent ),
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
ODBCConnOptions::ApplicationIntent,
sizeof( ODBCConnOptions::ApplicationIntent ),
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
SSConnOptionNames::AttachDBFileName,
sizeof( SSConnOptionNames::AttachDBFileName ),
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
ODBCConnOptions::AttachDBFileName,
sizeof( ODBCConnOptions::AttachDBFileName ),
CONN_ATTR_STRING,
conn_str_append_func::func
},
{
SSConnOptionNames::CharacterSet,
sizeof( SSConnOptionNames::CharacterSet ),
@ -291,6 +319,15 @@ const connection_option SS_CONN_OPTS[] = {
CONN_ATTR_BOOL,
bool_conn_str_func::func
},
{
SSConnOptionNames::MultiSubnetFailover,
sizeof( SSConnOptionNames::MultiSubnetFailover ),
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
ODBCConnOptions::MultiSubnetFailover,
sizeof( ODBCConnOptions::MultiSubnetFailover ),
CONN_ATTR_BOOL,
bool_conn_str_func::func
},
{
SSConnOptionNames::QuotedId,
sizeof( SSConnOptionNames::QuotedId ),
@ -868,6 +905,19 @@ PHP_FUNCTION( sqlsrv_prepare )
}
if( params_z && Z_TYPE_P( params_z ) != IS_ARRAY ) {
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
}
if( options_z && Z_TYPE_P( options_z ) != IS_ARRAY ) {
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
}
if( sql == NULL ) {
DIE( "sqlsrv_query: sql string was null." );
}
stmt = static_cast<ss_sqlsrv_stmt*>( core_sqlsrv_create_stmt( conn, core::allocate_stmt<ss_sqlsrv_stmt>,
ss_stmt_options_ht, SS_STMT_OPTS,
ss_error_handler, NULL TSRMLS_CC ) );
@ -979,6 +1029,14 @@ PHP_FUNCTION( sqlsrv_query )
validate_stmt_options( *conn, options_z, ss_stmt_options_ht TSRMLS_CC );
}
if( params_z && Z_TYPE_P( params_z ) != IS_ARRAY ) {
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
}
if( options_z && Z_TYPE_P( options_z ) != IS_ARRAY ) {
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
}
if( sql == NULL ) {
DIE( "sqlsrv_query: sql string was null." );

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use connection handles shared between sqlsrv and pdo_sqlsrv
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -43,7 +43,7 @@ const int INFO_BUFFER_LEN = 256;
const char* PROCESSOR_ARCH[] = { "x86", "x64", "ia64" };
// ODBC driver name.
const char CONNECTION_STRING_DRIVER_NAME[] = "Driver={SQL Server Native Client 10.0};";
const char CONNECTION_STRING_DRIVER_NAME[] = "Driver={SQL Server Native Client 11.0};";
// default options if only the server is specified
const char CONNECTION_STRING_DEFAULT_OPTIONS[] = "Mars_Connection={Yes}";
@ -562,6 +562,20 @@ void build_connection_string_and_set_conn_attr( sqlsrv_conn* conn, const char* s
return;
}
// workaround for a bug in ODBC Driver Manager wherein the Driver Manager creates a 0 KB file
// if the TraceFile option is set, even if the "TraceOn" is not present or the "TraceOn"
// flag is set to false.
if( zend_hash_index_exists( options, SQLSRV_CONN_OPTION_TRACE_FILE )) {
zval** trace_value = NULL;
int zr = zend_hash_index_find( options, SQLSRV_CONN_OPTION_TRACE_ON, (void**)&trace_value );
if( zr == FAILURE || !zend_is_true( *trace_value )) {
zend_hash_index_del( options, SQLSRV_CONN_OPTION_TRACE_FILE );
}
}
for( zend_hash_internal_pointer_reset( options );
zend_hash_has_more_elements( options ) == SUCCESS;
zend_hash_move_forward( options )) {
@ -573,10 +587,10 @@ void build_connection_string_and_set_conn_attr( sqlsrv_conn* conn, const char* s
zval** data = NULL;
type = zend_hash_get_current_key_ex( options, &key, &key_len, &index, 0, NULL );
CHECK_CUSTOM_ERROR(( type != HASH_KEY_IS_LONG ), conn, SQLSRV_ERROR_INVALID_OPTION_KEY ) {
throw core::CoreException();
}
// The driver layer should ensure a valid key.
DEBUG_SQLSRV_ASSERT(( type == HASH_KEY_IS_LONG ), "build_connection_string_and_set_conn_attr: invalid connection option key type." );
core::sqlsrv_zend_hash_get_current_data( *conn, options, (void**) &data TSRMLS_CC );
conn_opt = get_connection_option( conn, index, valid_conn_opts TSRMLS_CC );
@ -660,13 +674,14 @@ void determine_server_version( sqlsrv_conn* conn TSRMLS_DC )
char p[ INFO_BUFFER_LEN ];
core::SQLGetInfo( conn, SQL_DBMS_VER, p, INFO_BUFFER_LEN, &info_len TSRMLS_CC );
errno = 0;
char version_major_str[ 3 ];
SERVER_VERSION version_major;
memcpy( version_major_str, p, 2 );
version_major_str[ 2 ] = '\0';
version_major = static_cast<SERVER_VERSION>( atoi( version_major_str ));
CHECK_CUSTOM_ERROR( version_major == 0 || errno == ERANGE || errno == EINVAL, conn, SQLSRV_ERROR_UNKNOWN_SERVER_VERSION )
CHECK_CUSTOM_ERROR( version_major == 0 && ( errno == ERANGE || errno == EINVAL ), conn, SQLSRV_ERROR_UNKNOWN_SERVER_VERSION )
{
throw core::CoreException();
}

View file

@ -3,7 +3,7 @@
//
// Contents: common initialization routines shared by PDO and sqlsrv
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

1338
sqlsrv/core_results.cpp Normal file
View file

@ -0,0 +1,1338 @@
//---------------------------------------------------------------------------------------------------------------------------------
// File: core_results.cpp
//
// Contents: Result sets
//
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// You may obtain a copy of the License at:
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//---------------------------------------------------------------------------------------------------------------------------------
#include "core_sqlsrv.h"
#include <functional>
#include <iostream>
#include <sstream>
using namespace core;
// conversion matrix
// each entry holds a function that can perform the conversion or NULL which means the conversion isn't supported
// this is initialized the first time the buffered result set is created.
sqlsrv_buffered_result_set::conv_matrix_t sqlsrv_buffered_result_set::conv_matrix;
namespace {
// *** internal types ***
#pragma warning(disable:4200)
// *** internal constants ***
const int INITIAL_FIELD_STRING_LEN = 256; // base allocation size when retrieving a string field
// *** internal functions ***
// return an integral type rounded up to a certain number
template <int align, typename T>
T align_to( T number )
{
DEBUG_SQLSRV_ASSERT( (number + align) > number, "Number to align overflowed" );
return ((number % align) == 0) ? number : (number + align - (number % align));
}
// return a pointer address aligned to a certain address boundary
template <int align, typename T>
T* align_to( T* ptr )
{
size_t p_value = (size_t) ptr;
return align_to<align, size_t>( p_value );
}
// set the nth bit of the bitstream starting at ptr
void set_bit( void* ptr, unsigned int bit )
{
unsigned char* null_bits = reinterpret_cast<unsigned char*>( ptr );
null_bits += bit >> 3;
*null_bits |= 1 << ( 7 - ( bit & 0x7 ));
}
// retrieve the nth bit from the bitstream starting at ptr
bool get_bit( void* ptr, unsigned int bit )
{
unsigned char* null_bits = reinterpret_cast<unsigned char*>( ptr );
null_bits += bit >> 3;
return ((*null_bits & (1 << ( 7 - ( bit & 0x07 )))) != 0);
}
// read in LOB field during buffered result creation
SQLPOINTER read_lob_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_buffered_result_set::meta_data& meta,
unsigned long mem_used TSRMLS_DC );
// dtor for each row in the cache
void cache_row_dtor( void* data );
// convert a number to a string using locales
// There is an extra copy here, but given the size is short (usually <20 bytes) and the complications of
// subclassing a new streambuf just to avoid the copy, it's easier to do the copy
template <typename Char, typename Number>
SQLRETURN number_to_string( Number* number_data, __out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& last_error )
{
std::basic_ostringstream<Char> os;
std::locale loc;
os.imbue( loc );
std::use_facet< std::num_put< Char > >( loc ).put( std::basic_ostream<Char>::_Iter( os.rdbuf() ), os, ' ', *number_data );
std::basic_string<Char>& str_num = os.str();
if( os.fail() ) {
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error(
(SQLCHAR*) "IMSSP", (SQLCHAR*) "Failed to convert number to string", -1 );
return SQL_ERROR;
}
if( str_num.size() * sizeof(Char) + sizeof(Char) > (size_t) buffer_length ) {
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error(
(SQLCHAR*) "HY090", (SQLCHAR*) "Buffer length too small to hold number as string", -1 );
return SQL_ERROR;
}
*out_buffer_length = str_num.size() * sizeof(Char) + sizeof(Char); // include NULL terminator
memcpy( buffer, str_num.c_str(), *out_buffer_length );
return SQL_SUCCESS;
}
template <typename Number, typename Char>
SQLRETURN string_to_number( Char* string_data, SQLLEN str_len, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length, sqlsrv_error_auto_ptr& last_error )
{
Number* number_data = reinterpret_cast<Number*>( buffer );
std::locale loc; // default locale should match system
std::basic_istringstream<Char> is;
is.str( string_data );
is.imbue( loc );
std::ios_base::iostate st = 0;
std::use_facet< std::num_get< Char > >( loc ).get( std::basic_istream<Char>::_Iter( is.rdbuf( ) ),
std::basic_istream<Char>::_Iter(0), is, st, *number_data );
if( st & std::ios_base::failbit ) {
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error(
(SQLCHAR*) "22003", (SQLCHAR*) "Numeric value out of range", 103 );
return SQL_ERROR;
}
*out_buffer_length = sizeof( Number );
return SQL_SUCCESS;
}
// "closure" for the hash table destructor
struct row_dtor_closure {
sqlsrv_buffered_result_set* results;
BYTE* row_data;
row_dtor_closure( sqlsrv_buffered_result_set* st, BYTE* row ) :
results( st ), row_data( row )
{
}
};
sqlsrv_error* odbc_get_diag_rec( sqlsrv_stmt* odbc, SQLSMALLINT record_number )
{
SQLWCHAR wsql_state[ SQL_SQLSTATE_BUFSIZE ];
SQLCHAR* sql_state = reinterpret_cast<SQLCHAR*>( wsql_state );
SQLWCHAR wnative_message[ SQL_MAX_MESSAGE_LENGTH + 1 ];
sqlsrv_malloc_auto_ptr<SQLCHAR> native_message;
SQLINTEGER native_code;
SQLINTEGER message_len;
SQLRETURN r = SQLGetDiagRecW( SQL_HANDLE_STMT, odbc->handle(), record_number, wsql_state, &native_code, wnative_message,
SQL_MAX_MESSAGE_LENGTH + 1, NULL );
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
return NULL;
}
// convert the error into the encoding of the context
SQLSRV_ENCODING enc = odbc->encoding();
if( enc == SQLSRV_ENCODING_DEFAULT ) {
enc = odbc->conn->encoding();
}
// convert the error into the encoding of the context
message_len = SQL_SQLSTATE_BUFSIZE * sizeof(WCHAR);
convert_string_from_utf16( enc, reinterpret_cast<char**>( &sql_state ), message_len,
false /*no free*/ );
message_len = (SQL_MAX_MESSAGE_LENGTH + 1) * sizeof( WCHAR );
native_message = reinterpret_cast<SQLCHAR*>( wnative_message );
convert_string_from_utf16( enc, reinterpret_cast<char**>( &native_message ), message_len,
false /*no free*/ );
return new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) sql_state, (SQLCHAR*) native_message,
native_code );
}
} // namespace
// base class result set
sqlsrv_result_set::sqlsrv_result_set( sqlsrv_stmt* stmt ) :
odbc( stmt )
{
}
// ODBC result set
// This object simply wraps ODBC function calls
sqlsrv_odbc_result_set::sqlsrv_odbc_result_set( sqlsrv_stmt* stmt ) :
sqlsrv_result_set( stmt )
{
}
sqlsrv_odbc_result_set::~sqlsrv_odbc_result_set( void )
{
}
SQLRETURN sqlsrv_odbc_result_set::fetch( SQLSMALLINT orientation, SQLLEN offset TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLFetchScroll( odbc, orientation, offset TSRMLS_CC );
}
SQLRETURN sqlsrv_odbc_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out SQLPOINTER buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLGetData( odbc, field_index, target_type, buffer, buffer_length, out_buffer_length, handle_warning TSRMLS_CC );
}
SQLRETURN sqlsrv_odbc_result_set::get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLGetDiagField( odbc, record_number, diag_identifier, diag_info_buffer, buffer_length,
out_buffer_length TSRMLS_CC );
}
sqlsrv_error* sqlsrv_odbc_result_set::get_diag_rec( SQLSMALLINT record_number )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return odbc_get_diag_rec( odbc, record_number );
}
SQLLEN sqlsrv_odbc_result_set::row_count( TSRMLS_D )
{
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
return core::SQLRowCount( odbc TSRMLS_CC );
}
// Buffered result set
// This class holds a result set in memory
sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS_DC ) :
sqlsrv_result_set( stmt ),
cache(NULL),
col_count(0),
meta(NULL),
current(0),
last_field_index(-1),
read_so_far(0)
{
// 10 is an arbitrary number for now for the initial size of the cache
ALLOC_HASHTABLE( cache );
core::sqlsrv_zend_hash_init( *stmt, cache, 10 /* # of buckets */, NULL /* hashfn */, cache_row_dtor /*dtor*/, 0 /*persistent*/
TSRMLS_CC );
col_count = core::SQLNumResultCols( stmt TSRMLS_CC );
// there is no result set to buffer
if( col_count == 0 ) {
return;
}
SQLULEN null_bytes = ( col_count / 8 ) + 1; // number of bits to reserve at the beginning of each row for NULL flags
meta = static_cast<sqlsrv_buffered_result_set::meta_data*>( sqlsrv_malloc( col_count *
sizeof( sqlsrv_buffered_result_set::meta_data )));
// set up the conversion matrix if this is the first time we're called
if( conv_matrix.size() == 0 ) {
conv_matrix[ SQL_C_CHAR ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::to_same_string;
conv_matrix[ SQL_C_CHAR ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::system_to_wide_string;
conv_matrix[ SQL_C_CHAR ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_binary_string;
conv_matrix[ SQL_C_CHAR ][ SQL_C_DOUBLE ] = &sqlsrv_buffered_result_set::string_to_double;
conv_matrix[ SQL_C_CHAR ][ SQL_C_LONG ] = &sqlsrv_buffered_result_set::string_to_long;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::to_same_string;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_binary_string;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::wide_to_system_string;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_DOUBLE ] = &sqlsrv_buffered_result_set::wstring_to_double;
conv_matrix[ SQL_C_WCHAR ][ SQL_C_LONG ] = &sqlsrv_buffered_result_set::wstring_to_long;
conv_matrix[ SQL_C_BINARY ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_same_string;
conv_matrix[ SQL_C_BINARY ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::binary_to_system_string;
conv_matrix[ SQL_C_BINARY ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::binary_to_wide_string;
conv_matrix[ SQL_C_LONG ][ SQL_C_DOUBLE ] = &sqlsrv_buffered_result_set::long_to_double;
conv_matrix[ SQL_C_LONG ][ SQL_C_LONG ] = &sqlsrv_buffered_result_set::to_long;
conv_matrix[ SQL_C_LONG ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_long;
conv_matrix[ SQL_C_LONG ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::long_to_system_string;
conv_matrix[ SQL_C_LONG ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::long_to_wide_string;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_DOUBLE ] = &sqlsrv_buffered_result_set::to_double;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_BINARY ] = &sqlsrv_buffered_result_set::to_double;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_CHAR ] = &sqlsrv_buffered_result_set::double_to_system_string;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_LONG ] = &sqlsrv_buffered_result_set::double_to_long;
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::double_to_wide_string;
}
// get the meta data and calculate the size of a row buffer
SQLULEN offset = null_bytes;
for( SQLSMALLINT i = 0; i < col_count; ++i ) {
core::SQLDescribeCol( stmt, i + 1, NULL, 0, NULL, &meta[i].type, &meta[i].length, &meta[i].scale, NULL TSRMLS_CC );
offset = align_to<4>( offset );
meta[i].offset = offset;
switch( meta[i].type ) {
// these types are the display size
case SQL_BIGINT:
case SQL_DECIMAL:
case SQL_GUID:
case SQL_NUMERIC:
core::SQLColAttribute( stmt, i + 1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL,
reinterpret_cast<SQLLEN*>( &meta[i].length ) TSRMLS_CC );
meta[i].length += sizeof( char ) + sizeof( SQLULEN ); // null terminator space
offset += meta[i].length;
break;
// these types are the column size
case SQL_BINARY:
case SQL_CHAR:
case SQL_SS_UDT:
case SQL_VARBINARY:
case SQL_VARCHAR:
// var* field types are length prefixed
if( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
offset += sizeof( void* );
}
else {
meta[i].length += sizeof( SQLULEN ) + sizeof( char ); // length plus null terminator space
offset += meta[i].length;
}
break;
case SQL_WCHAR:
case SQL_WVARCHAR:
if( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
offset += sizeof( void* );
}
else {
meta[i].length *= sizeof( WCHAR );
meta[i].length += sizeof( SQLULEN ) + sizeof( WCHAR ); // length plus null terminator space
offset += meta[i].length;
}
break;
// these types are LOBs
case SQL_LONGVARBINARY:
case SQL_LONGVARCHAR:
case SQL_WLONGVARCHAR:
case SQL_SS_XML:
meta[i].length = sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN;
offset += sizeof( void* );
break;
// these types are the ISO date size
case SQL_DATETIME:
case SQL_TYPE_DATE:
case SQL_SS_TIME2:
case SQL_SS_TIMESTAMPOFFSET:
case SQL_TYPE_TIMESTAMP:
core::SQLColAttribute( stmt, i + 1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL,
reinterpret_cast<SQLLEN*>( &meta[i].length ) TSRMLS_CC );
meta[i].length += sizeof(char) + sizeof( SQLULEN ); // null terminator space
offset += meta[i].length;
break;
// these types are the native size
case SQL_BIT:
case SQL_INTEGER:
case SQL_SMALLINT:
case SQL_TINYINT:
meta[i].length = sizeof( long );
offset += meta[i].length;
break;
case SQL_REAL:
case SQL_FLOAT:
meta[i].length = sizeof( double );
offset += meta[i].length;
break;
default:
SQLSRV_ASSERT( false, "Unknown type in sqlsrv_buffered_query::sqlsrv_buffered_query" );
break;
}
switch( meta[i].type ) {
case SQL_BIGINT:
case SQL_CHAR:
case SQL_DATETIME:
case SQL_DECIMAL:
case SQL_GUID:
case SQL_NUMERIC:
case SQL_LONGVARCHAR:
case SQL_TYPE_DATE:
case SQL_SS_TIME2:
case SQL_SS_TIMESTAMPOFFSET:
case SQL_SS_XML:
case SQL_TYPE_TIMESTAMP:
case SQL_VARCHAR:
meta[i].c_type = SQL_C_CHAR;
break;
case SQL_SS_UDT:
case SQL_LONGVARBINARY:
case SQL_BINARY:
case SQL_VARBINARY:
meta[i].c_type = SQL_C_BINARY;
break;
case SQL_WLONGVARCHAR:
case SQL_WCHAR:
case SQL_WVARCHAR:
meta[i].c_type = SQL_C_WCHAR;
break;
case SQL_BIT:
case SQL_INTEGER:
case SQL_SMALLINT:
case SQL_TINYINT:
meta[i].c_type = SQL_C_LONG;
break;
case SQL_REAL:
case SQL_FLOAT:
meta[i].c_type = SQL_C_DOUBLE;
break;
default:
SQLSRV_ASSERT( false, "Unknown type in sqlsrv_buffered_query::sqlsrv_buffered_query" );
break;
}
}
// read the data into the cache
// (offset from the above loop has the size of the row buffer necessary)
unsigned long mem_used = 0;
unsigned long row_count = 0;
while( core::SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 TSRMLS_CC ) != SQL_NO_DATA ) {
// allocate the row buffer
unsigned char* row = static_cast<unsigned char*>( sqlsrv_malloc( offset ));
memset( row, 0, offset );
// read the fields into the row buffer
for( SQLSMALLINT i = 0; i < col_count; ++i ) {
SQLLEN out_buffer_temp = SQL_NULL_DATA;
SQLPOINTER buffer;
SQLLEN* out_buffer_length = &out_buffer_temp;
switch( meta[i].c_type ) {
case SQL_C_CHAR:
case SQL_C_WCHAR:
case SQL_C_BINARY:
if( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
out_buffer_length = &out_buffer_temp;
SQLPOINTER* lob_addr = reinterpret_cast<SQLPOINTER*>( &row[ meta[i].offset ] );
*lob_addr = read_lob_field( stmt, i, meta[i], mem_used TSRMLS_CC );
// a NULL pointer means NULL field
if( *lob_addr == NULL ) {
*out_buffer_length = SQL_NULL_DATA;
}
else {
*out_buffer_length = **reinterpret_cast<SQLLEN**>( lob_addr );
mem_used += *out_buffer_length;
}
}
else {
mem_used += meta[i].length;
CHECK_CUSTOM_ERROR( mem_used > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
buffer = row + meta[i].offset + sizeof( SQLULEN );
out_buffer_length = reinterpret_cast<SQLLEN*>( row + meta[i].offset );
core::SQLGetData( stmt, i + 1, meta[i].c_type, buffer, meta[i].length, out_buffer_length,
false TSRMLS_CC );
}
break;
case SQL_C_LONG:
case SQL_C_DOUBLE:
{
mem_used += meta[i].length;
CHECK_CUSTOM_ERROR( mem_used > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
buffer = row + meta[i].offset;
out_buffer_length = &out_buffer_temp;
core::SQLGetData( stmt, i + 1, meta[i].c_type, buffer, meta[i].length, out_buffer_length,
false TSRMLS_CC );
}
break;
default:
SQLSRV_ASSERT( false, "Unknown C type" );
break;
}
if( *out_buffer_length == SQL_NULL_DATA ) {
unsigned char* null_bits = reinterpret_cast<unsigned char*>( row );
set_bit( row, i );
}
}
SQLSRV_ASSERT( row_count < LONG_MAX, "Hard maximum of 2 billion rows exceeded in a buffered query" );
// add it to the cache
row_dtor_closure cl( this, row );
sqlsrv_zend_hash_next_index_insert( *stmt, cache, &cl, sizeof( cl ) TSRMLS_CC );
}
}
sqlsrv_buffered_result_set::~sqlsrv_buffered_result_set( void )
{
// free the rows
if( cache ) {
zend_hash_destroy( cache );
FREE_HASHTABLE( cache );
cache = NULL;
}
// free the meta data
if( meta ) {
efree( meta );
meta = NULL;
}
}
SQLRETURN sqlsrv_buffered_result_set::fetch( SQLSMALLINT orientation, SQLLEN offset TSRMLS_DC )
{
last_error = NULL;
last_field_index = -1;
read_so_far = 0;
switch( orientation ) {
case SQL_FETCH_NEXT:
offset = 1;
orientation = SQL_FETCH_RELATIVE;
break;
case SQL_FETCH_PRIOR:
offset = -1;
orientation = SQL_FETCH_RELATIVE;
break;
}
switch( orientation ) {
case SQL_FETCH_FIRST:
current = 1;
break;
case SQL_FETCH_LAST:
current = row_count( TSRMLS_C );
break;
case SQL_FETCH_ABSOLUTE:
current = offset;
break;
case SQL_FETCH_RELATIVE:
current += offset;
break;
default:
SQLSRV_ASSERT( false, "Invalid fetch orientation. Should have been caught before here." );
break;
}
// check validity of current row
// the cursor can never get further away than just before the first row
if( current <= 0 && ( offset < 0 || orientation != SQL_FETCH_RELATIVE )) {
current = 0;
return SQL_NO_DATA;
}
// the cursor can never get further away than just after the last row
if( current > row_count( TSRMLS_C ) || ( current <= 0 && offset > 0 ) /*overflow condition*/ ) {
current = row_count( TSRMLS_C ) + 1;
return SQL_NO_DATA;
}
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out SQLPOINTER buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )
{
last_error = NULL;
field_index--; // convert from 1 based to 0 based
SQLSRV_ASSERT( field_index < column_count(), "Invalid field index requested" );
if( field_index != last_field_index ) {
last_field_index = field_index;
read_so_far = 0;
}
unsigned char* row = get_row();
// if the field is null, then return SQL_NULL_DATA
if( get_bit( row, field_index )) {
*out_buffer_length = SQL_NULL_DATA;
return SQL_SUCCESS;
}
// check to make sure the conversion type is valid
if( conv_matrix.find( meta[ field_index ].c_type ) == conv_matrix.end() ||
conv_matrix.find( meta[ field_index ].c_type )->second.find( target_type ) ==
conv_matrix.find( meta[ field_index ].c_type )->second.end() ) {
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "07006",
(SQLCHAR*) "Restricted data type attribute violation", 0 );
return SQL_ERROR;
}
return (( this )->*( conv_matrix[ meta[ field_index ].c_type ][ target_type ] ))( field_index, buffer, buffer_length,
out_buffer_length );
}
SQLRETURN sqlsrv_buffered_result_set::get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC )
{
SQLSRV_ASSERT( record_number == 1, "Only record number 1 can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
SQLSRV_ASSERT( diag_identifier == SQL_DIAG_SQLSTATE,
"Only SQL_DIAG_SQLSTATE can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
SQLSRV_ASSERT( buffer_length >= SQL_SQLSTATE_BUFSIZE,
"Buffer not big enough to return SQLSTATE in sqlsrv_buffered_result_set::get_diag_field" );
if( last_error == NULL ) {
return SQL_NO_DATA;
}
SQLSRV_ASSERT( last_error->sqlstate != NULL,
"Must have a SQLSTATE in a valid last_error in sqlsrv_buffered_result_set::get_diag_field" );
memcpy( diag_info_buffer, last_error->sqlstate, min( buffer_length, SQL_SQLSTATE_BUFSIZE ));
return SQL_SUCCESS;
}
unsigned char* sqlsrv_buffered_result_set::get_row( void )
{
row_dtor_closure* cl_ptr;
int zr = zend_hash_index_find( cache, current - 1, (void**) &cl_ptr );
SQLSRV_ASSERT( zr == SUCCESS, "Failed to find row %1!d! in the cache", current );
return cl_ptr->row_data;
}
sqlsrv_error* sqlsrv_buffered_result_set::get_diag_rec( SQLSMALLINT record_number )
{
// we only hold a single error if there is one, otherwise return the ODBC error(s)
if( last_error == NULL ) {
return odbc_get_diag_rec( odbc, record_number );
}
if( record_number > 1 ) {
return NULL;
}
return new (sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( last_error->sqlstate, last_error->native_message, last_error->native_code );
}
SQLLEN sqlsrv_buffered_result_set::row_count( TSRMLS_D )
{
last_error = NULL;
return zend_hash_num_elements( cache );
}
// private functions
template <typename Char>
SQLRETURN binary_to_string( SQLCHAR* field_data, SQLLEN& read_so_far, __out void* buffer,
SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& out_error )
{
// hex characters for the conversion loop below
static char hex_chars[] = "0123456789ABCDEF";
SQLSRV_ASSERT( out_error == NULL, "Pending error for sqlsrv_buffered_results_set::binary_to_string" );
SQLRETURN r = SQL_ERROR;
// Set the amount of space necessary for null characters at the end of the data.
SQLSMALLINT extra = sizeof(Char);
SQLSRV_ASSERT( ((buffer_length - extra) % (extra * 2)) == 0, "Must be multiple of 2 for binary to system string or "
"multiple of 4 for binary to wide string" );
// all fields will be treated as ODBC returns varchar(max) fields:
// the entire length of the string is returned the first
// call in out_buffer_len. Successive calls return how much is
// left minus how much has already been read by previous reads
// *2 is for each byte to hex conversion and * extra is for either system or wide string allocation
*out_buffer_length = (*reinterpret_cast<SQLLEN*>( field_data - sizeof( SQLULEN )) - read_so_far) * 2 * extra;
// copy as much as we can into the buffer
SQLLEN to_copy;
if( buffer_length < *out_buffer_length + extra ) {
to_copy = (buffer_length - extra);
out_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
r = SQL_SUCCESS_WITH_INFO;
}
else {
r = SQL_SUCCESS;
to_copy = *out_buffer_length;
}
// if there are bytes to copy as hex
if( to_copy > 0 ) {
// quick hex conversion routine
Char* h = reinterpret_cast<Char*>( buffer );
BYTE* b = reinterpret_cast<BYTE*>( field_data );
// to_copy contains the number of bytes to copy, so we divide the number in half (or quarter)
// to get the number of hex digits we can copy
SQLLEN to_copy_hex = to_copy / (2 * extra);
for( int i = 0; i < to_copy_hex; ++i ) {
*h = hex_chars[ (*b & 0xf0) >> 4 ];
h++;
*h = hex_chars[ (*b++ & 0x0f) ];
h++;
}
read_so_far += to_copy_hex;
*h = static_cast<Char>( 0 );
}
else {
reinterpret_cast<char*>( buffer )[0] = '\0';
}
return r;
}
SQLRETURN sqlsrv_buffered_result_set::binary_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
}
else {
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN );
}
return binary_to_string<char>( field_data, read_so_far, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::binary_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLCHAR* row = get_row();
SQLCHAR* field_data = NULL;
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
}
else {
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN );
}
return binary_to_string<WCHAR>( field_data, read_so_far, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::double_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof(LONG), "Buffer length must be able to find a long in "
"sqlsrv_buffered_result_set::double_to_long" );
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
LONG* long_data = reinterpret_cast<LONG*>( buffer );
if( *double_data < double( LONG_MIN ) || *double_data > double( LONG_MAX )) {
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) "22003",
(SQLCHAR*) "Numeric value out of range", 0 );
return SQL_ERROR;
}
if( *double_data != floor( *double_data )) {
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) "01S07",
(SQLCHAR*) "Fractional truncation", 0 );
return SQL_SUCCESS_WITH_INFO;
}
*long_data = static_cast<LONG>( *double_data );
*out_buffer_length = sizeof( LONG );
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::double_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to system string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::double_to_system_string" );
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
return number_to_string<char>( double_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::double_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invalid conversion to wide string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::double_to_wide_string" );
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
return number_to_string<WCHAR>( double_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::long_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof(double), "Buffer length must be able to find a long in sqlsrv_buffered_result_set::double_to_long" );
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( buffer );
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
*double_data = static_cast<LONG>( *long_data );
*out_buffer_length = sizeof( double );
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::long_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to system string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::long_to_system_string" );
unsigned char* row = get_row();
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
return number_to_string<char>( long_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::long_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invalid conversion to wide string" );
SQLSRV_ASSERT( buffer_length > 0, "Buffer length must be > 0 in sqlsrv_buffered_result_set::long_to_wide_string" );
unsigned char* row = get_row();
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
return number_to_string<WCHAR>( long_data, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::string_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_CHAR, "Invalid conversion from string to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer needs to be big enough to hold a double" );
unsigned char* row = get_row();
char* string_data = reinterpret_cast<char*>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
return string_to_number<double>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::wstring_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_WCHAR, "Invalid conversion from wide string to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer needs to be big enough to hold a double" );
unsigned char* row = get_row();
SQLWCHAR* string_data = reinterpret_cast<SQLWCHAR*>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN ) / sizeof( SQLWCHAR );
return string_to_number<double>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::string_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_CHAR, "Invalid conversion from string to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer needs to be big enough to hold a long" );
unsigned char* row = get_row();
char* string_data = reinterpret_cast<char*>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
return string_to_number<LONG>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::wstring_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_WCHAR, "Invalid conversion from wide string to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer needs to be big enough to hold a long" );
unsigned char* row = get_row();
SQLWCHAR* string_data = reinterpret_cast<SQLWCHAR*>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN ) / sizeof( SQLWCHAR );
return string_to_number<LONG>( string_data, meta[ field_index ].length, buffer, buffer_length, out_buffer_length, last_error );
}
SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::system_to_wide_string" );
SQLSRV_ASSERT( buffer_length % 2 == 0, "Odd buffer length passed to sqlsrv_buffered_result_set::system_to_wide_string" );
SQLRETURN r = SQL_ERROR;
unsigned char* row = get_row();
SQLCHAR* field_data = NULL;
SQLULEN field_len = NULL;
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_len = **reinterpret_cast<SQLLEN**>( &row[ meta[ field_index ].offset ] );
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN ) + read_so_far;
}
else {
field_len = *reinterpret_cast<SQLLEN*>( &row[ meta[ field_index ].offset ] );
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN ) + read_so_far;
}
// all fields will be treated as ODBC returns varchar(max) fields:
// the entire length of the string is returned the first
// call in out_buffer_len. Successive calls return how much is
// left minus how much has already been read by previous reads
*out_buffer_length = (*reinterpret_cast<SQLLEN*>( field_data - sizeof( SQLULEN )) - read_so_far) * sizeof(WCHAR);
// to_copy is the number of characters to copy, not including the null terminator
// supposedly it will never happen that a Windows MBCS will explode to UTF-16 surrogate pair.
SQLLEN to_copy;
if( (size_t) buffer_length < (field_len - read_so_far + sizeof(char)) * sizeof(WCHAR)) {
to_copy = (buffer_length - sizeof(WCHAR)) / sizeof(WCHAR); // to_copy is the number of characters
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
r = SQL_SUCCESS_WITH_INFO;
}
else {
r = SQL_SUCCESS;
to_copy = field_len - read_so_far;
}
if( to_copy > 0 ) {
bool tried_again = false;
do {
int ch_space = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS, (LPCSTR) field_data, to_copy,
(LPWSTR) buffer, to_copy );
if( ch_space == 0 ) {
switch( GetLastError() ) {
case ERROR_NO_UNICODE_TRANSLATION:
// the theory here is the conversion failed because the end of the buffer we provided contained only
// half a character at the end
if( !tried_again ) {
to_copy--;
tried_again = true;
continue;
}
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "IMSSP", (SQLCHAR*) "Invalid Unicode translation", -1 );
break;
default:
SQLSRV_ASSERT( false, "Severe error translating Unicode" );
break;
}
return SQL_ERROR;
}
((WCHAR*)buffer)[ to_copy ] = L'\0';
read_so_far += to_copy;
break;
} while( true );
}
else {
reinterpret_cast<WCHAR*>( buffer )[0] = L'\0';
}
return r;
}
SQLRETURN sqlsrv_buffered_result_set::to_same_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::to_same_string" );
SQLRETURN r = SQL_ERROR;
unsigned char* row = get_row();
// Set the amount of space necessary for null characters at the end of the data.
SQLSMALLINT extra = 0;
switch( meta[ field_index ].c_type ) {
case SQL_C_WCHAR:
extra = sizeof( SQLWCHAR );
break;
case SQL_C_BINARY:
extra = 0;
break;
case SQL_C_CHAR:
extra = sizeof( SQLCHAR );
break;
default:
SQLSRV_ASSERT( false, "Invalid type in get_string_data" );
break;
}
SQLCHAR* field_data = NULL;
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN );
}
else {
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN );
}
// all fields will be treated as ODBC returns varchar(max) fields:
// the entire length of the string is returned the first
// call in out_buffer_len. Successive calls return how much is
// left minus how much has already been read by previous reads
*out_buffer_length = *reinterpret_cast<SQLLEN*>( field_data - sizeof( SQLULEN )) - read_so_far;
// copy as much as we can into the buffer
SQLLEN to_copy;
if( buffer_length < *out_buffer_length + extra ) {
to_copy = buffer_length - extra;
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
r = SQL_SUCCESS_WITH_INFO;
}
else {
r = SQL_SUCCESS;
to_copy = *out_buffer_length;
}
SQLSRV_ASSERT( to_copy >= 0, "Negative field length calculated in buffered result set" );
if( to_copy > 0 ) {
memcpy( buffer, field_data + read_so_far, to_copy );
read_so_far += to_copy;
}
if( extra ) {
OACR_WARNING_SUPPRESS( 26001, "Buffer length verified above" );
memcpy( reinterpret_cast<SQLCHAR*>( buffer ) + to_copy, L"\0", extra );
}
return r;
}
SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( last_error == NULL, "Pending error for sqlsrv_buffered_results_set::wide_to_system_string" );
SQLRETURN r = SQL_ERROR;
unsigned char* row = get_row();
SQLCHAR* field_data = NULL;
SQLULEN field_len = NULL;
// if this is the first time called for this field, just convert the entire string to system first then
// use that to read from instead of converting chunk by chunk. This is because it's impossible to know
// the total length of the string for output_buffer_length without doing the conversion and returning
// SQL_NO_TOTAL is not consistent with what our other conversion functions do (system_to_wide_string and
// to_same_string).
if( read_so_far == 0 ) {
if( meta[ field_index ].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
field_len = **reinterpret_cast<SQLLEN**>( &row[ meta[ field_index ].offset ] );
field_data = *reinterpret_cast<SQLCHAR**>( &row[ meta[ field_index ].offset ] ) + sizeof( SQLULEN ) + read_so_far;
}
else {
field_len = *reinterpret_cast<SQLLEN*>( &row[ meta[ field_index ].offset ] );
field_data = &row[ meta[ field_index ].offset ] + sizeof( SQLULEN ) + read_so_far;
}
BOOL default_char_used = FALSE;
char default_char = '?';
// allocate enough to handle WC -> DBCS conversion if it happens
temp_string = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( field_len, sizeof( char ), sizeof(char)));
temp_length = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR) field_data, field_len / sizeof(WCHAR),
(LPSTR) temp_string.get(), field_len, &default_char, &default_char_used );
if( temp_length == 0 ) {
switch( GetLastError() ) {
case ERROR_NO_UNICODE_TRANSLATION:
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "IMSSP", (SQLCHAR*) "Invalid Unicode translation", -1 );
break;
default:
SQLSRV_ASSERT( false, "Severe error translating Unicode" );
break;
}
return SQL_ERROR;
}
}
*out_buffer_length = (temp_length - read_so_far);
SQLLEN to_copy = 0;
if( (size_t) buffer_length < (temp_length - read_so_far + sizeof(char))) {
to_copy = buffer_length - sizeof(char);
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
r = SQL_SUCCESS_WITH_INFO;
}
else {
to_copy = (temp_length - read_so_far);
r = SQL_SUCCESS;
}
if( to_copy > 0 ) {
memcpy( buffer, temp_string.get() + read_so_far, to_copy );
}
SQLSRV_ASSERT( to_copy >= 0, "Invalid field copy length" );
OACR_WARNING_SUPPRESS( BUFFER_UNDERFLOW, "Buffer length verified above" );
((SQLCHAR*) buffer)[ to_copy ] = '\0';
read_so_far += to_copy;
return r;
}
SQLRETURN sqlsrv_buffered_result_set::to_binary_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
return to_same_string( field_index, buffer, buffer_length, out_buffer_length );
}
SQLRETURN sqlsrv_buffered_result_set::to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_LONG, "Invlid conversion to long" );
SQLSRV_ASSERT( buffer_length >= sizeof( LONG ), "Buffer too small for SQL_C_LONG" ); // technically should ignore this
unsigned char* row = get_row();
LONG* long_data = reinterpret_cast<LONG*>( &row[ meta[ field_index ].offset ] );
memcpy( buffer, long_data, sizeof( LONG ));
*out_buffer_length = sizeof( LONG );
return SQL_SUCCESS;
}
SQLRETURN sqlsrv_buffered_result_set::to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length )
{
SQLSRV_ASSERT( meta[ field_index ].c_type == SQL_C_DOUBLE, "Invlid conversion to double" );
SQLSRV_ASSERT( buffer_length >= sizeof( double ), "Buffer too small for SQL_C_DOUBLE" ); // technically should ignore this
unsigned char* row = get_row();
double* double_data = reinterpret_cast<double*>( &row[ meta[ field_index ].offset ] );
memcpy( buffer, double_data, sizeof( double ));
*out_buffer_length = sizeof( double );
return SQL_SUCCESS;
}
namespace {
// called for each row in the cache when the cache is destroyed in the destructor
void cache_row_dtor( void* data )
{
row_dtor_closure* cl = reinterpret_cast<row_dtor_closure*>( data );
BYTE* row = cl->row_data;
// don't release this here, since this is called from the destructor of the result_set
sqlsrv_buffered_result_set* result_set = cl->results;
for( SQLSMALLINT i = 0; i < result_set->column_count(); ++i ) {
if( result_set->col_meta_data(i).length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
void* out_of_row_data = *reinterpret_cast<void**>( &row[ result_set->col_meta_data(i).offset ] );
sqlsrv_free( out_of_row_data );
}
}
sqlsrv_free( row );
}
SQLPOINTER read_lob_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_buffered_result_set::meta_data& meta,
unsigned long mem_used TSRMLS_DC )
{
SQLSMALLINT extra = 0;
SQLLEN* output_buffer_len = NULL;
// Set the amount of space necessary for null characters at the end of the data.
switch( meta.c_type ) {
case SQL_C_WCHAR:
extra = sizeof( SQLWCHAR );
break;
case SQL_C_BINARY:
extra = 0;
break;
case SQL_C_CHAR:
extra = sizeof( SQLCHAR );
break;
default:
SQLSRV_ASSERT( false, "Invalid type in read_lob_field" );
break;
}
SQLLEN already_read = 0;
SQLLEN to_read = INITIAL_FIELD_STRING_LEN;
sqlsrv_malloc_auto_ptr<char> buffer;
buffer = static_cast<char*>( sqlsrv_malloc( INITIAL_FIELD_STRING_LEN + extra + sizeof( SQLULEN )));
SQLRETURN r = SQL_SUCCESS;
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
SQLLEN last_field_len = 0;
bool full_length_returned = false;
do {
output_buffer_len = reinterpret_cast<SQLLEN*>( buffer.get() );
r = core::SQLGetData( stmt, field_index + 1, meta.c_type, buffer.get() + already_read + sizeof( SQLULEN ),
to_read - already_read + extra, &last_field_len, false /*handle_warning*/ TSRMLS_CC );
// if the field is NULL, then return a NULL pointer
if( last_field_len == SQL_NULL_DATA ) {
return NULL;
}
// if the last read was successful, we're done
if( r == SQL_SUCCESS ) {
// check to make sure we haven't overflown our memory limit
CHECK_CUSTOM_ERROR( mem_used + last_field_len > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
break;
}
// else if it wasn't the truncated warning (01004) then we're done
else if( r == SQL_SUCCESS_WITH_INFO ) {
SQLSMALLINT len;
core::SQLGetDiagField( stmt, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len
TSRMLS_CC );
if( !is_truncated_warning( state )) {
break;
}
}
SQLSRV_ASSERT( SQL_SUCCEEDED( r ), "Unknown SQL error not triggered" );
// if the type of the field returns the total to be read, we use that and preallocate the buffer
if( last_field_len != SQL_NO_TOTAL ) {
CHECK_CUSTOM_ERROR( mem_used + last_field_len > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
already_read += to_read - already_read;
to_read = last_field_len;
buffer.resize( to_read + extra + sizeof( SQLULEN ));
output_buffer_len = reinterpret_cast<SQLLEN*>( buffer.get() );
// record the size of the field since we have it available
*output_buffer_len = last_field_len;
full_length_returned = true;
}
// otherwise allocate another chunk of memory to read in
else {
already_read += to_read - already_read;
to_read *= 2;
CHECK_CUSTOM_ERROR( mem_used + to_read > stmt->buffered_query_limit * 1024, stmt,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
throw core::CoreException();
}
buffer.resize( to_read + extra + sizeof( SQLULEN ));
output_buffer_len = reinterpret_cast<SQLLEN*>( buffer.get() );
}
} while( true );
SQLSRV_ASSERT( output_buffer_len != NULL, "Output buffer not allocated properly" );
// most LOB field types return the total length in the last_field_len, but some field types such as XML
// only return the amount read on the last read
if( !full_length_returned ) {
*output_buffer_len = already_read + last_field_len;
}
char* return_buffer = buffer;
buffer.transferred();
return return_buffer;
}
}

View file

@ -6,7 +6,7 @@
//
// Contents: Core routines and constants shared by the Microsoft Drivers for PHP for SQL Server
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -45,6 +45,10 @@ OACR_WARNING_DISABLE( INDEX_NEGATIVE, "Third party code." )
OACR_WARNING_DISABLE( UNANNOTATED_BUFFER, "Third party code." )
OACR_WARNING_DISABLE( INDEX_UNDERFLOW, "Third party code." )
OACR_WARNING_DISABLE( REALLOCLEAK, "Third party code." )
OACR_WARNING_DISABLE( ALLOC_SIZE_OVERFLOW_WITH_ACCESS, "Third party code." )
#else
// define to eliminate static analysis hints in the code
#define OACR_WARNING_SUPPRESS( warning, msg )
#endif
extern "C" {
@ -88,8 +92,6 @@ OACR_WARNING_POP
#include <sql.h>
#include <sqlext.h>
#include <deque>
#if !defined(WC_ERR_INVALID_CHARS)
// imported from winnls.h as it isn't included by 5.3.0
#define WC_ERR_INVALID_CHARS 0x00000080 // error for invalid chars
@ -101,8 +103,10 @@ OACR_WARNING_POP
#undef inline
#endif
#include <deque>
#include <map>
#include <algorithm>
#include <limits>
#include <cassert>
#include <strsafe.h>
@ -216,10 +220,46 @@ struct sqlsrv_static_assert<true> { static const int value = 1; };
#define SQLSRV_STATIC_ASSERT( c ) (sqlsrv_static_assert<(c) != 0>() )
//*********************************************************************************************************************************
// Logging
//*********************************************************************************************************************************
// log_callback
// a driver specific callback for logging messages
// severity - severity of the message: notice, warning, or error
// msg - the message to log in a FormatMessage style formatting
// print_args - args to the message
typedef void (*log_callback)( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
// each driver must register a log callback. This should be the first thing a driver does.
void core_sqlsrv_register_logger( log_callback );
// a simple wrapper around a PHP error logging function.
void write_to_log( unsigned int severity TSRMLS_DC, const char* msg, ... );
// a macro to make it convenient to use the function.
#define LOG( severity, msg, ...) write_to_log( severity TSRMLS_CC, msg, __VA_ARGS__ )
// mask for filtering which severities are written to the log
enum logging_severity {
SEV_ERROR = 0x01,
SEV_WARNING = 0x02,
SEV_NOTICE = 0x04,
SEV_ALL = -1,
};
// Kill the PHP process and log the message to PHP
void die( const char* msg, ... );
#define DIE( msg, ... ) { die( msg, __VA_ARGS__ ); }
//*********************************************************************************************************************************
// Resource/Memory Management
//*********************************************************************************************************************************
// the macro max is defined and overrides the call to max in the allocator class
#pragma push_macro( "max" )
#undef max
// new memory allocation/free debugging facilities to help us verify that all allocations are being
// released in a timely manner and not just at the end of the script.
// Zend has memory logging and checking, but it can generate a lot of noise for just one extension.
@ -229,36 +269,89 @@ struct sqlsrv_static_assert<true> { static const int value = 1; };
// #define SQLSRV_MEM_DEBUG 1
#if defined( PHP_DEBUG ) && !defined( ZTS ) && defined( SQLSRV_MEM_DEBUG )
// macro to log memory allocation and frees locations and their sizes
inline void* emalloc_trace( size_t size, const char* file, int line )
inline void* sqlsrv_malloc_trace( size_t size, const char* file, int line )
{
void* ptr = emalloc( size );
LOG( SEV_NOTICE, "emalloc returned %4!08x!: %1!d! bytes at %2!s!:%3!d!", size, file, line, ptr );
return ptr;
}
inline void* erealloc_trace( void* original, size_t size, const char* file, int line )
inline void* sqlsrv_malloc_trace( size_t element_count, size_t element_size, size_t extra, const char* file, int line )
{
OACR_WARNING_SUPPRESS( ALLOC_SIZE_OVERFLOW_IN_ALLOC_WRAPPER, "Overflow verified below" );
if(( element_count > 0 && element_size > 0 ) &&
( element_count > element_size * element_count || element_size > element_size * element_count )) {
DIE( "Integer overflow in sqlsrv_malloc" );
}
if( element_size * element_count > element_size * element_count + extra ) {
DIE( "Integer overflow in sqlsrv_malloc" );
}
if( element_size * element_count + extra == 0 ) {
DIE( "Allocation size must be more than 0" );
}
void* ptr = emalloc( element_size * element_count + extra );
LOG( SEV_NOTICE, "emalloc returned %4!08x!: %1!d! bytes at %2!s!:%3!d!", size, file, line, ptr );
return ptr;
}
inline void* sqlsrv_realloc_trace( void* buffer, size_t size, const char* file, int line )
{
void* ptr = erealloc( original, size );
LOG( SEV_NOTICE, "erealloc returned %5!08x! from %4!08x!: %1!d! bytes at %2!s!:%3!d!", size, file, line, ptr, original );
return ptr;
}
inline void efree_trace( void* ptr, const char* file, int line )
inline void sqlsrv_free_trace( void* ptr, const char* file, int line )
{
LOG( SEV_NOTICE, "efree %1!08x! at %2!s!:%3!d!", ptr, file, line );
efree( ptr );
}
#define sqlsrv_malloc( size ) emalloc_trace( size, __FILE__, __LINE__ )
#define sqlsrv_realloc( buffer, size ) erealloc_trace( buffer, size, __FILE__, __LINE__ )
#define sqlsrv_free( ptr ) efree_trace( ptr, __FILE__, __LINE__ )
#define sqlsrv_malloc( size ) sqlsrv_malloc_trace( size, __FILE__, __LINE__ )
#define sqlsrv_malloc( count, size, extra ) sqlsrv_malloc_trace( count, size, extra, __FILE__, __LINE__ )
#define sqlsrv_realloc( buffer, size ) sqlsrv_realloc_trace( buffer, size, __FILE__, __LINE__ )
#define sqlsrv_free( ptr ) sqlsrv_free_trace( ptr, __FILE__, __LINE__ )
#else
#define sqlsrv_malloc( size ) emalloc( size )
#define sqlsrv_realloc( buffer, size ) erealloc( buffer, size )
#define sqlsrv_free( ptr ) efree( ptr )
inline void* sqlsrv_malloc( size_t size )
{
return emalloc( size );
}
inline void* sqlsrv_malloc( size_t element_count, size_t element_size, size_t extra )
{
OACR_WARNING_SUPPRESS( ALLOC_SIZE_OVERFLOW_IN_ALLOC_WRAPPER, "Overflow verified below" );
if(( element_count > 0 && element_size > 0 ) &&
( element_count > element_size * element_count || element_size > element_size * element_count )) {
DIE( "Integer overflow in sqlsrv_malloc" );
}
if( element_size * element_count > element_size * element_count + extra ) {
DIE( "Integer overflow in sqlsrv_malloc" );
}
if( element_size * element_count + extra == 0 ) {
DIE( "Allocation size must be more than 0" );
}
return emalloc( element_size * element_count + extra );
}
inline void* sqlsrv_realloc( void* buffer, size_t size )
{
return erealloc( buffer, size );
}
inline void sqlsrv_free( void* ptr )
{
efree( ptr );
}
#endif
@ -273,6 +366,84 @@ struct remove_const<const T*> {
typedef T* type;
};
// allocator that uses the zend memory manager to manage memory
// this allows us to use STL classes that still work with Zend objects
template<typename T>
struct sqlsrv_allocator {
// typedefs used by the STL classes
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
// conversion typedef (used by list and other STL classes)
template<typename U>
struct rebind {
typedef sqlsrv_allocator<U> other;
};
inline sqlsrv_allocator() {}
inline ~sqlsrv_allocator() {}
inline sqlsrv_allocator( sqlsrv_allocator const& ) {}
template<typename U>
inline sqlsrv_allocator( sqlsrv_allocator<U> const& ) {}
// address (doesn't work if the class defines operator&)
inline pointer address( reference r )
{
return &r;
}
inline const_pointer address( const_reference r )
{
return &r;
}
// memory allocation/deallocation
inline pointer allocate( size_type cnt,
typename std::allocator<void>::const_pointer = 0 )
{
return reinterpret_cast<pointer>( sqlsrv_malloc(cnt, sizeof (T), 0));
}
inline void deallocate( pointer p, size_type )
{
sqlsrv_free(p);
}
// size
inline size_type max_size( void ) const
{
return std::numeric_limits<size_type>::max() / sizeof(T);
}
// object construction/destruction
inline void construct( pointer p, const T& t )
{
new(p) T(t);
}
inline void destroy(pointer p)
{
p->~T();
}
// equality operators
inline bool operator==( sqlsrv_allocator const& )
{
return true;
}
inline bool operator!=( sqlsrv_allocator const& a )
{
return !operator==(a);
}
};
// base class for auto_ptrs that we define below. It provides common operators and functions
// used by all the classes.
@ -398,6 +569,8 @@ protected:
// in a variable of sqlsrv_malloc_auto_ptr. sqlsrv_malloc_auto_ptr will "own" that block and assure that it is
// freed until the variable is destroyed (out of scope) or ownership is transferred using the function
// "transferred".
// DO NOT CALL sqlsrv_realloc with a sqlsrv_malloc_auto_ptr. Use the resize member function.
template <typename T>
class sqlsrv_malloc_auto_ptr : public sqlsrv_auto_ptr<T, sqlsrv_malloc_auto_ptr<T> > {
@ -432,6 +605,13 @@ public:
src.transferred();
this->_ptr = p;
}
// DO NOT CALL sqlsrv_realloc with a sqlsrv_malloc_auto_ptr. Use the resize member function.
// has the same parameter list as sqlsrv_realloc: new_size is the size in bytes of the newly allocated buffer
void resize( size_t new_size )
{
_ptr = reinterpret_cast<T*>( sqlsrv_realloc( _ptr, new_size ));
}
};
@ -507,6 +687,9 @@ private:
zval_auto_ptr( const zval_auto_ptr& src );
};
#pragma pop_macro( "max" )
//*********************************************************************************************************************************
// sqlsrv_error
//*********************************************************************************************************************************
@ -546,6 +729,11 @@ struct sqlsrv_error : public sqlsrv_error_const {
format = printf_format;
}
sqlsrv_error( sqlsrv_error_const const& prototype )
{
sqlsrv_error( prototype.sqlstate, prototype.native_message, prototype.native_code, prototype.format );
}
~sqlsrv_error( void )
{
if( sqlstate != NULL ) {
@ -816,6 +1004,7 @@ enum SQLSRV_STMT_OPTIONS {
SQLSRV_STMT_OPTION_QUERY_TIMEOUT,
SQLSRV_STMT_OPTION_SEND_STREAMS_AT_EXEC,
SQLSRV_STMT_OPTION_SCROLLABLE,
SQLSRV_STMT_OPTION_CLIENT_BUFFER_MAX_SIZE,
// Driver specific connection options
SQLSRV_STMT_OPTION_DRIVER_SPECIFIC = 1000,
@ -825,6 +1014,8 @@ enum SQLSRV_STMT_OPTIONS {
namespace ODBCConnOptions {
const char APP[] = "APP";
const char ApplicationIntent[] = "ApplicationIntent";
const char AttachDBFileName[] = "AttachDbFileName";
const char CharacterSet[] = "CharacterSet";
const char ConnectionPooling[] = "ConnectionPooling";
const char Database[] = "Database";
@ -832,6 +1023,7 @@ const char Encrypt[] = "Encrypt";
const char Failover_Partner[] = "Failover_Partner";
const char LoginTimeout[] = "LoginTimggeout";
const char MARS_ODBC[] = "MARS_Connection";
const char MultiSubnetFailover[] = "MultiSubnetFailover";
const char QuotedId[] = "QuotedId";
const char TraceFile[] = "TraceFile";
const char TraceOn[] = "TraceOn";
@ -861,6 +1053,9 @@ enum SQLSRV_CONN_OPTIONS {
SQLSRV_CONN_OPTION_TRANS_ISOLATION,
SQLSRV_CONN_OPTION_TRUST_SERVER_CERT,
SQLSRV_CONN_OPTION_WSID,
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
SQLSRV_CONN_OPTION_MULTI_SUBNET_FAILOVER,
// Driver specific connection options
SQLSRV_CONN_OPTION_DRIVER_SPECIFIC = 1000,
@ -963,6 +1158,11 @@ struct stmt_option_send_at_exec : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* opt, zval* value_z TSRMLS_DC );
};
struct stmt_option_buffered_query_limit : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* opt, zval* value_z TSRMLS_DC );
};
// used to hold the table for statment options
struct stmt_option {
@ -1029,25 +1229,28 @@ struct sqlsrv_output_param {
}
};
// forward decls
struct sqlsrv_result_set;
// *** Statement resource structure ***
struct sqlsrv_stmt : public sqlsrv_context {
void free_param_data( TSRMLS_D );
virtual void new_result_set( void );
virtual void new_result_set( TSRMLS_D );
sqlsrv_conn* conn; // Connection that created this statement
bool executed; // Whether the statement has been executed yet (used for error messages)
bool past_fetch_end; // Core_sqlsrv_fetch sets this field when the statement goes beyond the last row
bool scrollable; // Determines if the statement was created with the Scrollable query attribute
// (don't have to use ODBC to find out)
bool scroll_is_dynamic; // if scrollable, is it a dynamic cursor.
sqlsrv_result_set* current_results; // Current result set
SQLULEN cursor_type; // Type of cursor for the current result set
bool has_rows; // Has_rows is set if there are actual rows in the row set
bool fetch_called; // Used by core_sqlsrv_get_field to return an informative error if fetch not yet called
int last_field_index; // last field retrieved by core_sqlsrv_get_field
bool past_next_result_end; // core_sqlsrv_next_result sets this to true when the statement goes beyond the
// last results
unsigned long query_timeout; // maximum allowed statement execution time
unsigned long buffered_query_limit; // maximum allowed memory for a buffered query (measured in KB)
// holds output pointers for SQLBindParameter
// We use a deque because it 1) provides the at/[] access in constant time, and 2) grows dynamically without moving
@ -1101,6 +1304,9 @@ const int SQLSRV_DEFAULT_SIZE = -1; // size given for an output parameter th
// uninitialized query timeout value
const unsigned int QUERY_TIMEOUT_INVALID = 0xffffffff;
// special buffered query constant
const size_t SQLSRV_CURSOR_BUFFERED = 0xfffffffeUL; // arbitrary number that doesn't map to any other SQL_CURSOR_* constant
// factory to create a statement
typedef sqlsrv_stmt* (*driver_stmt_factory)( sqlsrv_conn* conn, SQLHANDLE h, error_callback e, void* drv TSRMLS_DC );
@ -1117,42 +1323,181 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
__out void** field_value, __out SQLLEN* field_length, bool cache_field,
__out SQLSRV_PHPTYPE *sqlsrv_php_type_out TSRMLS_DC );
bool core_sqlsrv_has_any_result( sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params = true );
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params = true, bool throw_on_errors = true );
void core_sqlsrv_post_param( sqlsrv_stmt* stmt, unsigned int paramno, zval* param_z TSRMLS_DC );
void core_sqlsrv_set_scrollable( sqlsrv_stmt* stmt, unsigned int cursor_type TSRMLS_DC );
void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, long timeout TSRMLS_DC );
void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
void core_sqlsrv_set_send_at_exec( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, long limit TSRMLS_DC );
//*********************************************************************************************************************************
// Logging
// Result Set
//*********************************************************************************************************************************
// log_callback
// a driver specific callback for logging messages
// severity - severity of the message: notice, warning, or error
// msg - the message to log in a FormatMessage style formatting
// print_args - args to the message
typedef void (*log_callback)( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
// each driver must register a log callback. This should be the first thing a driver does.
void core_sqlsrv_register_logger( log_callback );
// Abstract the result set so that a result set can either be used as is from ODBC or buffered.
// This is not a complete abstraction of a result set. Only enough is abstracted to allow for
// information and capabilities normally not available when a result set is not buffered
// (e.g., forward only vs buffered means row count is available and cursor movement is possible).
// Otherwise, normal ODBC calls are still valid and should be used to get information about the
// result set (e.g., SQLNumResultCols).
// a simple wrapper around a PHP error logging function.
void write_to_log( unsigned int severity TSRMLS_DC, const char* msg, ... );
struct sqlsrv_result_set {
// a macro to make it convenient to use the function.
#define LOG( severity, msg, ...) write_to_log( severity TSRMLS_CC, msg, __VA_ARGS__ )
sqlsrv_stmt* odbc;
// mask for filtering which severities are written to the log
enum logging_severity {
SEV_ERROR = 0x01,
SEV_WARNING = 0x02,
SEV_NOTICE = 0x04,
SEV_ALL = -1,
explicit sqlsrv_result_set( sqlsrv_stmt* );
virtual ~sqlsrv_result_set( void ) { }
virtual bool cached( int field_index ) = 0;
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC ) = 0;
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC )= 0;
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC ) = 0;
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number ) = 0;
virtual SQLLEN row_count( TSRMLS_D ) = 0;
};
struct sqlsrv_odbc_result_set : public sqlsrv_result_set {
explicit sqlsrv_odbc_result_set( sqlsrv_stmt* );
virtual ~sqlsrv_odbc_result_set( void );
virtual bool cached( int field_index ) { return false; }
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC );
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC );
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC );
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number );
virtual SQLLEN row_count( TSRMLS_D );
private:
// prevent invalid instantiations and assignments
sqlsrv_odbc_result_set( void );
sqlsrv_odbc_result_set( sqlsrv_odbc_result_set& );
sqlsrv_odbc_result_set& operator=( sqlsrv_odbc_result_set& );
};
struct sqlsrv_buffered_result_set : public sqlsrv_result_set {
struct meta_data {
SQLSMALLINT type;
SQLSMALLINT c_type; // convenience
SQLULEN offset; // in bytes
SQLULEN length; // in bytes
SQLSMALLINT scale;
static const SQLULEN SIZE_UNKNOWN = 0;
};
// default maximum amount of memory that a buffered query can consume
#define INI_BUFFERED_QUERY_LIMIT_DEFAULT "10240" // default used by the php.ini settings
static const unsigned long BUFFERED_QUERY_LIMIT_DEFAULT = 10240; // measured in KB
static const long BUFFERED_QUERY_LIMIT_INVALID = 0;
explicit sqlsrv_buffered_result_set( sqlsrv_stmt* odbc TSRMLS_DC );
virtual ~sqlsrv_buffered_result_set( void );
virtual bool cached( int field_index ) { return true; }
virtual SQLRETURN fetch( SQLSMALLINT fetch_orientation, SQLLEN fetch_offset TSRMLS_DC );
virtual SQLRETURN get_data( SQLUSMALLINT field_index, SQLSMALLINT target_type,
__out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length,
bool handle_warning TSRMLS_DC );
virtual SQLRETURN get_diag_field( SQLSMALLINT record_number, SQLSMALLINT diag_identifier,
__out SQLPOINTER diag_info_buffer, SQLSMALLINT buffer_length,
__out SQLSMALLINT* out_buffer_length TSRMLS_DC );
virtual sqlsrv_error* get_diag_rec( SQLSMALLINT record_number );
virtual SQLLEN row_count( TSRMLS_D );
// buffered result set specific
SQLSMALLINT column_count( void )
{
return col_count;
}
struct meta_data& col_meta_data( SQLSMALLINT i )
{
return meta[i];
}
private:
// prevent invalid instantiations and assignments
sqlsrv_buffered_result_set( void );
sqlsrv_buffered_result_set( sqlsrv_buffered_result_set& );
sqlsrv_buffered_result_set& operator=( sqlsrv_buffered_result_set& );
HashTable* cache; // rows of data kept in index based hash table
SQLSMALLINT col_count; // number of columns in the current result set
meta_data* meta; // metadata for fields in the cache
SQLLEN current; // 1 based, 0 means before first row
sqlsrv_error_auto_ptr last_error; // if an error occurred, it is kept here
SQLUSMALLINT last_field_index; // the last field data retrieved from
SQLLEN read_so_far; // position within string to read from (for partial reads of strings)
sqlsrv_malloc_auto_ptr<SQLCHAR> temp_string; // temp buffer to hold a converted field while in use
SQLLEN temp_length; // number of bytes in the temp conversion buffer
typedef SQLRETURN (sqlsrv_buffered_result_set::*conv_fn)( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
typedef std::map< SQLINTEGER, std::map< SQLINTEGER, conv_fn > > conv_matrix_t;
// two dimentional sparse matrix that holds the [from][to] functions that do conversions
static conv_matrix_t conv_matrix;
// string conversion functions
SQLRETURN binary_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN binary_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN system_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN to_binary_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN to_same_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN wide_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
// long conversion functions
SQLRETURN to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length );
SQLRETURN long_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN long_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN long_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
// double conversion functions
SQLRETURN to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length, __out SQLLEN* out_buffer_length );
SQLRETURN double_to_system_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN double_to_wide_string( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN double_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
// string to number conversion functions
// Future: See if these can be converted directly to template member functions
SQLRETURN string_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN string_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN wstring_to_double( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
SQLRETURN wstring_to_long( SQLSMALLINT field_index, __out void* buffer, SQLLEN buffer_length,
__out SQLLEN* out_buffer_length );
// utility functions for conversions
unsigned char* get_row( void );
};
//*********************************************************************************************************************************
// Utility
@ -1205,7 +1550,7 @@ enum SQLSRV_ERROR_CODES {
SQLSRV_ERROR_INVALID_CONNECTION_KEY,
SQLSRV_ERROR_MAX_PARAMS_EXCEEDED,
SQLSRV_ERROR_INVALID_OPTION_KEY,
SQLSRV_ERROR_INVALID_OPTION_VALUE,
SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE,
SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE,
SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE,
SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED,
@ -1215,6 +1560,8 @@ enum SQLSRV_ERROR_CODES {
SQLSRV_ERROR_STREAM_CREATE,
SQLSRV_ERROR_MARS_OFF,
SQLSRV_ERROR_FIELD_INDEX_ERROR,
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED,
SQLSRV_ERROR_INVALID_BUFFER_LIMIT,
// Driver specific error codes starts from here.
SQLSRV_ERROR_DRIVER_SPECIFIC = 1000,
@ -1222,7 +1569,8 @@ enum SQLSRV_ERROR_CODES {
};
// the message returned by SQL Native Client
const char CONNECTION_BUSY_ODBC_ERROR[] = "[Microsoft][SQL Server Native Client 10.0]Connection is busy with results for another command";
const char CONNECTION_BUSY_ODBC_ERROR[] = "[Microsoft][SQL Server Native Client 11.0]Connection is busy with results for "
"another command";
// SQLSTATE for all internal errors
extern SQLCHAR IMSSP[];
@ -1244,11 +1592,12 @@ enum error_handling_flags {
// 2/code) driver specific error code
// 3/message) driver specific error message
// The fetch type determines if the indices are numeric, associative, or both.
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_error* error, logging_severity severity TSRMLS_DC );
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, __out sqlsrv_error_auto_ptr& error,
logging_severity severity TSRMLS_DC );
// format and return a driver specfic error
void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const const* custom_error,
sqlsrv_error* formatted_error, logging_severity severity TSRMLS_DC, va_list* args );
sqlsrv_error_auto_ptr& formatted_error, logging_severity severity TSRMLS_DC, va_list* args );
// return the message for the HRESULT returned by GetLastError. Some driver errors use this to
@ -1278,10 +1627,6 @@ inline bool call_error_handler( sqlsrv_context* ctx, unsigned int sqlsrv_error_c
return ignored;
}
// Kill the PHP process and log the message to PHP
void die( const char* msg, ... );
#define DIE( msg, ... ) { die( msg, __VA_ARGS__ ); }
// PHP equivalent of ASSERT. C asserts cause a dialog to show and halt the process which
// we don't want on a web server
@ -1300,7 +1645,6 @@ void die( const char* msg, ... );
#endif
// check to see if the sqlstate is 01004, truncated field retrieved. Used for retrieving large fields.
inline bool is_truncated_warning( SQLCHAR* state )
{

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use statement handles shared between sqlsrv and pdo_sqlsrv
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -28,8 +28,10 @@ struct field_cache {
void* value;
SQLLEN len;
sqlsrv_phptype type;
field_cache( void* field_value, SQLLEN field_len )
field_cache( void* field_value, SQLLEN field_len, sqlsrv_phptype t )
: type( t )
{
// if the value is NULL, then just record a NULL pointer
if( field_value != NULL ) {
@ -105,7 +107,6 @@ void send_param_streams( sqlsrv_stmt* stmt TSRMLS_DC );
void sqlsrv_output_param_dtor( void* data );
// called when a bound stream parameter is to be destroyed.
void sqlsrv_stream_dtor( void* data );
sqlsrv_phptype sql_type_to_php_type( sqlsrv_stmt const* stmt, SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string );
bool is_streamable_type( SQLINTEGER sql_type );
}
@ -116,7 +117,8 @@ sqlsrv_stmt::sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, vo
conn( c ),
executed( false ),
past_fetch_end( false ),
scrollable( false ),
current_results( NULL ),
cursor_type( SQL_CURSOR_FORWARD_ONLY ),
has_rows( false ),
fetch_called( false ),
last_field_index( -1 ),
@ -126,6 +128,7 @@ sqlsrv_stmt::sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, vo
current_stream( NULL, SQLSRV_ENCODING_DEFAULT ),
current_stream_read( 0 ),
query_timeout( QUERY_TIMEOUT_INVALID ),
buffered_query_limit( sqlsrv_buffered_result_set::BUFFERED_QUERY_LIMIT_INVALID ),
active_stream( NULL )
{
// initialize the input string parameters array (which holds zvals)
@ -165,6 +168,14 @@ sqlsrv_stmt::~sqlsrv_stmt( void )
TSRMLS_FETCH();
close_active_stream( this TSRMLS_CC );
}
// delete any current results
if( current_results ) {
current_results->~sqlsrv_result_set();
efree( current_results );
current_results = NULL;
}
invalidate();
zval_ptr_dtor( &param_input_strings );
zval_ptr_dtor( &output_params );
@ -192,13 +203,28 @@ void sqlsrv_stmt::free_param_data( TSRMLS_D )
// to be called whenever a new result set is created, such as after an
// execute or next_result. Resets the state variables.
void sqlsrv_stmt::new_result_set( void )
void sqlsrv_stmt::new_result_set( TSRMLS_D )
{
this->fetch_called = false;
this->has_rows = false;
this->past_next_result_end = false;
this->past_fetch_end = false;
this->last_field_index = -1;
// delete any current results
if( current_results ) {
current_results->~sqlsrv_result_set();
efree( current_results );
current_results = NULL;
}
// create a new result set
if( cursor_type == SQLSRV_CURSOR_BUFFERED ) {
current_results = new (sqlsrv_malloc( sizeof( sqlsrv_buffered_result_set ))) sqlsrv_buffered_result_set( this TSRMLS_CC );
}
else {
current_results = new (sqlsrv_malloc( sizeof( sqlsrv_odbc_result_set ))) sqlsrv_odbc_result_set( this );
}
}
// core_sqlsrv_create_stmt
@ -247,16 +273,15 @@ sqlsrv_stmt* core_sqlsrv_create_stmt( sqlsrv_conn* conn, driver_stmt_factory stm
int type = zend_hash_get_current_key_ex( options_ht, &key, &key_len, &index, 0, NULL );
// The driver layer should ensure a valid key.
SQLSRV_ASSERT( (type == HASH_KEY_IS_LONG), "allocate_stmt: Invalid statment option key provided" );
DEBUG_SQLSRV_ASSERT(( type == HASH_KEY_IS_LONG ), "allocate_stmt: Invalid statment option key provided." );
core::sqlsrv_zend_hash_get_current_data( *(stmt->conn), options_ht, (void**) &value_z TSRMLS_CC );
const stmt_option* stmt_opt = get_stmt_option( stmt->conn, index, valid_stmt_opts TSRMLS_CC );
// if the key didn't match, then return the error to the script
if( !stmt_opt ) {
THROW_CORE_ERROR( stmt->conn, SQLSRV_ERROR_INVALID_OPTION_KEY );
}
// if the key didn't match, then return the error to the script.
// The driver layer should ensure that the key is valid.
DEBUG_SQLSRV_ASSERT( stmt_opt != NULL, "allocate_stmt: unexpected null value for statement option." );
// perform the actions the statement option needs done.
(*stmt_opt->func)( stmt, stmt_opt, *value_z TSRMLS_CC );
@ -273,6 +298,8 @@ sqlsrv_stmt* core_sqlsrv_create_stmt( sqlsrv_conn* conn, driver_stmt_factory stm
catch( core::CoreException& )
{
if( stmt ) {
conn->set_last_error( stmt->last_error() );
stmt->~sqlsrv_stmt();
}
@ -321,7 +348,7 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
try {
// check is only < because params are 0 based
CHECK_CUSTOM_ERROR( param_num >= SQL_SERVER_MAX_PARAMS, stmt, SQLSRV_ERROR_MAX_PARAMS_EXCEEDED, param_num ) {
CHECK_CUSTOM_ERROR( param_num >= SQL_SERVER_MAX_PARAMS, stmt, SQLSRV_ERROR_MAX_PARAMS_EXCEEDED, param_num + 1 ) {
throw core::CoreException();
}
@ -498,6 +525,27 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
// save the parameter to be adjusted and/or converted after the results are processed
sqlsrv_output_param output_param( param_z, encoding, param_num, buffer_len );
save_output_param_for_later( stmt, output_param TSRMLS_CC );
// For output parameters, if we set the column_size to be same as the buffer_len,
// than if there is a truncation due to the data coming from the server being
// greater than the column_size, we don't get any truncation error. In order to
// avoid this silent truncation, we set the column_size to be "MAX" size for
// string types. This will guarantee that there is no silent truncation for
// output parameters.
if( direction == SQL_PARAM_OUTPUT ) {
switch( sql_type ) {
case SQL_VARBINARY:
case SQL_VARCHAR:
case SQL_WVARCHAR:
column_size = SQL_SS_LENGTH_UNLIMITED;
break;
default:
break;
}
}
}
break;
case IS_RESOURCE:
@ -516,22 +564,33 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
case IS_OBJECT:
{
SQLSRV_ASSERT( direction == SQL_PARAM_INPUT, "Invalid output param type. The driver layer should catch this." );
sqlsrv_malloc_auto_ptr<char> class_name;
zend_uint class_name_len;
zval_auto_ptr function_z;
zval_auto_ptr buffer_z;
zval_auto_ptr format_z;
zval* params[1];
bool valid_class_name_found = false;
int zr = zend_get_object_classname( param_z, &class_name, &class_name_len TSRMLS_CC );
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
CHECK_CUSTOM_ERROR( class_name_len != DateTime::DATETIME_CLASS_NAME_LEN ||
stricmp( class_name, DateTime::DATETIME_CLASS_NAME ),
stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
zend_class_entry *class_entry = zend_get_class_entry( param_z TSRMLS_CC );
while( class_entry != NULL ) {
if( class_entry->name_length == DateTime::DATETIME_CLASS_NAME_LEN && class_entry->name != NULL &&
stricmp( class_entry->name, DateTime::DATETIME_CLASS_NAME ) == 0 ) {
valid_class_name_found = true;
break;
}
else {
// Check the parent
class_entry = class_entry->parent;
}
}
CHECK_CUSTOM_ERROR( !valid_class_name_found, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
ALLOC_INIT_ZVAL( buffer_z );
ALLOC_INIT_ZVAL( function_z );
ALLOC_INIT_ZVAL( format_z );
@ -554,7 +613,7 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
params[0] = format_z;
// This is equivalent to the PHP code: $param_z->format( $format_z ); where param_z is the
// DateTime object and $format_z is the format string.
zr = call_user_function( EG( function_table ), &param_z, function_z, buffer_z, 1, params TSRMLS_CC );
int zr = call_user_function( EG( function_table ), &param_z, function_z, buffer_z, 1, params TSRMLS_CC );
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_num + 1 ) {
throw core::CoreException();
}
@ -602,6 +661,8 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, unsigned int param_num, int dire
void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_len )
{
try {
// close the stream to release the resource
close_active_stream( stmt TSRMLS_CC );
@ -632,7 +693,7 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_
r = core::SQLExecute( stmt TSRMLS_CC );
}
stmt->new_result_set();
stmt->new_result_set( TSRMLS_C );
stmt->executed = true;
// if data is needed (streams were bound) and they should be sent at execute time, then do so now
@ -646,6 +707,19 @@ void core_sqlsrv_execute( sqlsrv_stmt* stmt TSRMLS_DC, const char* sql, int sql_
finalize_output_parameters( stmt TSRMLS_CC );
}
}
catch( core::CoreException& e ) {
// if the statement executed but failed in a subsequent operation before returning,
// we need to cancel the statement
if( stmt->executed ) {
SQLCancel( stmt->handle() );
// stmt->executed = false; should this be reset if something fails?
}
throw e;
}
}
@ -689,20 +763,19 @@ bool core_sqlsrv_fetch( sqlsrv_stmt* stmt, SQLSMALLINT fetch_orientation, SQLLEN
// if the statement has rows and is not scrollable but doesn't yet have
// fetch_called, this must be the first time we've called sqlsrv_fetch.
if( !stmt->scrollable && stmt->has_rows && !stmt->fetch_called ) {
if( stmt->cursor_type == SQL_CURSOR_FORWARD_ONLY && stmt->has_rows && !stmt->fetch_called ) {
stmt->fetch_called = true;
return true;
}
// move to the record requested. For absolute records, we use a 0 based offset, so +1 since
// SQLFetchScroll uses a 1 based offset, otherwise for relative, just use the fetch_offset provided.
SQLRETURN r = core::SQLFetchScroll( stmt, fetch_orientation,
( fetch_orientation == SQL_FETCH_RELATIVE ) ? fetch_offset : fetch_offset + 1
TSRMLS_CC );
SQLRETURN r = stmt->current_results->fetch( fetch_orientation,
( fetch_orientation == SQL_FETCH_RELATIVE ) ? fetch_offset : fetch_offset + 1
TSRMLS_CC );
if( r == SQL_NO_DATA ) {
// if this is a forward only cursor, mark that we've passed the end so future calls result in an error
if( !stmt->scrollable ) {
if( stmt->cursor_type == SQL_CURSOR_FORWARD_ONLY ) {
stmt->past_fetch_end = true;
}
return false;
@ -812,13 +885,18 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
if( cached->value == NULL ) {
*field_value = NULL;
*field_len = 0;
if( sqlsrv_php_type_out ) { *sqlsrv_php_type_out = SQLSRV_PHPTYPE_NULL; }
}
else {
*field_value = sqlsrv_malloc( cached->len + 1 );
*field_value = sqlsrv_malloc( cached->len, sizeof( char ), 1 );
memcpy( *field_value, cached->value, cached->len );
reinterpret_cast<char*>( *field_value )[ cached->len ] = '\0'; // prevent the 'string not null terminated' warning
if( cached->type.typeinfo.type == SQLSRV_PHPTYPE_STRING ) {
// prevent the 'string not null terminated' warning
reinterpret_cast<char*>( *field_value )[ cached->len ] = '\0';
}
*field_len = cached->len;
if( sqlsrv_php_type_out ) { *sqlsrv_php_type_out = static_cast<SQLSRV_PHPTYPE>( cached->type.typeinfo.type ); }
}
return;
}
@ -878,7 +956,7 @@ void core_sqlsrv_get_field( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_
// if the user wants us to cache the field, we'll do it
if( cache_field ) {
field_cache cache( *field_value, *field_len );
field_cache cache( *field_value, *field_len, sqlsrv_php_type );
core::sqlsrv_zend_hash_index_update( *stmt, Z_ARRVAL_P( stmt->field_cache ), field_index, &cache,
sizeof( field_cache ) TSRMLS_CC );
}
@ -913,7 +991,7 @@ bool core_sqlsrv_has_any_result( sqlsrv_stmt* stmt TSRMLS_DC )
// Returns
// Nothing, exception thrown if problem occurs
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params )
void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_params, bool throw_on_errors )
{
try {
@ -928,7 +1006,13 @@ void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_
close_active_stream( stmt TSRMLS_CC );
SQLRETURN r = core::SQLMoreResults( stmt TSRMLS_CC );
SQLRETURN r;
if( throw_on_errors ) {
r = core::SQLMoreResults( stmt TSRMLS_CC );
}
else {
r = SQLMoreResults( stmt->handle() );
}
if( r == SQL_NO_DATA ) {
@ -942,7 +1026,7 @@ void core_sqlsrv_next_result( sqlsrv_stmt* stmt TSRMLS_DC, bool finalize_output_
return;
}
stmt->new_result_set();
stmt->new_result_set( TSRMLS_C );
}
catch( core::CoreException& e ) {
@ -991,42 +1075,62 @@ void core_sqlsrv_set_scrollable( sqlsrv_stmt* stmt, unsigned int cursor_type TSR
case SQL_CURSOR_STATIC:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_STATIC ), SQL_IS_UINTEGER TSRMLS_CC );
stmt->scrollable = true;
stmt->scroll_is_dynamic = false;
break;
case SQL_CURSOR_DYNAMIC:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_DYNAMIC ), SQL_IS_UINTEGER TSRMLS_CC );
stmt->scrollable = true;
stmt->scroll_is_dynamic = true; // this cursor is dynamic
break;
case SQL_CURSOR_KEYSET_DRIVEN:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_KEYSET_DRIVEN ), SQL_IS_UINTEGER TSRMLS_CC );
stmt->scrollable = true;
stmt->scroll_is_dynamic = false;
break;
case SQL_CURSOR_FORWARD_ONLY:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_FORWARD_ONLY ), SQL_IS_UINTEGER TSRMLS_CC );
stmt->scrollable = false; // reset since forward isn't scrollable
stmt->scroll_is_dynamic = false;
break;
case SQLSRV_CURSOR_BUFFERED:
core::SQLSetStmtAttr( stmt, SQL_ATTR_CURSOR_TYPE,
reinterpret_cast<SQLPOINTER>( SQL_CURSOR_FORWARD_ONLY ), SQL_IS_UINTEGER TSRMLS_CC );
break;
default:
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE );
break;
}
stmt->cursor_type = cursor_type;
}
catch( core::CoreException& ) {
throw;
}
}
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
{
if( Z_TYPE_P( value_z ) != IS_LONG ) {
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_BUFFER_LIMIT );
}
core_sqlsrv_set_buffered_query_limit( stmt, Z_LVAL_P( value_z ) TSRMLS_CC );
}
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, long limit TSRMLS_DC )
{
if( limit <= 0 ) {
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_BUFFER_LIMIT );
}
stmt->buffered_query_limit = limit;
}
// Overloaded. Extracts the long value and calls the core_sqlsrv_set_query_timeout
// which accepts timeout parameter as a long. If the zval is not of type long
// than throws error.
@ -1038,7 +1142,7 @@ void core_sqlsrv_set_query_timeout( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC )
if( Z_TYPE_P( value_z ) != IS_LONG || Z_LVAL_P( value_z ) < 0 ) {
convert_to_string( value_z );
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_OPTION_VALUE, Z_STRVAL_P( value_z ) );
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE, Z_STRVAL_P( value_z ) );
}
core_sqlsrv_set_query_timeout( stmt, Z_LVAL_P( value_z ) TSRMLS_CC );
@ -1214,6 +1318,11 @@ void stmt_option_send_at_exec:: operator()( sqlsrv_stmt* stmt, stmt_option const
core_sqlsrv_set_send_at_exec( stmt, value_z TSRMLS_CC );
}
void stmt_option_buffered_query_limit:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
{
core_sqlsrv_set_buffered_query_limit( stmt, value_z TSRMLS_CC );
}
// internal function to release the active stream. Called by each main API function
// that will alter the statement and cancel any retrieval of data from a stream.
@ -1382,9 +1491,13 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
sqlsrv_malloc_auto_ptr<long> field_value_temp;
field_value_temp = static_cast<long*>( sqlsrv_malloc( sizeof( long )));
SQLRETURN r = core::SQLGetData( stmt, field_index + 1, SQL_C_LONG, field_value_temp, 0,
field_len, true /*handle_warning*/ TSRMLS_CC );
SQLRETURN r = stmt->current_results->get_data(field_index + 1, SQL_C_LONG, field_value_temp, sizeof( long ),
field_len, true /*handle_warning*/ TSRMLS_CC );
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
throw core::CoreException();
}
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException();
}
@ -1404,9 +1517,13 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
sqlsrv_malloc_auto_ptr<double> field_value_temp;
field_value_temp = static_cast<double*>( sqlsrv_malloc( sizeof( double )));
SQLRETURN r = core::SQLGetData( stmt, field_index + 1, SQL_C_DOUBLE, field_value_temp, 0,
field_len, true /*handle_warning*/ TSRMLS_CC );
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_DOUBLE, field_value_temp, sizeof( double ),
field_len, true /*handle_warning*/ TSRMLS_CC );
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
throw core::CoreException();
}
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException ();
}
@ -1440,8 +1557,8 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
ALLOC_INIT_ZVAL( function_z );
ALLOC_INIT_ZVAL( return_value_z );
SQLRETURN r = core::SQLGetData( stmt, field_index + 1, SQL_C_CHAR, field_value_temp, MAX_DATETIME_STRING_LEN,
field_len, true TSRMLS_CC );
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_CHAR, field_value_temp,
MAX_DATETIME_STRING_LEN, field_len, true TSRMLS_CC );
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException ();
@ -1512,6 +1629,11 @@ void core_get_field_common( __inout sqlsrv_stmt* stmt, SQLUSMALLINT field_index,
break;
}
case SQLSRV_PHPTYPE_NULL:
*field_value = NULL;
*field_len = 0;
break;
default:
DIE( "core_get_field_common: Unexpected sqlsrv_phptype provided" );
break;
@ -1630,7 +1752,7 @@ SQLSMALLINT default_c_type( sqlsrv_stmt* stmt, unsigned int paramno, zval const*
sql_c_type = SQL_C_CHAR;
break;
}
break;
break;
case IS_BOOL:
case IS_LONG:
sql_c_type = SQL_C_LONG;
@ -1951,8 +2073,8 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
field_value_temp = static_cast<char*>( sqlsrv_malloc( field_len_temp + extra + 1 ));
r = core::SQLGetData( stmt, field_index + 1, c_type, field_value_temp, ( field_len_temp + extra ),
&field_len_temp, false /*handle_warning*/ TSRMLS_CC );
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp, ( field_len_temp + extra ),
&field_len_temp, false /*handle_warning*/ TSRMLS_CC );
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException ();
@ -1969,7 +2091,7 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
SQLSMALLINT len;
core::SQLGetDiagField( stmt, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
stmt->current_results->get_diag_field( 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
if( is_truncated_warning( state ) ) {
@ -1993,8 +2115,9 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
field_len_temp -= initial_field_len;
// Get the rest of the data.
r = core::SQLGetData( stmt, field_index + 1, c_type, field_value_temp + initial_field_len,
field_len_temp + extra, &dummy_field_len, false /*handle_warning*/ TSRMLS_CC );
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp + initial_field_len,
field_len_temp + extra, &dummy_field_len,
false /*handle_warning*/ TSRMLS_CC );
// the last packet will contain the actual amount retrieved, not SQL_NO_TOTAL
// so we calculate the actual length of the string with that.
@ -2019,8 +2142,9 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
field_len_temp -= INITIAL_FIELD_STRING_LEN;
// Get the rest of the data.
r = core::SQLGetData( stmt, field_index + 1, c_type, field_value_temp + INITIAL_FIELD_STRING_LEN,
field_len_temp + extra, &dummy_field_len, true /*handle_warning*/ TSRMLS_CC );
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp + INITIAL_FIELD_STRING_LEN,
field_len_temp + extra, &dummy_field_len,
true /*handle_warning*/ TSRMLS_CC );
if( dummy_field_len == SQL_NULL_DATA ) {
*field_value = NULL;
@ -2072,9 +2196,11 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
field_value_temp = static_cast<char*>( sqlsrv_malloc( sql_display_size + extra + 1 ));
// get the data
r = core::SQLGetData( stmt, field_index + 1, c_type, field_value_temp, sql_display_size,
&field_len_temp, true /*handle_warning*/ TSRMLS_CC );
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp, sql_display_size,
&field_len_temp, true /*handle_warning*/ TSRMLS_CC );
CHECK_SQL_ERROR( r, stmt ) {
throw core::CoreException();
}
CHECK_CUSTOM_ERROR( (r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
throw core::CoreException ();
}

View file

@ -3,7 +3,7 @@
//
// Contents: Implementation of PHP streams for reading SQL Server data
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -113,8 +113,9 @@ size_t sqlsrv_stream_read( php_stream* stream, __out_bcount(count) char* buf, si
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
SQLSMALLINT len;
core::SQLGetDiagField( ss->stmt, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
ss->stmt->current_results->get_diag_field( 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len TSRMLS_CC );
if( read == SQL_NO_TOTAL ) {
SQLSRV_ASSERT( is_truncated_warning( state ), "sqlsrv_stream_read: truncation warning was expected but it "
"did not occur." );
@ -135,7 +136,7 @@ size_t sqlsrv_stream_read( php_stream* stream, __out_bcount(count) char* buf, si
read = count - 1;
break;
default:
DIE( "sqlsrv_stream_read: should have never reached in this switch case. ");
DIE( "sqlsrv_stream_read: should have never reached in this switch case.");
break;
}
}

View file

@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -147,7 +147,8 @@ wchar_t* utf16_string_from_mbcs_string( SQLSRV_ENCODING php_encoding, const char
// 3/message) driver specific error message
// The fetch type determines if the indices are numeric, associative, or both.
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_error* error, logging_severity severity TSRMLS_DC )
bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_error_auto_ptr& error, logging_severity severity
TSRMLS_DC )
{
SQLHANDLE h = ctx.handle();
SQLSMALLINT h_type = ctx.handle_type();
@ -165,22 +166,50 @@ bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_
SQLINTEGER message_len = 0;
SQLWCHAR wsqlstate[ SQL_SQLSTATE_BUFSIZE ];
SQLWCHAR wnative_message[ SQL_MAX_MESSAGE_LENGTH + 1 ];
SQLSRV_ENCODING enc = ctx.encoding();
r = SQLGetDiagRecW( h_type, h, record_number, wsqlstate, &error->native_code, wnative_message,
SQL_MAX_MESSAGE_LENGTH + 1, &wmessage_len );
// don't use the CHECK* macros here since it will trigger reentry into the error handling system
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
return false;
}
switch( h_type ) {
case SQL_HANDLE_STMT:
{
sqlsrv_stmt* stmt = static_cast<sqlsrv_stmt*>( &ctx );
if( stmt->current_results != NULL ) {
error = stmt->current_results->get_diag_rec( record_number );
// don't use the CHECK* macros here since it will trigger reentry into the error handling system
if( error == NULL ) {
return false;
}
break;
}
// convert the error into the encoding of the context
if( enc == SQLSRV_ENCODING_DEFAULT ) {
enc = stmt->conn->encoding();
}
}
default:
error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error();
r = SQLGetDiagRecW( h_type, h, record_number, wsqlstate, &error->native_code, wnative_message,
SQL_MAX_MESSAGE_LENGTH + 1, &wmessage_len );
// don't use the CHECK* macros here since it will trigger reentry into the error handling system
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
return false;
}
error->sqlstate = reinterpret_cast<SQLCHAR*>( wsqlstate );
convert_string_from_utf16( enc, reinterpret_cast<char**>( &error->sqlstate ), sqlstate_len,
false /*no free*/ );
error->native_message = reinterpret_cast<SQLCHAR*>( wnative_message );
message_len = wmessage_len * sizeof( wchar_t );
convert_string_from_utf16( enc, reinterpret_cast<char**>( &error->native_message ), message_len,
false /*no free*/ );
break;
}
// convert the error into the encoding of the context
error->sqlstate = reinterpret_cast<SQLCHAR*>( wsqlstate );
convert_string_from_utf16( ctx.encoding(), reinterpret_cast<char**>( &error->sqlstate ), sqlstate_len,
false /*no free*/ );
error->native_message = reinterpret_cast<SQLCHAR*>( wnative_message );
message_len = wmessage_len * sizeof( wchar_t );
convert_string_from_utf16( ctx.encoding(), reinterpret_cast<char**>( &error->native_message ), message_len,
false /*no free*/ );
// log the error first
LOG( severity, "%1!s!: SQLSTATE = %2!s!", ctx.func(), error->sqlstate );
@ -194,9 +223,10 @@ bool core_sqlsrv_get_odbc_error( sqlsrv_context& ctx, int record_number, sqlsrv_
// format and return a driver specfic error
void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const const* custom_error,
sqlsrv_error* formatted_error, logging_severity severity TSRMLS_DC, va_list* args )
sqlsrv_error_auto_ptr& formatted_error, logging_severity severity TSRMLS_DC, va_list* args )
{
// allocate space for the formatted message
formatted_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error();
formatted_error->sqlstate = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_SQLSTATE_BUFSIZE ));
formatted_error->native_message = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_MAX_MESSAGE_LENGTH + 1 ));

View file

@ -2,7 +2,7 @@
// File: init.cpp
// Contents: initialization routines for the extension
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -46,134 +46,137 @@ unsigned int current_log_subsystem = LOG_INIT;
// argument info structures for functions, arranged alphabetically.
// see zend_API.h in the PHP sources for more information about these macros
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_begin_transaction_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, "connection resource" )
ZEND_ARG_INFO( 0, conn )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_cancel_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_close_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, "connection resource" )
ZEND_ARG_INFO( 0, conn )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_client_info_arginfo, 0, 0, 0 )
ZEND_ARG_INFO( 0, "connection resource" )
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_client_info_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, conn )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_commit_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, "connection resource" )
ZEND_ARG_INFO( 0, conn )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_configure_arginfo, 0, 0, 2 )
ZEND_ARG_INFO( 0, "option name" )
ZEND_ARG_INFO( 0, "value" )
ZEND_ARG_INFO( 0, setting )
ZEND_ARG_INFO( 0, value )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_connect_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, "server" )
ZEND_ARG_ARRAY_INFO( 0, "options", 0 )
ZEND_ARG_INFO( 0, server_name )
ZEND_ARG_ARRAY_INFO( 0, connection_info, 0 )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_errors_arginfo, 0, 1, 0 )
ZEND_ARG_INFO( 0, "flags (errors, warnings, or all)" )
ZEND_ARG_INFO( 0, errors_and_or_warnings )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_execute_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, "parameters" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_fetch_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_fetch_array_arginfo, 0, 1, 1 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, "array type" )
ZEND_ARG_INFO( 0, stmt )
ZEND_ARG_INFO( 0, fetch_type )
ZEND_ARG_INFO( 0, row )
ZEND_ARG_INFO( 0, offset )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_fetch_object_arginfo, 0, 1, 1 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, "class name" )
ZEND_ARG_INFO( 0, "ctor params" )
ZEND_ARG_INFO( 0, stmt )
ZEND_ARG_INFO( 0, class_name )
ZEND_ARG_INFO( 0, ctor_params )
ZEND_ARG_INFO( 0, row )
ZEND_ARG_INFO( 0, offset )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_field_metadata_arginfo, 0, 1, 1 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_free_stmt_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_get_config_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, "option name" )
ZEND_ARG_INFO( 0, setting )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_get_field_arginfo, 0, 1, 2 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, "field index" )
ZEND_ARG_INFO( 0, "type" )
ZEND_ARG_INFO( 0, stmt )
ZEND_ARG_INFO( 0, field_index )
ZEND_ARG_INFO( 0, get_as_type )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_has_rows_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_next_result_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_num_fields_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_num_rows_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_prepare_arginfo, 0, 1, 2 )
ZEND_ARG_INFO( 0, "connection resource" )
ZEND_ARG_INFO( 0, "sql command" )
ZEND_ARG_INFO( 0, "parameters" )
ZEND_ARG_ARRAY_INFO( 0, "options", 0 )
ZEND_ARG_INFO( 0, conn )
ZEND_ARG_INFO( 0, tsql )
ZEND_ARG_INFO( 0, params )
ZEND_ARG_INFO( 0, options )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_query_arginfo, 0, 1, 2 )
ZEND_ARG_INFO( 0, "connection resource" )
ZEND_ARG_INFO( 0, "sql command" )
ZEND_ARG_INFO( 0, "parameters" )
ZEND_ARG_ARRAY_INFO( 0, "options", 0 )
ZEND_ARG_INFO( 0, conn )
ZEND_ARG_INFO( 0, tsql )
ZEND_ARG_INFO( 0, params )
ZEND_ARG_INFO( 0, options )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX( sqlsrv_rollback_arginfo, 0, 0, 1 )
ZEND_ARG_INFO( 0, "connection resource" )
ZEND_ARG_INFO( 0, conn )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_rows_affected_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_send_stream_data_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_server_info_arginfo, 0 )
ZEND_ARG_INFO( 0, "statement resource" )
ZEND_ARG_INFO( 0, stmt )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_sqltype_size_arginfo, 0 )
ZEND_ARG_INFO( 0, "size" )
ZEND_ARG_INFO( 0, size )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_sqltype_precision_scale_arginfo, 0 )
ZEND_ARG_INFO( 0, "precision" )
ZEND_ARG_INFO( 0, "scale" )
ZEND_ARG_INFO( 0, precision )
ZEND_ARG_INFO( 0, scale )
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO( sqlsrv_phptype_encoding_arginfo, 0 )
ZEND_ARG_INFO( 0, "encoding" )
ZEND_ARG_INFO( 0, encoding )
ZEND_END_ARG_INFO()
// function table with associated arginfo structures
@ -290,7 +293,8 @@ PHP_MINIT_FUNCTION(sqlsrv)
REGISTER_LONG_CONSTANT( "SQLSRV_LOG_SEVERITY_ALL", -1, CONST_PERSISTENT | CONST_CS ); // -1 so that all the bits are set
// register connection resource
ss_sqlsrv_conn::descriptor = zend_register_list_destructors_ex( sqlsrv_conn_dtor, NULL, "SQL Server Connection", module_number );
ss_sqlsrv_conn::descriptor = zend_register_list_destructors_ex( sqlsrv_conn_dtor, NULL, "SQL Server Connection",
module_number );
if( ss_sqlsrv_conn::descriptor == FAILURE ) {
LOG( SEV_ERROR, "%1!s!: connection resource registration failed", _FN_ );
@ -319,8 +323,8 @@ PHP_MINIT_FUNCTION(sqlsrv)
REGISTER_STRING_CONSTANT( "SQLSRV_ENC_BINARY", "binary", CONST_PERSISTENT | CONST_CS );
REGISTER_STRING_CONSTANT( "SQLSRV_ENC_CHAR", "char", CONST_PERSISTENT | CONST_CS );
REGISTER_LONG_CONSTANT( "SQLSRV_NULLABLE_YES", 0, CONST_PERSISTENT | CONST_CS );
REGISTER_LONG_CONSTANT( "SQLSRV_NULLABLE_NO", 1, CONST_PERSISTENT | CONST_CS );
REGISTER_LONG_CONSTANT( "SQLSRV_NULLABLE_NO", 0, CONST_PERSISTENT | CONST_CS );
REGISTER_LONG_CONSTANT( "SQLSRV_NULLABLE_YES", 1, CONST_PERSISTENT | CONST_CS );
REGISTER_LONG_CONSTANT( "SQLSRV_NULLABLE_UNKNOWN", 2, CONST_PERSISTENT | CONST_CS );
REGISTER_LONG_CONSTANT( "SQLSRV_SQLTYPE_BIGINT", SQL_BIGINT, CONST_PERSISTENT | CONST_CS );
@ -394,6 +398,7 @@ PHP_MINIT_FUNCTION(sqlsrv)
REGISTER_STRING_CONSTANT( "SQLSRV_CURSOR_STATIC", "static", CONST_PERSISTENT | CONST_CS );
REGISTER_STRING_CONSTANT( "SQLSRV_CURSOR_DYNAMIC", "dynamic", CONST_PERSISTENT | CONST_CS );
REGISTER_STRING_CONSTANT( "SQLSRV_CURSOR_KEYSET", "keyset", CONST_PERSISTENT | CONST_CS );
REGISTER_STRING_CONSTANT( "SQLSRV_CURSOR_CLIENT_BUFFERED", "buffered", CONST_PERSISTENT | CONST_CS );
try {
@ -601,9 +606,16 @@ PHP_RINIT_FUNCTION(sqlsrv)
LOG_FUNCTION( "PHP_RINIT for php_sqlsrv" );
// read INI settings
SQLSRV_G( warnings_return_as_errors ) = INI_BOOL( INI_PREFIX INI_WARNINGS_RETURN_AS_ERRORS );
SQLSRV_G( log_severity ) = INI_INT( INI_PREFIX INI_LOG_SEVERITY );
SQLSRV_G( log_subsystems ) = INI_INT( INI_PREFIX INI_LOG_SUBSYSTEMS );
SQLSRV_G( buffered_query_limit ) = INI_INT( INI_PREFIX INI_BUFFERED_QUERY_LIMIT );
LOG( SEV_NOTICE, INI_PREFIX INI_WARNINGS_RETURN_AS_ERRORS " = %1!s!", SQLSRV_G( warnings_return_as_errors ) ? "On" : "Off");
LOG( SEV_NOTICE, INI_PREFIX INI_LOG_SEVERITY " = %1!d!", SQLSRV_G( log_severity ));
LOG( SEV_NOTICE, INI_PREFIX INI_LOG_SUBSYSTEMS " = %1!d!", SQLSRV_G( log_subsystems ));
LOG( SEV_NOTICE, INI_PREFIX INI_BUFFERED_QUERY_LIMIT " = %1!d!", SQLSRV_G( buffered_query_limit ));
// verify memory at the end of the request (in debug mode only)
full_mem_check(MEMCHECK_SILENT);
@ -626,7 +638,7 @@ PHP_RSHUTDOWN_FUNCTION(sqlsrv)
zval_ptr_dtor( &SQLSRV_G( errors ));
zval_ptr_dtor( &SQLSRV_G( warnings ));
// verify memory at the end of the request (in debug mode only)
// verify memory at the end of the request (in debug mode only)
full_mem_check(MEMCHECK_SILENT);
return SUCCESS;

View file

@ -8,7 +8,7 @@
//
// Comments: Also contains "internal" declarations shared across source files.
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -169,19 +169,11 @@ struct stmt_option_scrollable : public stmt_option_functor {
// This object inherits and overrides the callbacks necessary
struct ss_sqlsrv_stmt : public sqlsrv_stmt {
ss_sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC ) :
sqlsrv_stmt( c, handle, e, drv TSRMLS_CC ),
prepared( false ),
conn_index( -1 ),
params_z( NULL ),
fetch_field_names( NULL ),
fetch_fields_count ( 0 )
{
}
ss_sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC );
virtual ~ss_sqlsrv_stmt( void );
void new_result_set( void );
void new_result_set( TSRMLS_D );
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream );
@ -278,10 +270,11 @@ zval* errors;
zval* warnings;
// flags for error handling and logging (set via sqlsrv_configure or php.ini)
unsigned int log_severity;
unsigned int log_subsystems;
unsigned int current_subsystem;
long log_severity;
long log_subsystems;
long current_subsystem;
zend_bool warnings_return_as_errors;
long buffered_query_limit;
ZEND_END_MODULE_GLOBALS(sqlsrv)
@ -301,6 +294,7 @@ ZEND_EXTERN_MODULE_GLOBALS(sqlsrv);
#define INI_WARNINGS_RETURN_AS_ERRORS "WarningsReturnAsErrors"
#define INI_LOG_SEVERITY "LogSeverity"
#define INI_LOG_SUBSYSTEMS "LogSubsystems"
#define INI_BUFFERED_QUERY_LIMIT "ClientBufferMaxKBSize"
#define INI_PREFIX "sqlsrv."
PHP_INI_BEGIN()
@ -310,6 +304,8 @@ PHP_INI_BEGIN()
sqlsrv_globals )
STD_PHP_INI_ENTRY( INI_PREFIX INI_LOG_SUBSYSTEMS, "0", PHP_INI_ALL, OnUpdateLong, log_subsystems, zend_sqlsrv_globals,
sqlsrv_globals )
STD_PHP_INI_ENTRY( INI_PREFIX INI_BUFFERED_QUERY_LIMIT, INI_BUFFERED_QUERY_LIMIT_DEFAULT, PHP_INI_ALL, OnUpdateLong, buffered_query_limit,
zend_sqlsrv_globals, sqlsrv_globals )
PHP_INI_END()
//*********************************************************************************************************************************
@ -366,7 +362,6 @@ bool ss_error_handler( sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool
// *** extension error functions ***
PHP_FUNCTION(sqlsrv_errors);
PHP_FUNCTION(sqlsrv_warnings);
// convert from the default encoding specified by the "CharacterSet"
// connection option to UTF-16. mbcs_len and utf16_len are sizes in
@ -461,7 +456,8 @@ public:
#define LOG_FUNCTION( function_name ) \
const char* _FN_ = function_name; \
SQLSRV_G( current_subsystem ) = current_log_subsystem; \
LOG( SEV_NOTICE, "%1!s!: entering", _FN_ );
LOG( SEV_NOTICE, "%1!s!: entering", _FN_ ); \
CheckMemory _check_memory_;
#define SET_FUNCTION_NAME( context ) \
{ \
@ -480,6 +476,22 @@ enum logging_subsystems {
LOG_ALL = -1,
};
struct CheckMemory {
CheckMemory( void )
{
// test the integrity of the Zend heap.
full_mem_check(MEMCHECK_SILENT);
}
~CheckMemory( void )
{
// test the integrity of the Zend heap.
full_mem_check(MEMCHECK_SILENT);
}
};
//*********************************************************************************************************************************
// Utility Functions
//*********************************************************************************************************************************
@ -497,9 +509,6 @@ inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, char const* param_spec,
zval* rsrc;
H* h;
// test the integrity of the Zend heap.
full_mem_check(MEMCHECK_SILENT);
// reset the errors from the previous API call
reset_errors( TSRMLS_C );
@ -529,8 +538,8 @@ inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, char const* param_spec,
int result = SUCCESS;
// dummy context to pass to the error handler
sqlsrv_context *error_ctx = new sqlsrv_context( 0, ss_error_handler, NULL );
error_ctx->set_func( calling_func );
sqlsrv_context error_ctx( 0, ss_error_handler, NULL );;
error_ctx.set_func( calling_func );
switch( param_count ) {
@ -574,7 +583,7 @@ inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, char const* param_spec,
}
}
CHECK_CUSTOM_ERROR(( result == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func ) {
CHECK_CUSTOM_ERROR(( result == FAILURE ), &error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func ) {
throw ss::SSException();
}
@ -582,7 +591,7 @@ inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, char const* param_spec,
// get the resource registered
h = static_cast<H*>( zend_fetch_resource( &rsrc TSRMLS_CC, -1, H::resource_name, NULL, 1, H::descriptor ));
CHECK_CUSTOM_ERROR(( h == NULL ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func ) {
CHECK_CUSTOM_ERROR(( h == NULL ), &error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func ) {
throw ss::SSException();
}

3043
sqlsrv/sqlncli.h Normal file
View file

@ -0,0 +1,3043 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 7.00.0474 */
/* Compiler settings for sqlncli.idl:
Oicf, W1, Zp8, env=Win32 (32b run)
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/
#ifndef __sqlncli_h__
#define __sqlncli_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
#ifndef __ICommandWithParameters_FWD_DEFINED__
#define __ICommandWithParameters_FWD_DEFINED__
typedef interface ICommandWithParameters ICommandWithParameters;
#endif /* __ICommandWithParameters_FWD_DEFINED__ */
#ifndef __IUMSInitialize_FWD_DEFINED__
#define __IUMSInitialize_FWD_DEFINED__
typedef interface IUMSInitialize IUMSInitialize;
#endif /* __IUMSInitialize_FWD_DEFINED__ */
#ifndef __ISQLServerErrorInfo_FWD_DEFINED__
#define __ISQLServerErrorInfo_FWD_DEFINED__
typedef interface ISQLServerErrorInfo ISQLServerErrorInfo;
#endif /* __ISQLServerErrorInfo_FWD_DEFINED__ */
#ifndef __IRowsetFastLoad_FWD_DEFINED__
#define __IRowsetFastLoad_FWD_DEFINED__
typedef interface IRowsetFastLoad IRowsetFastLoad;
#endif /* __IRowsetFastLoad_FWD_DEFINED__ */
#ifndef __ISchemaLock_FWD_DEFINED__
#define __ISchemaLock_FWD_DEFINED__
typedef interface ISchemaLock ISchemaLock;
#endif /* __ISchemaLock_FWD_DEFINED__ */
#ifndef __IBCPSession_FWD_DEFINED__
#define __IBCPSession_FWD_DEFINED__
typedef interface IBCPSession IBCPSession;
#endif /* __IBCPSession_FWD_DEFINED__ */
#ifndef __ISSAbort_FWD_DEFINED__
#define __ISSAbort_FWD_DEFINED__
typedef interface ISSAbort ISSAbort;
#endif /* __ISSAbort_FWD_DEFINED__ */
#ifndef __ISSCommandWithParameters_FWD_DEFINED__
#define __ISSCommandWithParameters_FWD_DEFINED__
typedef interface ISSCommandWithParameters ISSCommandWithParameters;
#endif /* __ISSCommandWithParameters_FWD_DEFINED__ */
#ifndef __IDBAsynchStatus_FWD_DEFINED__
#define __IDBAsynchStatus_FWD_DEFINED__
typedef interface IDBAsynchStatus IDBAsynchStatus;
#endif /* __IDBAsynchStatus_FWD_DEFINED__ */
#ifndef __ISSAsynchStatus_FWD_DEFINED__
#define __ISSAsynchStatus_FWD_DEFINED__
typedef interface ISSAsynchStatus ISSAsynchStatus;
#endif /* __ISSAsynchStatus_FWD_DEFINED__ */
/* header files for imported files */
#include "unknwn.h"
#include "oaidl.h"
#ifdef __cplusplus
extern "C"{
#endif
/* interface __MIDL_itf_sqlncli_0000_0000 */
/* [local] */
//-----------------------------------------------------------------------------
// File: sqlncli.h
//
// Copyright: Copyright (c) Microsoft Corporation
//
// Contents: SQL Server Native Client OLEDB provider and ODBC driver specific
// definitions.
//
//-----------------------------------------------------------------------------
#if !defined(SQLNCLI_VER)
#define SQLNCLI_VER 1000
#endif
#if SQLNCLI_VER >= 1000
#define SQLNCLI_PRODUCT_NAME_FULL_VER_ANSI "Microsoft SQL Server Native Client 10.0"
#define SQLNCLI_PRODUCT_NAME_FULL_ANSI "Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_VER_ANSI "SQL Server Native Client 10.0"
#define SQLNCLI_PRODUCT_NAME_SHORT_ANSI "SQL Server Native Client"
#define SQLNCLI_FILE_NAME_ANSI "sqlncli"
#define SQLNCLI_FILE_NAME_VER_ANSI "sqlncli10"
#define SQLNCLI_FILE_NAME_FULL_ANSI "sqlncli10.dll"
#define SQLNCLI_PRODUCT_NAME_FULL_VER_UNICODE L"Microsoft SQL Server Native Client 10.0"
#define SQLNCLI_PRODUCT_NAME_FULL_UNICODE L"Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_VER_UNICODE L"SQL Server Native Client 10.0"
#define SQLNCLI_PRODUCT_NAME_SHORT_UNICODE L"SQL Server Native Client"
#define SQLNCLI_FILE_NAME_UNICODE L"sqlncli"
#define SQLNCLI_FILE_NAME_VER_UNICODE L"sqlncli10"
#define SQLNCLI_FILE_NAME_FULL_UNICODE L"sqlncli10.dll"
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#define SQLNCLI_VI_PROG_ID_ANSI "SQLNCLI10"
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_ANSI "SQLNCLI10 ErrorLookup"
#define SQLNCLI_VI_ENUMERATOR_PROG_ID_ANSI "SQLNCLI10 Enumerator"
#define SQLNCLI_PROG_ID_ANSI "SQLNCLI10.1"
#define SQLNCLI_ERROR_LOOKUP_PROG_ID_ANSI "SQLNCLI10 ErrorLookup.1"
#define SQLNCLI_ENUMERATOR_PROG_ID_ANSI "SQLNCLI10 Enumerator.1"
#define SQLNCLI_VI_PROG_ID_UNICODE L"SQLNCLI10"
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_UNICODE L"SQLNCLI10 ErrorLookup"
#define SQLNCLI_VI_ENUMERATOR_PROG_ID_UNICODE L"SQLNCLI10 Enumerator"
#define SQLNCLI_PROG_ID_UNICODE L"SQLNCLI10.1"
#define SQLNCLI_ERROR_LOOKUP_PROG_ID_UNICODE L"SQLNCLI10 ErrorLookup.1"
#define SQLNCLI_ENUMERATOR_PROG_ID_UNICODE L"SQLNCLI10 Enumerator.1"
#define SQLNCLI_CLSID CLSID_SQLNCLI10
#define SQLNCLI_ERROR_CLSID CLSID_SQLNCLI10_ERROR
#define SQLNCLI_ENUMERATOR_CLSID CLSID_SQLNCLI10_ENUMERATOR
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#else // SQLNCLI_VER >= 1000
#define SQLNCLI_PRODUCT_NAME_FULL_VER_ANSI "Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_FULL_ANSI "Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_VER_ANSI "SQL Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_ANSI "SQL Native Client"
#define SQLNCLI_FILE_NAME_ANSI "sqlncli"
#define SQLNCLI_FILE_NAME_VER_ANSI "sqlncli"
#define SQLNCLI_FILE_NAME_FULL_ANSI "sqlncli.dll"
#define SQLNCLI_PRODUCT_NAME_FULL_VER_UNICODE L"Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_FULL_UNICODE L"Microsoft SQL Server Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_VER_UNICODE L"SQL Native Client"
#define SQLNCLI_PRODUCT_NAME_SHORT_UNICODE L"SQL Native Client"
#define SQLNCLI_FILE_NAME_UNICODE L"sqlncli"
#define SQLNCLI_FILE_NAME_VER_UNICODE L"sqlncli"
#define SQLNCLI_FILE_NAME_FULL_UNICODE L"sqlncli.dll"
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#define SQLNCLI_VI_PROG_ID_ANSI "SQLNCLI"
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_ANSI "SQLNCLI ErrorLookup"
#define SQLNCLI_VI_ENUMERATOR_PROG_ID_ANSI "SQLNCLI Enumerator"
#define SQLNCLI_PROG_ID_ANSI "SQLNCLI.1"
#define SQLNCLI_ERROR_LOOKUP_PROG_ID_ANSI "SQLNCLI ErrorLookup.1"
#define SQLNCLI_ENUMERATOR_PROG_ID_ANSI "SQLNCLI Enumerator.1"
#define SQLNCLI_VI_PROG_ID_UNICODE L"SQLNCLI"
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_UNICODE L"SQLNCLI ErrorLookup"
#define SQLNCLI_VI_ENUMERATOR_PROG_ID_UNICODE L"SQLNCLI Enumerator"
#define SQLNCLI_PROG_ID_UNICODE L"SQLNCLI.1"
#define SQLNCLI_ERROR_LOOKUP_PROG_ID_UNICODE L"SQLNCLI ErrorLookup.1"
#define SQLNCLI_ENUMERATOR_PROG_ID_UNICODE L"SQLNCLI Enumerator.1"
#define SQLNCLI_CLSID CLSID_SQLNCLI
#define SQLNCLI_ERROR_CLSID CLSID_SQLNCLI_ERROR
#define SQLNCLI_ENUMERATOR_CLSID CLSID_SQLNCLI_ENUMERATOR
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#endif // SQLNCLI_VER >= 1000
// define the character type agnostic constants
#if defined(_UNICODE) || defined(UNICODE)
#define SQLNCLI_PRODUCT_NAME_FULL_VER SQLNCLI_PRODUCT_NAME_FULL_VER_UNICODE
#define SQLNCLI_PRODUCT_NAME_FULL SQLNCLI_PRODUCT_NAME_FULL_UNICODE
#define SQLNCLI_PRODUCT_NAME_SHORT_VER SQLNCLI_PRODUCT_NAME_SHORT_VER_UNICODE
#define SQLNCLI_PRODUCT_NAME_SHORT SQLNCLI_PRODUCT_NAME_SHORT_UNICODE
#define SQLNCLI_FILE_NAME SQLNCLI_FILE_NAME_UNICODE
#define SQLNCLI_FILE_NAME_VER SQLNCLI_FILE_NAME_VER_UNICODE
#define SQLNCLI_FILE_NAME_FULL SQLNCLI_FILE_NAME_FULL_UNICODE
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#define SQLNCLI_VI_PROG_ID SQLNCLI_VI_PROG_ID_UNICODE
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_UNICODE
#define SQLNCLI_VI_ENUMERATOR_PROG_ID SQLNCLI_VI_ENUMERATOR_PROG_ID_UNICODE
#define SQLNCLI_PROG_ID SQLNCLI_PROG_ID_UNICODE
#define SQLNCLI_ERROR_LOOKUP_PROG_ID SQLNCLI_ERROR_LOOKUP_PROG_ID_UNICODE
#define SQLNCLI_ENUMERATOR_PROG_ID SQLNCLI_ENUMERATOR_PROG_ID_UNICODE
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#else // _UNICODE || UNICODE
#define SQLNCLI_PRODUCT_NAME_FULL_VER SQLNCLI_PRODUCT_NAME_FULL_VER_ANSI
#define SQLNCLI_PRODUCT_NAME_FULL SQLNCLI_PRODUCT_NAME_FULL_ANSI
#define SQLNCLI_PRODUCT_NAME_SHORT_VER SQLNCLI_PRODUCT_NAME_SHORT_VER_ANSI
#define SQLNCLI_PRODUCT_NAME_SHORT SQLNCLI_PRODUCT_NAME_SHORT_ANSI
#define SQLNCLI_FILE_NAME SQLNCLI_FILE_NAME_ANSI
#define SQLNCLI_FILE_NAME_VER SQLNCLI_FILE_NAME_VER_ANSI
#define SQLNCLI_FILE_NAME_FULL SQLNCLI_FILE_NAME_FULL_ANSI
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#define SQLNCLI_VI_PROG_ID SQLNCLI_VI_PROG_ID_ANSI
#define SQLNCLI_VI_ERROR_LOOKUP_PROG_ID SQLNCLI_VI_ERROR_LOOKUP_PROG_ID_ANSI
#define SQLNCLI_VI_ENUMERATOR_PROG_ID SQLNCLI_VI_ENUMERATOR_PROG_ID_ANSI
#define SQLNCLI_PROG_ID SQLNCLI_PROG_ID_ANSI
#define SQLNCLI_ERROR_LOOKUP_PROG_ID SQLNCLI_ERROR_LOOKUP_PROG_ID_ANSI
#define SQLNCLI_ENUMERATOR_PROG_ID SQLNCLI_ENUMERATOR_PROG_ID_ANSI
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#endif // _UNICODE || UNICODE
#if defined(_SQLNCLI_ODBC_) || !defined(_SQLNCLI_OLEDB_)
#define SQLNCLI_DRIVER_NAME SQLNCLI_PRODUCT_NAME_SHORT_VER
#endif
// OLEDB part of SQL Server Native Client header - begin here
#if defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
#ifndef __oledb_h__
#include <oledb.h>
#endif /*__oledb_h__*/
#if 0 // This is already defined in oledb.h
#ifdef _WIN64
// Length of a non-character object, size
typedef ULONGLONG DBLENGTH;
// Offset within a rowset
typedef LONGLONG DBROWOFFSET;
// Number of rows
typedef LONGLONG DBROWCOUNT;
typedef ULONGLONG DBCOUNTITEM;
// Ordinal (column number, etc.)
typedef ULONGLONG DBORDINAL;
typedef LONGLONG DB_LORDINAL;
// Bookmarks
typedef ULONGLONG DBBKMARK;
// Offset in the buffer
typedef ULONGLONG DBBYTEOFFSET;
// Reference count of each row/accessor handle
typedef ULONG DBREFCOUNT;
// Parameters
typedef ULONGLONG DB_UPARAMS;
typedef LONGLONG DB_LPARAMS;
// hash values corresponding to the elements (bookmarks)
typedef DWORDLONG DBHASHVALUE;
// For reserve
typedef DWORDLONG DB_DWRESERVE;
typedef LONGLONG DB_LRESERVE;
typedef ULONGLONG DB_URESERVE;
#else //_WIN64
// Length of a non-character object, size
typedef ULONG DBLENGTH;
// Offset within a rowset
typedef LONG DBROWOFFSET;
// Number of rows
typedef LONG DBROWCOUNT;
typedef ULONG DBCOUNTITEM;
// Ordinal (column number, etc.)
typedef ULONG DBORDINAL;
typedef LONG DB_LORDINAL;
// Bookmarks
typedef ULONG DBBKMARK;
// Offset in the buffer
typedef ULONG DBBYTEOFFSET;
// Reference count of each row handle
typedef ULONG DBREFCOUNT;
// Parameters
typedef ULONG DB_UPARAMS;
typedef LONG DB_LPARAMS;
// hash values corresponding to the elements (bookmarks)
typedef DWORD DBHASHVALUE;
// For reserve
typedef DWORD DB_DWRESERVE;
typedef LONG DB_LRESERVE;
typedef ULONG DB_URESERVE;
#endif // _WIN64
typedef DWORD DBKIND;
enum DBKINDENUM
{ DBKIND_GUID_NAME = 0,
DBKIND_GUID_PROPID = ( DBKIND_GUID_NAME + 1 ) ,
DBKIND_NAME = ( DBKIND_GUID_PROPID + 1 ) ,
DBKIND_PGUID_NAME = ( DBKIND_NAME + 1 ) ,
DBKIND_PGUID_PROPID = ( DBKIND_PGUID_NAME + 1 ) ,
DBKIND_PROPID = ( DBKIND_PGUID_PROPID + 1 ) ,
DBKIND_GUID = ( DBKIND_PROPID + 1 )
} ;
typedef struct tagDBID
{
union
{
GUID guid;
GUID *pguid;
/* Empty union arm */
} uGuid;
DBKIND eKind;
union
{
LPOLESTR pwszName;
ULONG ulPropid;
/* Empty union arm */
} uName;
} DBID;
typedef struct tagDB_NUMERIC
{
BYTE precision;
BYTE scale;
BYTE sign;
BYTE val[ 16 ];
} DB_NUMERIC;
typedef struct tagDBDATE
{
SHORT year;
USHORT month;
USHORT day;
} DBDATE;
typedef struct tagDBTIME
{
USHORT hour;
USHORT minute;
USHORT second;
} DBTIME;
typedef struct tagDBTIMESTAMP
{
SHORT year;
USHORT month;
USHORT day;
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
} DBTIMESTAMP;
typedef struct tagDBOBJECT
{
DWORD dwFlags;
IID iid;
} DBOBJECT;
typedef WORD DBTYPE;
typedef ULONG_PTR HACCESSOR;
typedef ULONG_PTR HCHAPTER;
typedef DWORD DBPARAMFLAGS;
typedef struct tagDBPARAMINFO
{
DBPARAMFLAGS dwFlags;
DBORDINAL iOrdinal;
LPOLESTR pwszName;
ITypeInfo *pTypeInfo;
DBLENGTH ulParamSize;
DBTYPE wType;
BYTE bPrecision;
BYTE bScale;
} DBPARAMINFO;
typedef DWORD DBPROPID;
typedef struct tagDBPROPIDSET
{
DBPROPID *rgPropertyIDs;
ULONG cPropertyIDs;
GUID guidPropertySet;
} DBPROPIDSET;
typedef DWORD DBPROPFLAGS;
typedef DWORD DBPROPOPTIONS;
typedef DWORD DBPROPSTATUS;
typedef struct tagDBPROP
{
DBPROPID dwPropertyID;
DBPROPOPTIONS dwOptions;
DBPROPSTATUS dwStatus;
DBID colid;
VARIANT vValue;
} DBPROP;
typedef struct tagDBPROPSET
{
DBPROP *rgProperties;
ULONG cProperties;
GUID guidPropertySet;
} DBPROPSET;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0000_v0_0_s_ifspec;
#ifndef __ICommandWithParameters_INTERFACE_DEFINED__
#define __ICommandWithParameters_INTERFACE_DEFINED__
/* interface ICommandWithParameters */
/* [unique][uuid][object][local] */
typedef struct tagDBPARAMBINDINFO
{
LPOLESTR pwszDataSourceType;
LPOLESTR pwszName;
DBLENGTH ulParamSize;
DBPARAMFLAGS dwFlags;
BYTE bPrecision;
BYTE bScale;
} DBPARAMBINDINFO;
EXTERN_C const IID IID_ICommandWithParameters;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("0c733a64-2a1c-11ce-ade5-00aa0044773d")
ICommandWithParameters : public IUnknown
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetParameterInfo(
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ DBPARAMINFO **prgParamInfo,
/* [out] */ OLECHAR **ppNamesBuffer) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE MapParameterNames(
/* [in] */ DB_UPARAMS cParamNames,
/* [size_is][in] */ const OLECHAR *rgParamNames[ ],
/* [size_is][out] */ DB_LPARAMS rgParamOrdinals[ ]) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE SetParameterInfo(
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ const DB_UPARAMS rgParamOrdinals[ ],
/* [size_is][unique][in] */ const DBPARAMBINDINFO rgParamBindInfo[ ]) = 0;
};
#else /* C style interface */
typedef struct ICommandWithParametersVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ICommandWithParameters * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ICommandWithParameters * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ICommandWithParameters * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetParameterInfo )(
ICommandWithParameters * This,
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ DBPARAMINFO **prgParamInfo,
/* [out] */ OLECHAR **ppNamesBuffer);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *MapParameterNames )(
ICommandWithParameters * This,
/* [in] */ DB_UPARAMS cParamNames,
/* [size_is][in] */ const OLECHAR *rgParamNames[ ],
/* [size_is][out] */ DB_LPARAMS rgParamOrdinals[ ]);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetParameterInfo )(
ICommandWithParameters * This,
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ const DB_UPARAMS rgParamOrdinals[ ],
/* [size_is][unique][in] */ const DBPARAMBINDINFO rgParamBindInfo[ ]);
END_INTERFACE
} ICommandWithParametersVtbl;
interface ICommandWithParameters
{
CONST_VTBL struct ICommandWithParametersVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ICommandWithParameters_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ICommandWithParameters_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ICommandWithParameters_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ICommandWithParameters_GetParameterInfo(This,pcParams,prgParamInfo,ppNamesBuffer) \
( (This)->lpVtbl -> GetParameterInfo(This,pcParams,prgParamInfo,ppNamesBuffer) )
#define ICommandWithParameters_MapParameterNames(This,cParamNames,rgParamNames,rgParamOrdinals) \
( (This)->lpVtbl -> MapParameterNames(This,cParamNames,rgParamNames,rgParamOrdinals) )
#define ICommandWithParameters_SetParameterInfo(This,cParams,rgParamOrdinals,rgParamBindInfo) \
( (This)->lpVtbl -> SetParameterInfo(This,cParams,rgParamOrdinals,rgParamBindInfo) )
#endif /* COBJMACROS */
#endif /* C style interface */
/* [call_as] */ HRESULT STDMETHODCALLTYPE ICommandWithParameters_RemoteGetParameterInfo_Proxy(
ICommandWithParameters * This,
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ DBPARAMINFO **prgParamInfo,
/* [size_is][size_is][out] */ DBBYTEOFFSET **prgNameOffsets,
/* [out][in] */ DBLENGTH *pcbNamesBuffer,
/* [size_is][size_is][unique][out][in] */ OLECHAR **ppNamesBuffer,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB ICommandWithParameters_RemoteGetParameterInfo_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
/* [call_as] */ HRESULT STDMETHODCALLTYPE ICommandWithParameters_RemoteMapParameterNames_Proxy(
ICommandWithParameters * This,
/* [in] */ DB_UPARAMS cParamNames,
/* [size_is][in] */ LPCOLESTR *rgParamNames,
/* [size_is][out] */ DB_LPARAMS *rgParamOrdinals,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB ICommandWithParameters_RemoteMapParameterNames_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
/* [call_as] */ HRESULT STDMETHODCALLTYPE ICommandWithParameters_RemoteSetParameterInfo_Proxy(
ICommandWithParameters * This,
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ const DB_UPARAMS *rgParamOrdinals,
/* [size_is][unique][in] */ const DBPARAMBINDINFO *rgParamBindInfo,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB ICommandWithParameters_RemoteSetParameterInfo_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __ICommandWithParameters_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0001 */
/* [local] */
typedef DWORD DBASYNCHOP;
typedef DWORD DBASYNCHPHASE;
#endif // This is already defined in oledb.h
//-------------------------------------------------------------------
// Variant Access macros, similar to ole automation.
//-------------------------------------------------------------------
#define V_SS_VT(X) ((X)->vt)
#define V_SS_UNION(X, Y) ((X)->Y)
#define V_SS_UI1(X) V_SS_UNION(X, bTinyIntVal)
#define V_SS_I2(X) V_SS_UNION(X, sShortIntVal)
#define V_SS_I4(X) V_SS_UNION(X, lIntVal)
#define V_SS_I8(X) V_SS_UNION(X, llBigIntVal)
#define V_SS_R4(X) V_SS_UNION(X, fltRealVal)
#define V_SS_R8(X) V_SS_UNION(X, dblFloatVal)
#define V_SS_UI4(X) V_SS_UNION(X, ulVal)
#define V_SS_MONEY(X) V_SS_UNION(X, cyMoneyVal)
#define V_SS_SMALLMONEY(X) V_SS_UNION(X, cyMoneyVal)
#define V_SS_WSTRING(X) V_SS_UNION(X, NCharVal)
#define V_SS_WVARSTRING(X) V_SS_UNION(X, NCharVal)
#define V_SS_STRING(X) V_SS_UNION(X, CharVal)
#define V_SS_VARSTRING(X) V_SS_UNION(X, CharVal)
#define V_SS_BIT(X) V_SS_UNION(X, fBitVal)
#define V_SS_GUID(X) V_SS_UNION(X, rgbGuidVal)
#define V_SS_NUMERIC(X) V_SS_UNION(X, numNumericVal)
#define V_SS_DECIMAL(X) V_SS_UNION(X, numNumericVal)
#define V_SS_BINARY(X) V_SS_UNION(X, BinaryVal)
#define V_SS_VARBINARY(X) V_SS_UNION(X, BinaryVal)
#define V_SS_DATETIME(X) V_SS_UNION(X, tsDateTimeVal)
#define V_SS_SMALLDATETIME(X) V_SS_UNION(X, tsDateTimeVal)
#define V_SS_UNKNOWN(X) V_SS_UNION(X, UnknownType)
//Text and image types.
#define V_SS_IMAGE(X) V_SS_UNION(X, ImageVal)
#define V_SS_TEXT(X) V_SS_UNION(X, TextVal)
#define V_SS_NTEXT(X) V_SS_UNION(X, NTextVal)
//Microsoft SQL Server 2008 datetime.
#define V_SS_DATE(X) V_SS_UNION(X, dDateVal)
#define V_SS_TIME2(X) V_SS_UNION(X, Time2Val)
#define V_SS_DATETIME2(X) V_SS_UNION(X, DateTimeVal)
#define V_SS_DATETIMEOFFSET(X) V_SS_UNION(X, DateTimeOffsetVal)
//-------------------------------------------------------------------
// define SQL Server specific types.
//-------------------------------------------------------------------
typedef enum DBTYPEENUM EOledbTypes;
#define DBTYPE_XML ((EOledbTypes) 141) // introduced in SQL 2005
#define DBTYPE_TABLE ((EOledbTypes) 143) // introduced in SQL 2008
#define DBTYPE_DBTIME2 ((EOledbTypes) 145) // introduced in SQL 2008
#define DBTYPE_DBTIMESTAMPOFFSET ((EOledbTypes) 146) // introduced in SQL 2008
#ifdef _SQLOLEDB_H_
#undef DBTYPE_SQLVARIANT
#endif //_SQLOLEDB_H_
#define DBTYPE_SQLVARIANT ((EOledbTypes) 144) // introduced in MDAC 2.5
#ifndef _SQLOLEDB_H_
enum SQLVARENUM
{
VT_SS_EMPTY = DBTYPE_EMPTY,
VT_SS_NULL = DBTYPE_NULL,
VT_SS_UI1 = DBTYPE_UI1,
VT_SS_I2 = DBTYPE_I2,
VT_SS_I4 = DBTYPE_I4,
VT_SS_I8 = DBTYPE_I8,
//Floats
VT_SS_R4 = DBTYPE_R4,
VT_SS_R8 = DBTYPE_R8,
//Money
VT_SS_MONEY = DBTYPE_CY,
VT_SS_SMALLMONEY = 200,
//Strings
VT_SS_WSTRING = 201,
VT_SS_WVARSTRING = 202,
VT_SS_STRING = 203,
VT_SS_VARSTRING = 204,
//Bit
VT_SS_BIT = DBTYPE_BOOL,
//Guid
VT_SS_GUID = DBTYPE_GUID,
//Exact precision
VT_SS_NUMERIC = DBTYPE_NUMERIC,
VT_SS_DECIMAL = 205,
//Datetime
VT_SS_DATETIME = DBTYPE_DBTIMESTAMP,
VT_SS_SMALLDATETIME =206,
//Binary
VT_SS_BINARY =207,
VT_SS_VARBINARY = 208,
//Future
VT_SS_UNKNOWN = 209,
//Additional datetime
VT_SS_DATE = DBTYPE_DBDATE,
VT_SS_TIME2 = DBTYPE_DBTIME2,
VT_SS_DATETIME2 = 212,
VT_SS_DATETIMEOFFSET = DBTYPE_DBTIMESTAMPOFFSET,
};
typedef unsigned short SSVARTYPE;
enum DBPARAMFLAGSENUM_SS_100
{ DBPARAMFLAGS_SS_ISVARIABLESCALE = 0x40000000
} ;
enum DBCOLUMNFLAGSENUM_SS_100
{ DBCOLUMNFLAGS_SS_ISVARIABLESCALE = 0x40000000,
DBCOLUMNFLAGS_SS_ISCOLUMNSET = 0x80000000
} ;
//-------------------------------------------------------------------
// Class Factory Interface used to initialize pointer to UMS.
//-------------------------------------------------------------------
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0001_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0001_v0_0_s_ifspec;
#ifndef __IUMSInitialize_INTERFACE_DEFINED__
#define __IUMSInitialize_INTERFACE_DEFINED__
/* interface IUMSInitialize */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_IUMSInitialize;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5cf4ca14-ef21-11d0-97e7-00c04fc2ad98")
IUMSInitialize : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE Initialize(
/* [in] */ void *pUMS) = 0;
};
#else /* C style interface */
typedef struct IUMSInitializeVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUMSInitialize * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IUMSInitialize * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IUMSInitialize * This);
HRESULT ( STDMETHODCALLTYPE *Initialize )(
IUMSInitialize * This,
/* [in] */ void *pUMS);
END_INTERFACE
} IUMSInitializeVtbl;
interface IUMSInitialize
{
CONST_VTBL struct IUMSInitializeVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IUMSInitialize_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IUMSInitialize_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IUMSInitialize_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IUMSInitialize_Initialize(This,pUMS) \
( (This)->lpVtbl -> Initialize(This,pUMS) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __IUMSInitialize_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0002 */
/* [local] */
// the structure returned by ISQLServerErrorInfo::GetSQLServerInfo
typedef struct tagSSErrorInfo
{
LPOLESTR pwszMessage;
LPOLESTR pwszServer;
LPOLESTR pwszProcedure;
LONG lNative;
BYTE bState;
BYTE bClass;
WORD wLineNumber;
} SSERRORINFO;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0002_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0002_v0_0_s_ifspec;
#ifndef __ISQLServerErrorInfo_INTERFACE_DEFINED__
#define __ISQLServerErrorInfo_INTERFACE_DEFINED__
/* interface ISQLServerErrorInfo */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISQLServerErrorInfo;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5CF4CA12-EF21-11d0-97E7-00C04FC2AD98")
ISQLServerErrorInfo : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetErrorInfo(
/* [out] */ SSERRORINFO **ppErrorInfo,
/* [out] */ OLECHAR **ppStringsBuffer) = 0;
};
#else /* C style interface */
typedef struct ISQLServerErrorInfoVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISQLServerErrorInfo * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISQLServerErrorInfo * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISQLServerErrorInfo * This);
HRESULT ( STDMETHODCALLTYPE *GetErrorInfo )(
ISQLServerErrorInfo * This,
/* [out] */ SSERRORINFO **ppErrorInfo,
/* [out] */ OLECHAR **ppStringsBuffer);
END_INTERFACE
} ISQLServerErrorInfoVtbl;
interface ISQLServerErrorInfo
{
CONST_VTBL struct ISQLServerErrorInfoVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISQLServerErrorInfo_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISQLServerErrorInfo_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISQLServerErrorInfo_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISQLServerErrorInfo_GetErrorInfo(This,ppErrorInfo,ppStringsBuffer) \
( (This)->lpVtbl -> GetErrorInfo(This,ppErrorInfo,ppStringsBuffer) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISQLServerErrorInfo_INTERFACE_DEFINED__ */
#ifndef __IRowsetFastLoad_INTERFACE_DEFINED__
#define __IRowsetFastLoad_INTERFACE_DEFINED__
/* interface IRowsetFastLoad */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_IRowsetFastLoad;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5CF4CA13-EF21-11d0-97E7-00C04FC2AD98")
IRowsetFastLoad : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE InsertRow(
/* [in] */ HACCESSOR hAccessor,
/* [in] */ void *pData) = 0;
virtual HRESULT STDMETHODCALLTYPE Commit(
/* [in] */ BOOL fDone) = 0;
};
#else /* C style interface */
typedef struct IRowsetFastLoadVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IRowsetFastLoad * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IRowsetFastLoad * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IRowsetFastLoad * This);
HRESULT ( STDMETHODCALLTYPE *InsertRow )(
IRowsetFastLoad * This,
/* [in] */ HACCESSOR hAccessor,
/* [in] */ void *pData);
HRESULT ( STDMETHODCALLTYPE *Commit )(
IRowsetFastLoad * This,
/* [in] */ BOOL fDone);
END_INTERFACE
} IRowsetFastLoadVtbl;
interface IRowsetFastLoad
{
CONST_VTBL struct IRowsetFastLoadVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IRowsetFastLoad_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IRowsetFastLoad_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IRowsetFastLoad_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IRowsetFastLoad_InsertRow(This,hAccessor,pData) \
( (This)->lpVtbl -> InsertRow(This,hAccessor,pData) )
#define IRowsetFastLoad_Commit(This,fDone) \
( (This)->lpVtbl -> Commit(This,fDone) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __IRowsetFastLoad_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0004 */
/* [local] */
#include <pshpack8.h> // 8-byte structure packing
typedef struct tagDBTIME2
{
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
} DBTIME2;
typedef struct tagDBTIMESTAMPOFFSET
{
SHORT year;
USHORT month;
USHORT day;
USHORT hour;
USHORT minute;
USHORT second;
ULONG fraction;
SHORT timezone_hour;
SHORT timezone_minute;
} DBTIMESTAMPOFFSET;
#include <poppack.h> // restore original structure packing
struct SSVARIANT
{
SSVARTYPE vt;
DWORD dwReserved1;
DWORD dwReserved2;
union
{
BYTE bTinyIntVal;
SHORT sShortIntVal;
LONG lIntVal;
LONGLONG llBigIntVal;
FLOAT fltRealVal;
DOUBLE dblFloatVal;
CY cyMoneyVal;
VARIANT_BOOL fBitVal;
BYTE rgbGuidVal[ 16 ];
DB_NUMERIC numNumericVal;
DBDATE dDateVal;
DBTIMESTAMP tsDateTimeVal;
struct _Time2Val
{
DBTIME2 tTime2Val;
BYTE bScale;
} Time2Val;
struct _DateTimeVal
{
DBTIMESTAMP tsDateTimeVal;
BYTE bScale;
} DateTimeVal;
struct _DateTimeOffsetVal
{
DBTIMESTAMPOFFSET tsoDateTimeOffsetVal;
BYTE bScale;
} DateTimeOffsetVal;
struct _NCharVal
{
SHORT sActualLength;
SHORT sMaxLength;
WCHAR *pwchNCharVal;
BYTE rgbReserved[ 5 ];
DWORD dwReserved;
WCHAR *pwchReserved;
} NCharVal;
struct _CharVal
{
SHORT sActualLength;
SHORT sMaxLength;
CHAR *pchCharVal;
BYTE rgbReserved[ 5 ];
DWORD dwReserved;
WCHAR *pwchReserved;
} CharVal;
struct _BinaryVal
{
SHORT sActualLength;
SHORT sMaxLength;
BYTE *prgbBinaryVal;
DWORD dwReserved;
} BinaryVal;
struct _UnknownType
{
DWORD dwActualLength;
BYTE rgMetadata[ 16 ];
BYTE *pUnknownData;
} UnknownType;
struct _BLOBType
{
DBOBJECT dbobj;
IUnknown *pUnk;
} BLOBType;
} ;
} ;
typedef DWORD LOCKMODE;
enum LOCKMODEENUM
{ LOCKMODE_INVALID = 0,
LOCKMODE_EXCLUSIVE = ( LOCKMODE_INVALID + 1 ) ,
LOCKMODE_SHARED = ( LOCKMODE_EXCLUSIVE + 1 )
} ;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0004_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0004_v0_0_s_ifspec;
#ifndef __ISchemaLock_INTERFACE_DEFINED__
#define __ISchemaLock_INTERFACE_DEFINED__
/* interface ISchemaLock */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISchemaLock;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("4C2389FB-2511-11d4-B258-00C04F7971CE")
ISchemaLock : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetSchemaLock(
/* [in] */ DBID *pTableID,
/* [in] */ LOCKMODE lmMode,
/* [out] */ HANDLE *phLockHandle,
/* [out] */ ULONGLONG *pTableVersion) = 0;
virtual HRESULT STDMETHODCALLTYPE ReleaseSchemaLock(
/* [in] */ HANDLE hLockHandle) = 0;
};
#else /* C style interface */
typedef struct ISchemaLockVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISchemaLock * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISchemaLock * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISchemaLock * This);
HRESULT ( STDMETHODCALLTYPE *GetSchemaLock )(
ISchemaLock * This,
/* [in] */ DBID *pTableID,
/* [in] */ LOCKMODE lmMode,
/* [out] */ HANDLE *phLockHandle,
/* [out] */ ULONGLONG *pTableVersion);
HRESULT ( STDMETHODCALLTYPE *ReleaseSchemaLock )(
ISchemaLock * This,
/* [in] */ HANDLE hLockHandle);
END_INTERFACE
} ISchemaLockVtbl;
interface ISchemaLock
{
CONST_VTBL struct ISchemaLockVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISchemaLock_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISchemaLock_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISchemaLock_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISchemaLock_GetSchemaLock(This,pTableID,lmMode,phLockHandle,pTableVersion) \
( (This)->lpVtbl -> GetSchemaLock(This,pTableID,lmMode,phLockHandle,pTableVersion) )
#define ISchemaLock_ReleaseSchemaLock(This,hLockHandle) \
( (This)->lpVtbl -> ReleaseSchemaLock(This,hLockHandle) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISchemaLock_INTERFACE_DEFINED__ */
#ifndef __IBCPSession_INTERFACE_DEFINED__
#define __IBCPSession_INTERFACE_DEFINED__
/* interface IBCPSession */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_IBCPSession;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("88352D80-42D1-42f0-A170-AB0F8B45B939")
IBCPSession : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE BCPColFmt(
/* [in] */ DBORDINAL idxUserDataCol,
/* [in] */ int eUserDataType,
/* [in] */ int cbIndicator,
/* [in] */ int cbUserData,
/* [size_is][in] */ BYTE *pbUserDataTerm,
/* [in] */ int cbUserDataTerm,
/* [in] */ DBORDINAL idxServerCol) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPColumns(
/* [in] */ DBCOUNTITEM nColumns) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPControl(
/* [in] */ int eOption,
/* [in] */ void *iValue) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPDone( void) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPExec(
/* [out] */ DBROWCOUNT *pRowsCopied) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPInit(
/* [string][in] */ const wchar_t *pwszTable,
/* [string][in] */ const wchar_t *pwszDataFile,
/* [string][in] */ const wchar_t *pwszErrorFile,
/* [in] */ int eDirection) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPReadFmt(
/* [string][in] */ const wchar_t *pwszFormatFile) = 0;
virtual HRESULT STDMETHODCALLTYPE BCPWriteFmt(
/* [string][in] */ const wchar_t *pwszFormatFile) = 0;
};
#else /* C style interface */
typedef struct IBCPSessionVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IBCPSession * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IBCPSession * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IBCPSession * This);
HRESULT ( STDMETHODCALLTYPE *BCPColFmt )(
IBCPSession * This,
/* [in] */ DBORDINAL idxUserDataCol,
/* [in] */ int eUserDataType,
/* [in] */ int cbIndicator,
/* [in] */ int cbUserData,
/* [size_is][in] */ BYTE *pbUserDataTerm,
/* [in] */ int cbUserDataTerm,
/* [in] */ DBORDINAL idxServerCol);
HRESULT ( STDMETHODCALLTYPE *BCPColumns )(
IBCPSession * This,
/* [in] */ DBCOUNTITEM nColumns);
HRESULT ( STDMETHODCALLTYPE *BCPControl )(
IBCPSession * This,
/* [in] */ int eOption,
/* [in] */ void *iValue);
HRESULT ( STDMETHODCALLTYPE *BCPDone )(
IBCPSession * This);
HRESULT ( STDMETHODCALLTYPE *BCPExec )(
IBCPSession * This,
/* [out] */ DBROWCOUNT *pRowsCopied);
HRESULT ( STDMETHODCALLTYPE *BCPInit )(
IBCPSession * This,
/* [string][in] */ const wchar_t *pwszTable,
/* [string][in] */ const wchar_t *pwszDataFile,
/* [string][in] */ const wchar_t *pwszErrorFile,
/* [in] */ int eDirection);
HRESULT ( STDMETHODCALLTYPE *BCPReadFmt )(
IBCPSession * This,
/* [string][in] */ const wchar_t *pwszFormatFile);
HRESULT ( STDMETHODCALLTYPE *BCPWriteFmt )(
IBCPSession * This,
/* [string][in] */ const wchar_t *pwszFormatFile);
END_INTERFACE
} IBCPSessionVtbl;
interface IBCPSession
{
CONST_VTBL struct IBCPSessionVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IBCPSession_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IBCPSession_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IBCPSession_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IBCPSession_BCPColFmt(This,idxUserDataCol,eUserDataType,cbIndicator,cbUserData,pbUserDataTerm,cbUserDataTerm,idxServerCol) \
( (This)->lpVtbl -> BCPColFmt(This,idxUserDataCol,eUserDataType,cbIndicator,cbUserData,pbUserDataTerm,cbUserDataTerm,idxServerCol) )
#define IBCPSession_BCPColumns(This,nColumns) \
( (This)->lpVtbl -> BCPColumns(This,nColumns) )
#define IBCPSession_BCPControl(This,eOption,iValue) \
( (This)->lpVtbl -> BCPControl(This,eOption,iValue) )
#define IBCPSession_BCPDone(This) \
( (This)->lpVtbl -> BCPDone(This) )
#define IBCPSession_BCPExec(This,pRowsCopied) \
( (This)->lpVtbl -> BCPExec(This,pRowsCopied) )
#define IBCPSession_BCPInit(This,pwszTable,pwszDataFile,pwszErrorFile,eDirection) \
( (This)->lpVtbl -> BCPInit(This,pwszTable,pwszDataFile,pwszErrorFile,eDirection) )
#define IBCPSession_BCPReadFmt(This,pwszFormatFile) \
( (This)->lpVtbl -> BCPReadFmt(This,pwszFormatFile) )
#define IBCPSession_BCPWriteFmt(This,pwszFormatFile) \
( (This)->lpVtbl -> BCPWriteFmt(This,pwszFormatFile) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __IBCPSession_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0006 */
/* [local] */
#endif //_SQLOLEDB_H_
#define ISOLATIONLEVEL_SNAPSHOT ((ISOLATIONLEVEL)(0x01000000)) // Changes made in other transactions can not be seen.
#define DBPROPVAL_TI_SNAPSHOT 0x01000000L
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0006_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0006_v0_0_s_ifspec;
#ifndef __ISSAbort_INTERFACE_DEFINED__
#define __ISSAbort_INTERFACE_DEFINED__
/* interface ISSAbort */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISSAbort;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("5CF4CA15-EF21-11d0-97E7-00C04FC2AD98")
ISSAbort : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0;
};
#else /* C style interface */
typedef struct ISSAbortVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISSAbort * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISSAbort * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISSAbort * This);
HRESULT ( STDMETHODCALLTYPE *Abort )(
ISSAbort * This);
END_INTERFACE
} ISSAbortVtbl;
interface ISSAbort
{
CONST_VTBL struct ISSAbortVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISSAbort_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISSAbort_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISSAbort_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISSAbort_Abort(This) \
( (This)->lpVtbl -> Abort(This) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISSAbort_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0007 */
/* [local] */
enum DBBINDFLAGENUM90
{ DBBINDFLAG_OBJECT = 0x2
} ;
enum SSACCESSORFLAGS
{ SSACCESSOR_ROWDATA = 0x100
} ;
enum DBPROPFLAGSENUM90
{ DBPROPFLAGS_PARAMETER = 0x10000
} ;
typedef struct tagSSPARAMPROPS
{
DBORDINAL iOrdinal;
ULONG cPropertySets;
DBPROPSET *rgPropertySets;
} SSPARAMPROPS;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0007_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0007_v0_0_s_ifspec;
#ifndef __ISSCommandWithParameters_INTERFACE_DEFINED__
#define __ISSCommandWithParameters_INTERFACE_DEFINED__
/* interface ISSCommandWithParameters */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISSCommandWithParameters;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("eec30162-6087-467c-b995-7c523ce96561")
ISSCommandWithParameters : public ICommandWithParameters
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetParameterProperties(
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ SSPARAMPROPS **prgParamProperties) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE SetParameterProperties(
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ SSPARAMPROPS rgParamProperties[ ]) = 0;
};
#else /* C style interface */
typedef struct ISSCommandWithParametersVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISSCommandWithParameters * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISSCommandWithParameters * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISSCommandWithParameters * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetParameterInfo )(
ISSCommandWithParameters * This,
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ DBPARAMINFO **prgParamInfo,
/* [out] */ OLECHAR **ppNamesBuffer);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *MapParameterNames )(
ISSCommandWithParameters * This,
/* [in] */ DB_UPARAMS cParamNames,
/* [size_is][in] */ const OLECHAR *rgParamNames[ ],
/* [size_is][out] */ DB_LPARAMS rgParamOrdinals[ ]);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetParameterInfo )(
ISSCommandWithParameters * This,
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ const DB_UPARAMS rgParamOrdinals[ ],
/* [size_is][unique][in] */ const DBPARAMBINDINFO rgParamBindInfo[ ]);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetParameterProperties )(
ISSCommandWithParameters * This,
/* [out][in] */ DB_UPARAMS *pcParams,
/* [size_is][size_is][out] */ SSPARAMPROPS **prgParamProperties);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *SetParameterProperties )(
ISSCommandWithParameters * This,
/* [in] */ DB_UPARAMS cParams,
/* [size_is][unique][in] */ SSPARAMPROPS rgParamProperties[ ]);
END_INTERFACE
} ISSCommandWithParametersVtbl;
interface ISSCommandWithParameters
{
CONST_VTBL struct ISSCommandWithParametersVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISSCommandWithParameters_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISSCommandWithParameters_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISSCommandWithParameters_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISSCommandWithParameters_GetParameterInfo(This,pcParams,prgParamInfo,ppNamesBuffer) \
( (This)->lpVtbl -> GetParameterInfo(This,pcParams,prgParamInfo,ppNamesBuffer) )
#define ISSCommandWithParameters_MapParameterNames(This,cParamNames,rgParamNames,rgParamOrdinals) \
( (This)->lpVtbl -> MapParameterNames(This,cParamNames,rgParamNames,rgParamOrdinals) )
#define ISSCommandWithParameters_SetParameterInfo(This,cParams,rgParamOrdinals,rgParamBindInfo) \
( (This)->lpVtbl -> SetParameterInfo(This,cParams,rgParamOrdinals,rgParamBindInfo) )
#define ISSCommandWithParameters_GetParameterProperties(This,pcParams,prgParamProperties) \
( (This)->lpVtbl -> GetParameterProperties(This,pcParams,prgParamProperties) )
#define ISSCommandWithParameters_SetParameterProperties(This,cParams,rgParamProperties) \
( (This)->lpVtbl -> SetParameterProperties(This,cParams,rgParamProperties) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISSCommandWithParameters_INTERFACE_DEFINED__ */
#ifndef __IDBAsynchStatus_INTERFACE_DEFINED__
#define __IDBAsynchStatus_INTERFACE_DEFINED__
/* interface IDBAsynchStatus */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_IDBAsynchStatus;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("0c733a95-2a1c-11ce-ade5-00aa0044773d")
IDBAsynchStatus : public IUnknown
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Abort(
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation) = 0;
virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetStatus(
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [out] */ DBCOUNTITEM *pulProgress,
/* [out] */ DBCOUNTITEM *pulProgressMax,
/* [out] */ DBASYNCHPHASE *peAsynchPhase,
/* [out] */ LPOLESTR *ppwszStatusText) = 0;
};
#else /* C style interface */
typedef struct IDBAsynchStatusVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IDBAsynchStatus * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IDBAsynchStatus * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IDBAsynchStatus * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Abort )(
IDBAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetStatus )(
IDBAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [out] */ DBCOUNTITEM *pulProgress,
/* [out] */ DBCOUNTITEM *pulProgressMax,
/* [out] */ DBASYNCHPHASE *peAsynchPhase,
/* [out] */ LPOLESTR *ppwszStatusText);
END_INTERFACE
} IDBAsynchStatusVtbl;
interface IDBAsynchStatus
{
CONST_VTBL struct IDBAsynchStatusVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IDBAsynchStatus_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define IDBAsynchStatus_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define IDBAsynchStatus_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define IDBAsynchStatus_Abort(This,hChapter,eOperation) \
( (This)->lpVtbl -> Abort(This,hChapter,eOperation) )
#define IDBAsynchStatus_GetStatus(This,hChapter,eOperation,pulProgress,pulProgressMax,peAsynchPhase,ppwszStatusText) \
( (This)->lpVtbl -> GetStatus(This,hChapter,eOperation,pulProgress,pulProgressMax,peAsynchPhase,ppwszStatusText) )
#endif /* COBJMACROS */
#endif /* C style interface */
/* [call_as] */ HRESULT STDMETHODCALLTYPE IDBAsynchStatus_RemoteAbort_Proxy(
IDBAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB IDBAsynchStatus_RemoteAbort_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
/* [call_as] */ HRESULT STDMETHODCALLTYPE IDBAsynchStatus_RemoteGetStatus_Proxy(
IDBAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [unique][out][in] */ DBCOUNTITEM *pulProgress,
/* [unique][out][in] */ DBCOUNTITEM *pulProgressMax,
/* [unique][out][in] */ DBASYNCHPHASE *peAsynchPhase,
/* [unique][out][in] */ LPOLESTR *ppwszStatusText,
/* [out] */ IErrorInfo **ppErrorInfoRem);
void __RPC_STUB IDBAsynchStatus_RemoteGetStatus_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __IDBAsynchStatus_INTERFACE_DEFINED__ */
#ifndef __ISSAsynchStatus_INTERFACE_DEFINED__
#define __ISSAsynchStatus_INTERFACE_DEFINED__
/* interface ISSAsynchStatus */
/* [unique][uuid][object][local] */
EXTERN_C const IID IID_ISSAsynchStatus;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("1FF1F743-8BB0-4c00-ACC4-C10E43B08FC1")
ISSAsynchStatus : public IDBAsynchStatus
{
public:
virtual /* [local] */ HRESULT STDMETHODCALLTYPE WaitForAsynchCompletion(
/* [in] */ DWORD dwMillisecTimeOut) = 0;
};
#else /* C style interface */
typedef struct ISSAsynchStatusVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
ISSAsynchStatus * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */
__RPC__deref_out void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
ISSAsynchStatus * This);
ULONG ( STDMETHODCALLTYPE *Release )(
ISSAsynchStatus * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Abort )(
ISSAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *GetStatus )(
ISSAsynchStatus * This,
/* [in] */ HCHAPTER hChapter,
/* [in] */ DBASYNCHOP eOperation,
/* [out] */ DBCOUNTITEM *pulProgress,
/* [out] */ DBCOUNTITEM *pulProgressMax,
/* [out] */ DBASYNCHPHASE *peAsynchPhase,
/* [out] */ LPOLESTR *ppwszStatusText);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *WaitForAsynchCompletion )(
ISSAsynchStatus * This,
/* [in] */ DWORD dwMillisecTimeOut);
END_INTERFACE
} ISSAsynchStatusVtbl;
interface ISSAsynchStatus
{
CONST_VTBL struct ISSAsynchStatusVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define ISSAsynchStatus_QueryInterface(This,riid,ppvObject) \
( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
#define ISSAsynchStatus_AddRef(This) \
( (This)->lpVtbl -> AddRef(This) )
#define ISSAsynchStatus_Release(This) \
( (This)->lpVtbl -> Release(This) )
#define ISSAsynchStatus_Abort(This,hChapter,eOperation) \
( (This)->lpVtbl -> Abort(This,hChapter,eOperation) )
#define ISSAsynchStatus_GetStatus(This,hChapter,eOperation,pulProgress,pulProgressMax,peAsynchPhase,ppwszStatusText) \
( (This)->lpVtbl -> GetStatus(This,hChapter,eOperation,pulProgress,pulProgressMax,peAsynchPhase,ppwszStatusText) )
#define ISSAsynchStatus_WaitForAsynchCompletion(This,dwMillisecTimeOut) \
( (This)->lpVtbl -> WaitForAsynchCompletion(This,dwMillisecTimeOut) )
#endif /* COBJMACROS */
#endif /* C style interface */
#endif /* __ISSAsynchStatus_INTERFACE_DEFINED__ */
/* interface __MIDL_itf_sqlncli_0000_0010 */
/* [local] */
//----------------------------------------------------------------------------
// Values for STATUS bitmask for DBSCHEMA_TABLES & DBSCHEMA_TABLES_INFO
#define TABLE_HAS_UPDATE_INSTEAD_OF_TRIGGER 0x00000001 //table has IOT defined
#define TABLE_HAS_DELETE_INSTEAD_OF_TRIGGER 0x00000002 //table has IOT defined
#define TABLE_HAS_INSERT_INSTEAD_OF_TRIGGER 0x00000004 //table has IOT defined
#define TABLE_HAS_AFTER_UPDATE_TRIGGER 0x00000008 //table has update trigger
#define TABLE_HAS_AFTER_DELETE_TRIGGER 0x00000010 //table has delete trigger
#define TABLE_HAS_AFTER_INSERT_TRIGGER 0x00000020 //table has insert trigger
#define TABLE_HAS_CASCADE_UPDATE 0x00000040 //table has cascade update
#define TABLE_HAS_CASCADE_DELETE 0x00000080 //table has cascade delete
//----------------------------------------------------------------------------
// PropIds for DBPROP_INIT_GENERALTIMEOUT
#if (OLEDBVER >= 0x0210)
#define DBPROP_INIT_GENERALTIMEOUT 0x11cL
#endif
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERDATASOURCE
#define SSPROP_ENABLEFASTLOAD 2
#define SSPROP_ENABLEBULKCOPY 3
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERDATASOURCEINFO
#define SSPROP_UNICODELCID 2
#define SSPROP_UNICODECOMPARISONSTYLE 3
#define SSPROP_COLUMNLEVELCOLLATION 4
#define SSPROP_CHARACTERSET 5
#define SSPROP_SORTORDER 6
#define SSPROP_CURRENTCOLLATION 7
#define SSPROP_INTEGRATEDAUTHENTICATIONMETHOD 8
#define SSPROP_MUTUALLYAUTHENTICATED 9
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERDBINIT
#define SSPROP_INIT_CURRENTLANGUAGE 4
#define SSPROP_INIT_NETWORKADDRESS 5
#define SSPROP_INIT_NETWORKLIBRARY 6
#define SSPROP_INIT_USEPROCFORPREP 7
#define SSPROP_INIT_AUTOTRANSLATE 8
#define SSPROP_INIT_PACKETSIZE 9
#define SSPROP_INIT_APPNAME 10
#define SSPROP_INIT_WSID 11
#define SSPROP_INIT_FILENAME 12
#define SSPROP_INIT_ENCRYPT 13
#define SSPROP_AUTH_REPL_SERVER_NAME 14
#define SSPROP_INIT_TAGCOLUMNCOLLATION 15
#define SSPROP_INIT_MARSCONNECTION 16
#define SSPROP_INIT_FAILOVERPARTNER 18
#define SSPROP_AUTH_OLD_PASSWORD 19
#define SSPROP_INIT_DATATYPECOMPATIBILITY 20
#define SSPROP_INIT_TRUST_SERVER_CERTIFICATE 21
#define SSPROP_INIT_SERVERSPN 22
#define SSPROP_INIT_FAILOVERPARTNERSPN 23
//-----------------------------------------------------------------------------
// Values for SSPROP_INIT_USEPROCFORPREP
#define SSPROPVAL_USEPROCFORPREP_OFF 0
#define SSPROPVAL_USEPROCFORPREP_ON 1
#define SSPROPVAL_USEPROCFORPREP_ON_DROP 2
//-----------------------------------------------------------------------------
// Values for SSPROP_INIT_DATATYPECOMPATIBILITY
#define SSPROPVAL_DATATYPECOMPATIBILITY_SQL2000 80
#define SSPROPVAL_DATATYPECOMPATIBILITY_DEFAULT 0
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERSESSION
#define SSPROP_QUOTEDCATALOGNAMES 2
#define SSPROP_ALLOWNATIVEVARIANT 3
#define SSPROP_SQLXMLXPROGID 4
#define SSPROP_ASYNCH_BULKCOPY 5
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERROWSET
#define SSPROP_MAXBLOBLENGTH 8
#define SSPROP_FASTLOADOPTIONS 9
#define SSPROP_FASTLOADKEEPNULLS 10
#define SSPROP_FASTLOADKEEPIDENTITY 11
#define SSPROP_CURSORAUTOFETCH 12
#define SSPROP_DEFERPREPARE 13
#define SSPROP_IRowsetFastLoad 14
#define SSPROP_QP_NOTIFICATION_TIMEOUT 17
#define SSPROP_QP_NOTIFICATION_MSGTEXT 18
#define SSPROP_QP_NOTIFICATION_OPTIONS 19
#define SSPROP_NOCOUNT_STATUS 20
#define SSPROP_COMPUTE_ID 21
#define SSPROP_COLUMN_ID 22
#define SSPROP_COMPUTE_BYLIST 23
#define SSPROP_ISSAsynchStatus 24
//-----------------------------------------------------------------------------
// Values for SSPROP_QP_NOTIFICATION_TIMEOUT
#define SSPROPVAL_DEFAULT_NOTIFICATION_TIMEOUT 432000 /* in sec */
#define SSPROPVAL_MAX_NOTIFICATION_TIMEOUT 0x7FFFFFFF /* in sec */
#define MAX_NOTIFICATION_LEN 2000 /* NVARCHAR [2000] for both ID & DELIVERY_QUEUE */
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERCOLUMN
#define SSPROP_COL_COLLATIONNAME 14
#define SSPROP_COL_UDT_CATALOGNAME 31
#define SSPROP_COL_UDT_SCHEMANAME 32
#define SSPROP_COL_UDT_NAME 33
#define SSPROP_COL_XML_SCHEMACOLLECTION_CATALOGNAME 34
#define SSPROP_COL_XML_SCHEMACOLLECTION_SCHEMANAME 35
#define SSPROP_COL_XML_SCHEMACOLLECTIONNAME 36
#define SSPROP_COL_COMPUTED 37
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERSTREAM
#define SSPROP_STREAM_XMLROOT 19
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERPARAMETER
#define SSPROP_PARAM_XML_SCHEMACOLLECTION_CATALOGNAME 24
#define SSPROP_PARAM_XML_SCHEMACOLLECTION_SCHEMANAME 25
#define SSPROP_PARAM_XML_SCHEMACOLLECTIONNAME 26
#define SSPROP_PARAM_UDT_CATALOGNAME 27
#define SSPROP_PARAM_UDT_SCHEMANAME 28
#define SSPROP_PARAM_UDT_NAME 29
#define SSPROP_PARAM_TYPE_CATALOGNAME 38
#define SSPROP_PARAM_TYPE_SCHEMANAME 39
#define SSPROP_PARAM_TYPE_TYPENAME 40
#define SSPROP_PARAM_TABLE_DEFAULT_COLUMNS 41
#define SSPROP_PARAM_TABLE_COLUMN_SORT_ORDER 42
//----------------------------------------------------------------------------
// PropIds for DBPROPSET_SQLSERVERINDEX
#define SSPROP_INDEX_XML 1
//-----------------------------------------------------------------------------
//
#define BCP_TYPE_DEFAULT 0x00
#define BCP_TYPE_SQLTEXT 0x23
#define BCP_TYPE_SQLVARBINARY 0x25
#define BCP_TYPE_SQLINTN 0x26
#define BCP_TYPE_SQLVARCHAR 0x27
#define BCP_TYPE_SQLBINARY 0x2d
#define BCP_TYPE_SQLIMAGE 0x22
#define BCP_TYPE_SQLCHARACTER 0x2f
#define BCP_TYPE_SQLINT1 0x30
#define BCP_TYPE_SQLBIT 0x32
#define BCP_TYPE_SQLINT2 0x34
#define BCP_TYPE_SQLINT4 0x38
#define BCP_TYPE_SQLMONEY 0x3c
#define BCP_TYPE_SQLDATETIME 0x3d
#define BCP_TYPE_SQLFLT8 0x3e
#define BCP_TYPE_SQLFLTN 0x6d
#define BCP_TYPE_SQLMONEYN 0x6e
#define BCP_TYPE_SQLDATETIMN 0x6f
#define BCP_TYPE_SQLFLT4 0x3b
#define BCP_TYPE_SQLMONEY4 0x7a
#define BCP_TYPE_SQLDATETIM4 0x3a
#define BCP_TYPE_SQLDECIMAL 0x6a
#define BCP_TYPE_SQLNUMERIC 0x6c
#define BCP_TYPE_SQLUNIQUEID 0x24
#define BCP_TYPE_SQLBIGCHAR 0xaf
#define BCP_TYPE_SQLBIGVARCHAR 0xa7
#define BCP_TYPE_SQLBIGBINARY 0xad
#define BCP_TYPE_SQLBIGVARBINARY 0xa5
#define BCP_TYPE_SQLBITN 0x68
#define BCP_TYPE_SQLNCHAR 0xef
#define BCP_TYPE_SQLNVARCHAR 0xe7
#define BCP_TYPE_SQLNTEXT 0x63
#define BCP_TYPE_SQLDECIMALN 0x6a
#define BCP_TYPE_SQLNUMERICN 0x6c
#define BCP_TYPE_SQLINT8 0x7f
#define BCP_TYPE_SQLVARIANT 0x62
#define BCP_TYPE_SQLUDT 0xf0
#define BCP_TYPE_SQLXML 0xf1
#define BCP_TYPE_SQLDATE 0x28
#define BCP_TYPE_SQLTIME 0x29
#define BCP_TYPE_SQLDATETIME2 0x2a
#define BCP_TYPE_SQLDATETIMEOFFSET 0x2b
#define BCP_DIRECTION_IN 1
#define BCP_DIRECTION_OUT 2
#define BCP_OPTION_MAXERRS 1
#define BCP_OPTION_FIRST 2
#define BCP_OPTION_LAST 3
#define BCP_OPTION_BATCH 4
#define BCP_OPTION_KEEPNULLS 5
#define BCP_OPTION_ABORT 6
#define BCP_OPTION_KEEPIDENTITY 8
#define BCP_OPTION_HINTSA 10
#define BCP_OPTION_HINTSW 11
#define BCP_OPTION_FILECP 12
#define BCP_OPTION_UNICODEFILE 13
#define BCP_OPTION_TEXTFILE 14
#define BCP_OPTION_FILEFMT 15
#define BCP_OPTION_FMTXML 16
#define BCP_OPTION_FIRSTEX 17
#define BCP_OPTION_LASTEX 18
#define BCP_OPTION_ROWCOUNT 19
#define BCP_FILECP_ACP 0
#define BCP_FILECP_OEMCP 1
#define BCP_FILECP_RAW (-1)
#ifdef UNICODE
#define BCP_OPTION_HINTS BCP_OPTION_HINTSW
#else
#define BCP_OPTION_HINTS BCP_OPTION_HINTSA
#endif
#define BCP_PREFIX_DEFAULT (-10)
#define BCP_LENGTH_NULL (-1)
#define BCP_LENGTH_VARIABLE (-10)
//
//-----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Provider-specific Class Ids
//
#if SQLNCLI_VER >= 1000
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI10 = {0x8F4A6B68L,0x4F36,0x4e3c,{0xBE,0x81,0xBC,0x7C,0xA4,0xE9,0xC4,0x5C}};
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI10_ERROR = {0x53F9C3BCL,0x275F,0x4FA5,{0xB3,0xE6,0x25,0xED,0xCD,0x51,0x20,0x23}};
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI10_ENUMERATOR = {0x91E4F2A5L,0x1B07,0x45f6,{0x86,0xBF,0x92,0x03,0xC7,0xC7,0x2B,0xE3}};
#endif
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI = {0x85ecafccL,0xbdd9,0x4b03,{0x97,0xa8,0xfa,0x65,0xcb,0xe3,0x85,0x9b}};
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI_ERROR = {0xe8bc0a7aL,0xea71,0x4263,{0x8c,0xda,0x94,0xf3,0x88,0xb8,0xed,0x10}};
extern const GUID OLEDBDECLSPEC CLSID_SQLNCLI_ENUMERATOR = {0x4898ad37L,0xfe05,0x42df,{0x92,0xf9,0xe8,0x57,0xdd,0xfe,0xe7,0x30}};
extern const GUID OLEDBDECLSPEC CLSID_ROWSET_TVP = {0xc7ef28d5L,0x7bee,0x443f,{0x86,0xda,0xe3,0x98,0x4f,0xcd,0x4d,0xf9}};
//----------------------------------------------------------------------------
// Provider-specific Interface Ids
//
#ifndef _SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC IID_ISQLServerErrorInfo = {0x5cf4ca12,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC IID_IRowsetFastLoad = {0x5cf4ca13,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC IID_IUMSInitialize = {0x5cf4ca14,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC IID_ISchemaLock = {0x4c2389fb,0x2511,0x11d4,{0xb2,0x58,0x0,0xc0,0x4f,0x79,0x71,0xce}};
extern const GUID OLEDBDECLSPEC IID_ISQLXMLHelper = {0xd22a7678L,0xf860,0x40cd,{0xa5,0x67,0x15,0x63,0xde,0xb4,0x6d,0x49}};
#endif //_SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC IID_ISSAbort = {0x5cf4ca15,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC IID_IBCPSession = {0x88352D80,0x42D1,0x42f0,{0xA1,0x70,0xAB,0x0F,0x8B,0x45,0xB9,0x39}};
extern const GUID OLEDBDECLSPEC IID_ISSCommandWithParameters = {0xeec30162,0x6087,0x467c,{0xb9,0x95,0x7c,0x52,0x3c,0xe9,0x65,0x61}};
extern const GUID OLEDBDECLSPEC IID_ISSAsynchStatus = {0x1FF1F743,0x8BB0, 0x4c00,{0xAC,0xC4,0xC1,0x0E,0x43,0xB0,0x8F,0xC1}};
//----------------------------------------------------------------------------
// Provider-specific schema rowsets
//
#ifndef _SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC DBSCHEMA_LINKEDSERVERS = {0x9093caf4,0x2eac,0x11d1,{0x98,0x9,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
#endif //_SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_ASSEMBLIES = {0x7c1112c8, 0xc2d3, 0x4f6e, {0x94, 0x9a, 0x98, 0x3d, 0x38, 0xa5, 0x8f, 0x46}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_ASSEMBLY_DEPENDENCIES = {0xcb0f837b, 0x974c, 0x41b8, {0x90, 0x9d, 0x64, 0x9c, 0xaf, 0x45, 0xad, 0x2f}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_USER_TYPES = {0xf1198bd8, 0xa424, 0x4ea3, {0x8d, 0x4c, 0x60, 0x7e, 0xee, 0x2b, 0xab, 0x60}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_XML_COLLECTIONS = {0x56bfad8c, 0x6e8f, 0x480d, {0x91, 0xde, 0x35, 0x16, 0xd9, 0x9a, 0x5d, 0x10}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_TABLE_TYPES = {0x4e26cde7, 0xaaa4, 0x41ed, {0x93, 0xdd, 0x37, 0x6e, 0x6d, 0x40, 0x9c, 0x17}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_TABLE_TYPE_PRIMARY_KEYS = {0x9738faea, 0x31e8, 0x4f63, {0xae, 0xd, 0x61, 0x33, 0x16, 0x41, 0x8c, 0xdd}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SQL_TABLE_TYPE_COLUMNS = {0xa663d94b, 0xddf7, 0x4a7f, {0xa5, 0x37, 0xd6, 0x1f, 0x12, 0x36, 0x5d, 0x7c}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_COLUMNS_EXTENDED = {0x66462f01, 0x633a, 0x44d9, {0xb0, 0xd0, 0xfe, 0x66, 0xf2, 0x1a, 0x0d, 0x24}};
extern const GUID OLEDBDECLSPEC DBSCHEMA_SPARSE_COLUMN_SET = {0x31a4837c, 0xf9ff, 0x405f, {0x89, 0x82, 0x02, 0x19, 0xaa, 0xaa, 0x4a, 0x12}};
#ifndef CRESTRICTIONS_DBSCHEMA_LINKEDSERVERS
#define CRESTRICTIONS_DBSCHEMA_LINKEDSERVERS 1
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_ASSEMBLIES
#define CRESTRICTIONS_DBSCHEMA_SQL_ASSEMBLIES 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_ASSEMBLY_DEPENDENCIES
#define CRESTRICTIONS_DBSCHEMA_SQL_ASSEMBLY_DEPENDENCIES 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_USER_TYPES
#define CRESTRICTIONS_DBSCHEMA_SQL_USER_TYPES 3
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_XML_COLLECTIONS
#define CRESTRICTIONS_DBSCHEMA_XML_COLLECTIONS 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPES
#define CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPES 3
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPE_PRIMARY_KEYS
#define CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPE_PRIMARY_KEYS 3
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPE_COLUMNS
#define CRESTRICTIONS_DBSCHEMA_SQL_TABLE_TYPE_COLUMNS 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_COLUMNS_EXTENDED
#define CRESTRICTIONS_DBSCHEMA_COLUMNS_EXTENDED 4
#endif
#ifndef CRESTRICTIONS_DBSCHEMA_SPARSE_COLUMN_SET
#define CRESTRICTIONS_DBSCHEMA_SPARSE_COLUMN_SET 4
#endif
//----------------------------------------------------------------------------
// Provider-specific property sets
//
#ifndef _SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERDATASOURCE = {0x28efaee4,0x2d2c,0x11d1,{0x98,0x7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERDATASOURCEINFO= {0xdf10cb94,0x35f6,0x11d2,{0x9c,0x54,0x0,0xc0,0x4f,0x79,0x71,0xd3}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERDBINIT = {0x5cf4ca10,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERROWSET = {0x5cf4ca11,0xef21,0x11d0,{0x97,0xe7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERSESSION = {0x28efaee5,0x2d2c,0x11d1,{0x98,0x7,0x0,0xc0,0x4f,0xc2,0xad,0x98}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERCOLUMN = {0x3b63fb5e,0x3fbb,0x11d3,{0x9f,0x29,0x0,0xc0,0x4f,0x8e,0xe9,0xdc}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERSTREAM = {0x9f79c073,0x8a6d,0x4bca,{0xa8,0xa8,0xc9,0xb7,0x9a,0x9b,0x96,0x2d}};
#endif //_SQLOLEDB_H_
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERPARAMETER = {0xfee09128,0xa67d,0x47ea,{0x8d,0x40,0x24,0xa1,0xd4,0x73,0x7e,0x8d}};
extern const GUID OLEDBDECLSPEC DBPROPSET_SQLSERVERINDEX = {0xE428B84E,0xA6B7,0x413a,{0x94,0x65,0x56,0x23,0x2E,0x0D,0x2B,0xEB}};
extern const GUID OLEDBDECLSPEC DBPROPSET_PARAMETERALL = {0x2cd2b7d8,0xe7c2,0x4f6c,{0x9b,0x30,0x75,0xe2,0x58,0x46,0x10,0x97}};
//----------------------------------------------------------------------------
// Provider-specific columns for IColumnsRowset
//
#define DBCOLUMN_SS_X_GUID {0x627bd890,0xed54,0x11d2,{0xb9,0x94,0x0,0xc0,0x4f,0x8c,0xa8,0x2c}}
//
#ifndef _SQLOLEDB_H_
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_COMPFLAGS = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)100};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_SORTID = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)101};
extern const DBID OLEDBDECLSPEC DBCOLUMN_BASETABLEINSTANCE = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)102};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_TDSCOLLATION = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)103};
#endif //_SQLOLEDB_H_
extern const DBID OLEDBDECLSPEC DBCOLUMN_BASESERVERNAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)104};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_XML_SCHEMACOLLECTION_CATALOGNAME= {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)105};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_XML_SCHEMACOLLECTION_SCHEMANAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)106};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_XML_SCHEMACOLLECTIONNAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)107};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_UDT_CATALOGNAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)108};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_UDT_SCHEMANAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)109};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_UDT_NAME = {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)110};
extern const DBID OLEDBDECLSPEC DBCOLUMN_SS_ASSEMBLY_TYPENAME= {DBCOLUMN_SS_X_GUID, DBKIND_GUID_PROPID, (LPOLESTR)111};
// OLEDB part of SQL Server Native Client header - end here!
#endif // defined(_SQLNCLI_OLEDB_) || !defined(_SQLNCLI_ODBC_)
// ODBC part of SQL Server Native Client header - begin here!
#if defined(_SQLNCLI_ODBC_) || !defined(_SQLNCLI_OLEDB_)
#ifdef ODBCVER
// max SQL Server identifier length
#define SQL_MAX_SQLSERVERNAME 128
// SQLSetConnectAttr driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server Native Client driver usage.
// Connection attributes
#define SQL_COPT_SS_BASE 1200
#define SQL_COPT_SS_REMOTE_PWD (SQL_COPT_SS_BASE+1) // dbrpwset SQLSetConnectOption only
#define SQL_COPT_SS_USE_PROC_FOR_PREP (SQL_COPT_SS_BASE+2) // Use create proc for SQLPrepare
#define SQL_COPT_SS_INTEGRATED_SECURITY (SQL_COPT_SS_BASE+3) // Force integrated security on login
#define SQL_COPT_SS_PRESERVE_CURSORS (SQL_COPT_SS_BASE+4) // Preserve server cursors after SQLTransact
#define SQL_COPT_SS_USER_DATA (SQL_COPT_SS_BASE+5) // dbgetuserdata/dbsetuserdata
#define SQL_COPT_SS_ENLIST_IN_DTC SQL_ATTR_ENLIST_IN_DTC // Enlist in a DTC transaction
#define SQL_COPT_SS_ENLIST_IN_XA SQL_ATTR_ENLIST_IN_XA // Enlist in a XA transaction
#define SQL_COPT_SS_FALLBACK_CONNECT (SQL_COPT_SS_BASE+10) // Enables FallBack connections
#define SQL_COPT_SS_PERF_DATA (SQL_COPT_SS_BASE+11) // Used to access SQL Server ODBC driver performance data
#define SQL_COPT_SS_PERF_DATA_LOG (SQL_COPT_SS_BASE+12) // Used to set the logfile name for the Performance data
#define SQL_COPT_SS_PERF_QUERY_INTERVAL (SQL_COPT_SS_BASE+13) // Used to set the query logging threshold in milliseconds.
#define SQL_COPT_SS_PERF_QUERY_LOG (SQL_COPT_SS_BASE+14) // Used to set the logfile name for saving queryies.
#define SQL_COPT_SS_PERF_QUERY (SQL_COPT_SS_BASE+15) // Used to start and stop query logging.
#define SQL_COPT_SS_PERF_DATA_LOG_NOW (SQL_COPT_SS_BASE+16) // Used to make a statistics log entry to disk.
#define SQL_COPT_SS_QUOTED_IDENT (SQL_COPT_SS_BASE+17) // Enable/Disable Quoted Identifiers
#define SQL_COPT_SS_ANSI_NPW (SQL_COPT_SS_BASE+18) // Enable/Disable ANSI NULL, Padding and Warnings
#define SQL_COPT_SS_BCP (SQL_COPT_SS_BASE+19) // Allow BCP usage on connection
#define SQL_COPT_SS_TRANSLATE (SQL_COPT_SS_BASE+20) // Perform code page translation
#define SQL_COPT_SS_ATTACHDBFILENAME (SQL_COPT_SS_BASE+21) // File name to be attached as a database
#define SQL_COPT_SS_CONCAT_NULL (SQL_COPT_SS_BASE+22) // Enable/Disable CONCAT_NULL_YIELDS_NULL
#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_FAILOVER_PARTNER (SQL_COPT_SS_BASE+25) // Failover partner server
#define SQL_COPT_SS_OLDPWD (SQL_COPT_SS_BASE+26) // Old Password, used when changing password during login
#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
#define SQL_COPT_SS_SERVER_SPN (SQL_COPT_SS_BASE+29) // Server SPN
#define SQL_COPT_SS_FAILOVER_PARTNER_SPN (SQL_COPT_SS_BASE+30) // Failover partner server SPN
#define SQL_COPT_SS_INTEGRATED_AUTHENTICATION_METHOD (SQL_COPT_SS_BASE+31) // The integrated authentication method used for the connection
#define SQL_COPT_SS_MUTUALLY_AUTHENTICATED (SQL_COPT_SS_BASE+32) // Used to decide if the connection is mutually authenticated
#define SQL_COPT_SS_MAX_USED SQL_COPT_SS_MUTUALLY_AUTHENTICATED
// Define old names
#define SQL_REMOTE_PWD SQL_COPT_SS_REMOTE_PWD
#define SQL_USE_PROCEDURE_FOR_PREPARE SQL_COPT_SS_USE_PROC_FOR_PREP
#define SQL_INTEGRATED_SECURITY SQL_COPT_SS_INTEGRATED_SECURITY
#define SQL_PRESERVE_CURSORS SQL_COPT_SS_PRESERVE_CURSORS
// SQLSetStmtAttr SQL Server Native Client driver 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_CURRENT_COMMAND (SQL_SOPT_SS_BASE+1) // dbcurcmd SQLGetStmtOption only
#define SQL_SOPT_SS_HIDDEN_COLUMNS (SQL_SOPT_SS_BASE+2) // Expose FOR BROWSE hidden columns
#define SQL_SOPT_SS_NOBROWSETABLE (SQL_SOPT_SS_BASE+3) // Set NOBROWSETABLE option
#define SQL_SOPT_SS_REGIONALIZE (SQL_SOPT_SS_BASE+4) // Regionalize output character conversions
#define SQL_SOPT_SS_CURSOR_OPTIONS (SQL_SOPT_SS_BASE+5) // Server cursor options
#define SQL_SOPT_SS_NOCOUNT_STATUS (SQL_SOPT_SS_BASE+6) // Real vs. Not Real row count indicator
#define SQL_SOPT_SS_DEFER_PREPARE (SQL_SOPT_SS_BASE+7) // Defer prepare until necessary
#define SQL_SOPT_SS_QUERYNOTIFICATION_TIMEOUT (SQL_SOPT_SS_BASE+8) // Notification timeout
#define SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT (SQL_SOPT_SS_BASE+9) // Notification message text
#define SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS (SQL_SOPT_SS_BASE+10)// SQL service broker name
#define SQL_SOPT_SS_PARAM_FOCUS (SQL_SOPT_SS_BASE+11)// Direct subsequent calls to parameter related methods to set properties on constituent columns/parameters of container types
#define SQL_SOPT_SS_NAME_SCOPE (SQL_SOPT_SS_BASE+12)// Sets name scope for subsequent catalog function calls
#define SQL_SOPT_SS_MAX_USED SQL_SOPT_SS_NAME_SCOPE
// Define old names
#define SQL_TEXTPTR_LOGGING SQL_SOPT_SS_TEXTPTR_LOGGING
#define SQL_COPT_SS_BASE_EX 1240
#define SQL_COPT_SS_BROWSE_CONNECT (SQL_COPT_SS_BASE_EX+1) // Browse connect mode of operation
#define SQL_COPT_SS_BROWSE_SERVER (SQL_COPT_SS_BASE_EX+2) // Single Server browse request.
#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_BROWSE_CACHE_DATA (SQL_COPT_SS_BASE_EX+5) // Determines if we should cache browse info. Used when returned buffer is greater then ODBC limit (32K)
#define SQL_COPT_SS_RESET_CONNECTION (SQL_COPT_SS_BASE_EX+6) // When this option is set, we will perform connection reset on next packet
#define SQL_COPT_SS_EX_MAX_USED SQL_COPT_SS_RESET_CONNECTION
// SQLColAttributes driver specific defines.
// SQLSetDescField/SQLGetDescField driver specific defines.
// Microsoft has 1200 thru 1249 reserved for Microsoft SQL Server Native Client driver 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_DESC_BASE_COLUMN_NAME_OLD (SQL_CA_SS_BASE+13) // This is defined at another location.
#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_UDT_ASSEMBLY_TYPE_NAME (SQL_CA_SS_BASE+21) // Qualified name of the assembly containing the UDT class
#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
// 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
#define SQL_CA_SS_MAX_USED (SQL_CA_SS_BASE+36)
// Defines returned by SQL_ATTR_CURSOR_TYPE/SQL_CURSOR_TYPE
#define SQL_CURSOR_FAST_FORWARD_ONLY 8 // Only returned by SQLGetStmtAttr/Option
// Defines for use with SQL_COPT_SS_USE_PROC_FOR_PREP
#define SQL_UP_OFF 0L // Procedures won't be used for prepare
#define SQL_UP_ON 1L // Procedures will be used for prepare
#define SQL_UP_ON_DROP 2L // Temp procedures will be explicitly dropped
#define SQL_UP_DEFAULT SQL_UP_ON
// 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_PRESERVE_CURSORS
#define SQL_PC_OFF 0L // Cursors are closed on SQLTransact
#define SQL_PC_ON 1L // Cursors remain open on SQLTransact
#define SQL_PC_DEFAULT SQL_PC_OFF
// Defines for use with SQL_COPT_SS_USER_DATA
#define SQL_UD_NOTSET NULL // No user data pointer set
// 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_COPT_SS_FALLBACK_CONNECT - Pre-Connect Option only
#define SQL_FB_OFF 0L // FallBack connections are disabled
#define SQL_FB_ON 1L // FallBack connections are enabled
#define SQL_FB_DEFAULT SQL_FB_OFF
// Defines for use with SQL_COPT_SS_BCP - Pre-Connect Option only
#define SQL_BCP_OFF 0L // BCP is not allowed on connection
#define SQL_BCP_ON 1L // BCP is allowed on connection
#define SQL_BCP_DEFAULT SQL_BCP_OFF
// Defines for use with SQL_COPT_SS_QUOTED_IDENT
#define SQL_QI_OFF 0L // Quoted identifiers are enable
#define SQL_QI_ON 1L // Quoted identifiers are disabled
#define SQL_QI_DEFAULT SQL_QI_ON
// Defines for use with SQL_COPT_SS_ANSI_NPW - Pre-Connect Option only
#define SQL_AD_OFF 0L // ANSI NULLs, Padding and Warnings are enabled
#define SQL_AD_ON 1L // ANSI NULLs, Padding and Warnings are disabled
#define SQL_AD_DEFAULT SQL_AD_ON
// Defines for use with SQL_COPT_SS_CONCAT_NULL - Pre-Connect Option only
#define SQL_CN_OFF 0L // CONCAT_NULL_YIELDS_NULL is off
#define SQL_CN_ON 1L // CONCAT_NULL_YIELDS_NULL is on
#define SQL_CN_DEFAULT SQL_CN_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
#define SQL_TL_DEFAULT SQL_TL_ON
// Defines for use with SQL_SOPT_SS_HIDDEN_COLUMNS
#define SQL_HC_OFF 0L // FOR BROWSE columns are hidden
#define SQL_HC_ON 1L // FOR BROWSE columns are exposed
#define SQL_HC_DEFAULT SQL_HC_OFF
// 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_REGIONALIZE
#define SQL_RE_OFF 0L // No regionalization occurs on output character conversions
#define SQL_RE_ON 1L // Regionalization occurs on output character conversions
#define SQL_RE_DEFAULT SQL_RE_OFF
// Defines for use with SQL_SOPT_SS_CURSOR_OPTIONS
#define SQL_CO_OFF 0L // Clear all cursor options
#define SQL_CO_FFO 1L // Fast-forward cursor will be used
#define SQL_CO_AF 2L // Autofetch on cursor open
#define SQL_CO_FFO_AF (SQL_CO_FFO|SQL_CO_AF) // Fast-forward cursor with autofetch
#define SQL_CO_FIREHOSE_AF 4L // Auto fetch on fire-hose cursors
#define SQL_CO_DEFAULT SQL_CO_OFF
//SQL_SOPT_SS_NOCOUNT_STATUS
#define SQL_NC_OFF 0L
#define SQL_NC_ON 1L
//SQL_SOPT_SS_DEFER_PREPARE
#define SQL_DP_OFF 0L
#define SQL_DP_ON 1L
//SQL_SOPT_SS_NAME_SCOPE
#define SQL_SS_NAME_SCOPE_TABLE 0L
#define SQL_SS_NAME_SCOPE_TABLE_TYPE 1L
#define SQL_SS_NAME_SCOPE_EXTENDED 2L
#define SQL_SS_NAME_SCOPE_SPARSE_COLUMN_SET 3L
#define SQL_SS_NAME_SCOPE_DEFAULT SQL_SS_NAME_SCOPE_TABLE
//SQL_COPT_SS_ENCRYPT
#define SQL_EN_OFF 0L
#define SQL_EN_ON 1L
//SQL_COPT_SS_TRUST_SERVER_CERTIFICATE
#define SQL_TRUST_SERVER_CERTIFICATE_NO 0L
#define SQL_TRUST_SERVER_CERTIFICATE_YES 1L
//SQL_COPT_SS_BROWSE_CONNECT
#define SQL_MORE_INFO_NO 0L
#define SQL_MORE_INFO_YES 1L
//SQL_COPT_SS_BROWSE_CACHE_DATA
#define SQL_CACHE_DATA_NO 0L
#define SQL_CACHE_DATA_YES 1L
//SQL_COPT_SS_RESET_CONNECTION
#define SQL_RESET_YES 1L
//SQL_COPT_SS_WARN_ON_CP_ERROR
#define SQL_WARN_NO 0L
#define SQL_WARN_YES 1L
//SQL_COPT_SS_MARS_ENABLED
#define SQL_MARS_ENABLED_NO 0L
#define SQL_MARS_ENABLED_YES 1L
/* SQL_TXN_ISOLATION_OPTION bitmasks */
#define SQL_TXN_SS_SNAPSHOT 0x00000020L
// 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 SQL Server Native Client driver usage.
#define SQL_SS_VARIANT (-150)
#define SQL_SS_UDT (-151)
#define SQL_SS_XML (-152)
#define SQL_SS_TABLE (-153)
#define SQL_SS_TIME2 (-154)
#define SQL_SS_TIMESTAMPOFFSET (-155)
// 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
#ifndef SQLNCLI_NO_BCP
// Define the symbol SQLNCLI_NO_BCP if you are not using BCP in your application
// and you want to exclude the BCP-related definitions in this header file.
// SQL Server Data Type defines.
// New types for SQL 6.0 and later servers
#define SQLTEXT 0x23
#define SQLVARBINARY 0x25
#define SQLINTN 0x26
#define SQLVARCHAR 0x27
#define SQLBINARY 0x2d
#define SQLIMAGE 0x22
#define SQLCHARACTER 0x2f
#define SQLINT1 0x30
#define SQLBIT 0x32
#define SQLINT2 0x34
#define SQLINT4 0x38
#define SQLMONEY 0x3c
#define SQLDATETIME 0x3d
#define SQLFLT8 0x3e
#define SQLFLTN 0x6d
#define SQLMONEYN 0x6e
#define SQLDATETIMN 0x6f
#define SQLFLT4 0x3b
#define SQLMONEY4 0x7a
#define SQLDATETIM4 0x3a
// New types for SQL 6.0 and later servers
#define SQLDECIMAL 0x6a
#define SQLNUMERIC 0x6c
// New types for SQL 7.0 and later servers
#define SQLUNIQUEID 0x24
#define SQLBIGCHAR 0xaf
#define SQLBIGVARCHAR 0xa7
#define SQLBIGBINARY 0xad
#define SQLBIGVARBINARY 0xa5
#define SQLBITN 0x68
#define SQLNCHAR 0xef
#define SQLNVARCHAR 0xe7
#define SQLNTEXT 0x63
// New types for SQL 2000 and later servers
#define SQLINT8 0x7f
#define SQLVARIANT 0x62
// New types for SQL 2005 and later servers
#define SQLUDT 0xf0
#define SQLXML 0xf1
// New types for SQL 2008 and later servers
#define SQLTABLE 0xf3
#define SQLDATEN 0x28
#define SQLTIMEN 0x29
#define SQLDATETIME2N 0x2a
#define SQLDATETIMEOFFSETN 0x2b
// Define old names
#define SQLDECIMALN 0x6a
#define SQLNUMERICN 0x6c
#endif // SQLNCLI_NO_BCP
// 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.
#define SQLudtBINARY 3
#define SQLudtBIT 16
#define SQLudtBITN 0
#define SQLudtCHAR 1
#define SQLudtDATETIM4 22
#define SQLudtDATETIME 12
#define SQLudtDATETIMN 15
#define SQLudtDECML 24
#define SQLudtDECMLN 26
#define SQLudtFLT4 23
#define SQLudtFLT8 8
#define SQLudtFLTN 14
#define SQLudtIMAGE 20
#define SQLudtINT1 5
#define SQLudtINT2 6
#define SQLudtINT4 7
#define SQLudtINTN 13
#define SQLudtMONEY 11
#define SQLudtMONEY4 21
#define SQLudtMONEYN 17
#define SQLudtNUM 10
#define SQLudtNUMN 25
#define SQLudtSYSNAME 18
#define SQLudtTEXT 19
#define SQLudtTIMESTAMP 80
#define SQLudtUNIQUEIDENTIFIER 0
#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
// SQLGetInfo driver specific defines.
// Microsoft has 1151 thru 1200 reserved for Microsoft SQL Server Native Client driver usage.
#define SQL_INFO_SS_FIRST 1199
#define SQL_INFO_SS_NETLIB_NAMEW (SQL_INFO_SS_FIRST+0) // dbprocinfo
#define SQL_INFO_SS_NETLIB_NAMEA (SQL_INFO_SS_FIRST+1) // dbprocinfo
#define SQL_INFO_SS_MAX_USED SQL_INFO_SS_NETLIB_NAMEA
#ifdef UNICODE
#define SQL_INFO_SS_NETLIB_NAME SQL_INFO_SS_NETLIB_NAMEW
#else
#define SQL_INFO_SS_NETLIB_NAME SQL_INFO_SS_NETLIB_NAMEA
#endif
// SQLGetDiagField driver specific defines.
// Microsoft has -1150 thru -1199 reserved for Microsoft SQL Server Native Client driver 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 SQL Server Native Client driver 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)
#define SQL_DIAG_DFC_SS_CONDITION (SQL_DIAG_DFC_SS_BASE-2)
#define SQL_DIAG_DFC_SS_CREATE_DATABASE (SQL_DIAG_DFC_SS_BASE-3)
#define SQL_DIAG_DFC_SS_CREATE_DEFAULT (SQL_DIAG_DFC_SS_BASE-4)
#define SQL_DIAG_DFC_SS_CREATE_PROCEDURE (SQL_DIAG_DFC_SS_BASE-5)
#define SQL_DIAG_DFC_SS_CREATE_RULE (SQL_DIAG_DFC_SS_BASE-6)
#define SQL_DIAG_DFC_SS_CREATE_TRIGGER (SQL_DIAG_DFC_SS_BASE-7)
#define SQL_DIAG_DFC_SS_CURSOR_DECLARE (SQL_DIAG_DFC_SS_BASE-8)
#define SQL_DIAG_DFC_SS_CURSOR_OPEN (SQL_DIAG_DFC_SS_BASE-9)
#define SQL_DIAG_DFC_SS_CURSOR_FETCH (SQL_DIAG_DFC_SS_BASE-10)
#define SQL_DIAG_DFC_SS_CURSOR_CLOSE (SQL_DIAG_DFC_SS_BASE-11)
#define SQL_DIAG_DFC_SS_DEALLOCATE_CURSOR (SQL_DIAG_DFC_SS_BASE-12)
#define SQL_DIAG_DFC_SS_DBCC (SQL_DIAG_DFC_SS_BASE-13)
#define SQL_DIAG_DFC_SS_DISK (SQL_DIAG_DFC_SS_BASE-14)
#define SQL_DIAG_DFC_SS_DROP_DATABASE (SQL_DIAG_DFC_SS_BASE-15)
#define SQL_DIAG_DFC_SS_DROP_DEFAULT (SQL_DIAG_DFC_SS_BASE-16)
#define SQL_DIAG_DFC_SS_DROP_PROCEDURE (SQL_DIAG_DFC_SS_BASE-17)
#define SQL_DIAG_DFC_SS_DROP_RULE (SQL_DIAG_DFC_SS_BASE-18)
#define SQL_DIAG_DFC_SS_DROP_TRIGGER (SQL_DIAG_DFC_SS_BASE-19)
#define SQL_DIAG_DFC_SS_DUMP_DATABASE (SQL_DIAG_DFC_SS_BASE-20)
#define SQL_DIAG_DFC_SS_BACKUP_DATABASE (SQL_DIAG_DFC_SS_BASE-20)
#define SQL_DIAG_DFC_SS_DUMP_TABLE (SQL_DIAG_DFC_SS_BASE-21)
#define SQL_DIAG_DFC_SS_DUMP_TRANSACTION (SQL_DIAG_DFC_SS_BASE-22)
#define SQL_DIAG_DFC_SS_BACKUP_TRANSACTION (SQL_DIAG_DFC_SS_BASE-22)
#define SQL_DIAG_DFC_SS_GOTO (SQL_DIAG_DFC_SS_BASE-23)
#define SQL_DIAG_DFC_SS_INSERT_BULK (SQL_DIAG_DFC_SS_BASE-24)
#define SQL_DIAG_DFC_SS_KILL (SQL_DIAG_DFC_SS_BASE-25)
#define SQL_DIAG_DFC_SS_LOAD_DATABASE (SQL_DIAG_DFC_SS_BASE-26)
#define SQL_DIAG_DFC_SS_RESTORE_DATABASE (SQL_DIAG_DFC_SS_BASE-26)
#define SQL_DIAG_DFC_SS_LOAD_HEADERONLY (SQL_DIAG_DFC_SS_BASE-27)
#define SQL_DIAG_DFC_SS_RESTORE_HEADERONLY (SQL_DIAG_DFC_SS_BASE-27)
#define SQL_DIAG_DFC_SS_LOAD_TABLE (SQL_DIAG_DFC_SS_BASE-28)
#define SQL_DIAG_DFC_SS_LOAD_TRANSACTION (SQL_DIAG_DFC_SS_BASE-29)
#define SQL_DIAG_DFC_SS_RESTORE_TRANSACTION (SQL_DIAG_DFC_SS_BASE-29)
#define SQL_DIAG_DFC_SS_PRINT (SQL_DIAG_DFC_SS_BASE-30)
#define SQL_DIAG_DFC_SS_RAISERROR (SQL_DIAG_DFC_SS_BASE-31)
#define SQL_DIAG_DFC_SS_READTEXT (SQL_DIAG_DFC_SS_BASE-32)
#define SQL_DIAG_DFC_SS_RECONFIGURE (SQL_DIAG_DFC_SS_BASE-33)
#define SQL_DIAG_DFC_SS_RETURN (SQL_DIAG_DFC_SS_BASE-34)
#define SQL_DIAG_DFC_SS_SELECT_INTO (SQL_DIAG_DFC_SS_BASE-35)
#define SQL_DIAG_DFC_SS_SET (SQL_DIAG_DFC_SS_BASE-36)
#define SQL_DIAG_DFC_SS_SET_IDENTITY_INSERT (SQL_DIAG_DFC_SS_BASE-37)
#define SQL_DIAG_DFC_SS_SET_ROW_COUNT (SQL_DIAG_DFC_SS_BASE-38)
#define SQL_DIAG_DFC_SS_SET_STATISTICS (SQL_DIAG_DFC_SS_BASE-39)
#define SQL_DIAG_DFC_SS_SET_TEXTSIZE (SQL_DIAG_DFC_SS_BASE-40)
#define SQL_DIAG_DFC_SS_SETUSER (SQL_DIAG_DFC_SS_BASE-41)
#define SQL_DIAG_DFC_SS_SHUTDOWN (SQL_DIAG_DFC_SS_BASE-42)
#define SQL_DIAG_DFC_SS_TRANS_BEGIN (SQL_DIAG_DFC_SS_BASE-43)
#define SQL_DIAG_DFC_SS_TRANS_COMMIT (SQL_DIAG_DFC_SS_BASE-44)
#define SQL_DIAG_DFC_SS_TRANS_PREPARE (SQL_DIAG_DFC_SS_BASE-45)
#define SQL_DIAG_DFC_SS_TRANS_ROLLBACK (SQL_DIAG_DFC_SS_BASE-46)
#define SQL_DIAG_DFC_SS_TRANS_SAVE (SQL_DIAG_DFC_SS_BASE-47)
#define SQL_DIAG_DFC_SS_TRUNCATE_TABLE (SQL_DIAG_DFC_SS_BASE-48)
#define SQL_DIAG_DFC_SS_UPDATE_STATISTICS (SQL_DIAG_DFC_SS_BASE-49)
#define SQL_DIAG_DFC_SS_UPDATETEXT (SQL_DIAG_DFC_SS_BASE-50)
#define SQL_DIAG_DFC_SS_USE (SQL_DIAG_DFC_SS_BASE-51)
#define SQL_DIAG_DFC_SS_WAITFOR (SQL_DIAG_DFC_SS_BASE-52)
#define SQL_DIAG_DFC_SS_WRITETEXT (SQL_DIAG_DFC_SS_BASE-53)
#define SQL_DIAG_DFC_SS_DENY (SQL_DIAG_DFC_SS_BASE-54)
#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
#define EX_ANY 0
#define EX_INFO 10
#define EX_MAXISEVERITY EX_INFO
#define EX_MISSING 11
#define EX_TYPE 12
#define EX_DEADLOCK 13
#define EX_PERMIT 14
#define EX_SYNTAX 15
#define EX_USER 16
#define EX_RESOURCE 17
#define EX_INTOK 18
#define MAXUSEVERITY EX_INTOK
#define EX_LIMIT 19
#define EX_CMDFATAL 20
#define MINFATALERR EX_CMDFATAL
#define EX_DBFATAL 21
#define EX_TABCORRUPT 22
#define EX_DBCORRUPT 23
#define EX_HARDWARE 24
#define EX_CONTROL 25
// Internal server datatypes - used when binding to SQL_C_BINARY
#ifndef MAXNUMERICLEN // Resolve ODS/DBLib conflicts
// DB-Library datatypes
#define DBMAXCHAR (8000+1) // Max length of DBVARBINARY and DBVARCHAR, etc. +1 for zero byte
#define MAXNAME (SQL_MAX_SQLSERVERNAME+1) // Max server identifier length including zero byte
#ifdef UNICODE
typedef wchar_t DBCHAR;
#else
typedef char DBCHAR;
#endif
typedef short SQLSMALLINT;
typedef unsigned short SQLUSMALLINT;
typedef long SQLINTEGER;
typedef unsigned long SQLUINTEGER;
typedef unsigned char DBBINARY;
typedef unsigned char DBTINYINT;
typedef short DBSMALLINT;
typedef unsigned short DBUSMALLINT;
typedef double DBFLT8;
typedef unsigned char DBBIT;
typedef unsigned char DBBOOL;
typedef float DBFLT4;
typedef DBFLT4 DBREAL;
typedef UINT DBUBOOL;
typedef struct dbmoney
{
LONG mnyhigh;
ULONG mnylow;
} DBMONEY;
typedef struct dbdatetime
{
LONG dtdays;
ULONG dttime;
} DBDATETIME;
typedef struct dbdatetime4
{
USHORT numdays;
USHORT nummins;
} DBDATETIM4;
typedef LONG DBMONEY4;
#include <pshpack8.h> // 8-byte structure packing
// New Date Time Structures
// New Structure for TIME2
typedef struct tagSS_TIME2_STRUCT
{
SQLUSMALLINT hour;
SQLUSMALLINT minute;
SQLUSMALLINT second;
SQLUINTEGER fraction;
} SQL_SS_TIME2_STRUCT;
// New Structure for TIMESTAMPOFFSET
typedef struct tagSS_TIMESTAMPOFFSET_STRUCT
{
SQLSMALLINT year;
SQLUSMALLINT month;
SQLUSMALLINT day;
SQLUSMALLINT hour;
SQLUSMALLINT minute;
SQLUSMALLINT second;
SQLUINTEGER fraction;
SQLSMALLINT timezone_hour;
SQLSMALLINT timezone_minute;
} SQL_SS_TIMESTAMPOFFSET_STRUCT;
#include <poppack.h> // restore original structure packing
// Money value *10,000
#define DBNUM_PREC_TYPE BYTE
#define DBNUM_SCALE_TYPE BYTE
#define DBNUM_VAL_TYPE BYTE
#if (ODBCVER < 0x0300)
#define MAXNUMERICLEN 16
typedef struct dbnumeric // Internal representation of NUMERIC data type
{
DBNUM_PREC_TYPE precision; // Precision
DBNUM_SCALE_TYPE scale; // Scale
BYTE sign; // Sign (1 if positive, 0 if negative)
DBNUM_VAL_TYPE val[MAXNUMERICLEN];// Value
} DBNUMERIC;
typedef DBNUMERIC DBDECIMAL;// Internal representation of DECIMAL data type
#else // Use ODBC 3.0 definitions since same as DBLib
#define MAXNUMERICLEN SQL_MAX_NUMERIC_LEN
typedef SQL_NUMERIC_STRUCT DBNUMERIC;
typedef SQL_NUMERIC_STRUCT DBDECIMAL;
#endif // ODCBVER
#endif // MAXNUMERICLEN
#ifndef INT
typedef int INT;
typedef long DBINT;
typedef DBINT * LPDBINT;
#ifndef _LPCBYTE_DEFINED
#define _LPCBYTE_DEFINED
typedef BYTE const* LPCBYTE;
#endif //_LPCBYTE_DEFINED
#endif // INT
/**************************************************************************
This struct is a global used for gathering statistical data on the driver.
Access to this structure is controlled via the pStatCrit;
***************************************************************************/
typedef struct sqlperf
{
// Application Profile Statistics
DWORD TimerResolution;
DWORD SQLidu;
DWORD SQLiduRows;
DWORD SQLSelects;
DWORD SQLSelectRows;
DWORD Transactions;
DWORD SQLPrepares;
DWORD ExecDirects;
DWORD SQLExecutes;
DWORD CursorOpens;
DWORD CursorSize;
DWORD CursorUsed;
LDOUBLE PercentCursorUsed;
LDOUBLE AvgFetchTime;
LDOUBLE AvgCursorSize;
LDOUBLE AvgCursorUsed;
DWORD SQLFetchTime;
DWORD SQLFetchCount;
DWORD CurrentStmtCount;
DWORD MaxOpenStmt;
DWORD SumOpenStmt;
// Connection Statistics
DWORD CurrentConnectionCount;
DWORD MaxConnectionsOpened;
DWORD SumConnectionsOpened;
DWORD SumConnectiontime;
LDOUBLE AvgTimeOpened;
// Network Statistics
DWORD ServerRndTrips;
DWORD BuffersSent;
DWORD BuffersRec;
DWORD BytesSent;
DWORD BytesRec;
// Time Statistics;
DWORD msExecutionTime;
DWORD msNetWorkServerTime;
} SQLPERF;
// The following are options for SQL_COPT_SS_PERF_DATA and SQL_COPT_SS_PERF_QUERY
#define SQL_PERF_START 1 // Starts the driver sampling performance data.
#define SQL_PERF_STOP 2 // Stops the counters from sampling performance data.
// The following are defines for SQL_COPT_SS_PERF_DATA_LOG
#define SQL_SS_DL_DEFAULT TEXT("STATS.LOG")
// The following are defines for SQL_COPT_SS_PERF_QUERY_LOG
#define SQL_SS_QL_DEFAULT TEXT("QUERY.LOG")
// The following are defines for SQL_COPT_SS_PERF_QUERY_INTERVAL
#define SQL_SS_QI_DEFAULT 30000 // 30,000 milliseconds
#ifndef SQLNCLI_NO_BCP
// Define the symbol SQLNCLI_NO_BCP if you are not using BCP in your application
// and you want to exclude the BCP-related definitions in this header file.
// ODBC BCP prototypes and defines
// Return codes
#define SUCCEED 1
#define FAIL 0
#define SUCCEED_ABORT 2
#define SUCCEED_ASYNC 3
// Transfer directions
#define DB_IN 1 // Transfer from client to server
#define DB_OUT 2 // Transfer from server to client
// bcp_control option
#define BCPMAXERRS 1 // Sets max errors allowed
#define BCPFIRST 2 // Sets first row to be copied out
#define BCPLAST 3 // Sets number of rows to be copied out
#define BCPBATCH 4 // Sets input batch size
#define BCPKEEPNULLS 5 // Sets to insert NULLs for empty input values
#define BCPABORT 6 // Sets to have bcpexec return SUCCEED_ABORT
#define BCPODBC 7 // Sets ODBC canonical character output
#define BCPKEEPIDENTITY 8 // Sets IDENTITY_INSERT on
#if SQLNCLI_VER < 1000
#define BCP6xFILEFMT 9 // DEPRECATED: Sets 6x file format on
#endif
#define BCPHINTSA 10 // Sets server BCP hints (ANSI string)
#define BCPHINTSW 11 // Sets server BCP hints (UNICODE string)
#define BCPFILECP 12 // Sets clients code page for the file
#define BCPUNICODEFILE 13 // Sets that the file contains unicode header
#define BCPTEXTFILE 14 // Sets BCP mode to expect a text file and to detect Unicode or ANSI automatically
#define BCPFILEFMT 15 // Sets file format version
#define BCPFMTXML 16 // Sets the format file type to xml
#define BCPFIRSTEX 17 // Starting Row for BCP operation (64 bit)
#define BCPLASTEX 18 // Ending Row for BCP operation (64 bit)
#define BCPROWCOUNT 19 // Total Number of Rows Copied (64 bit)
// BCPFILECP values
// Any valid code page that is installed on the client can be passed plus:
#define BCPFILECP_ACP 0 // Data in file is in Windows code page
#define BCPFILECP_OEMCP 1 // Data in file is in OEM code page (default)
#define BCPFILECP_RAW (-1)// Data in file is in Server code page (no conversion)
// bcp_collen definition
#define SQL_VARLEN_DATA (-10) // Use default length for column
// BCP column format properties
#define BCP_FMT_TYPE 0x01
#define BCP_FMT_INDICATOR_LEN 0x02
#define BCP_FMT_DATA_LEN 0x03
#define BCP_FMT_TERMINATOR 0x04
#define BCP_FMT_SERVER_COL 0x05
#define BCP_FMT_COLLATION 0x06
#define BCP_FMT_COLLATION_ID 0x07
// BCP functions
DBINT SQL_API bcp_batch (HDBC);
RETCODE SQL_API bcp_bind (HDBC, LPCBYTE, INT, DBINT, LPCBYTE, INT, INT, INT);
RETCODE SQL_API bcp_colfmt (HDBC, INT, BYTE, INT, DBINT, LPCBYTE, INT, INT);
RETCODE SQL_API bcp_collen (HDBC, DBINT, INT);
RETCODE SQL_API bcp_colptr (HDBC, LPCBYTE, INT);
RETCODE SQL_API bcp_columns (HDBC, INT);
RETCODE SQL_API bcp_control (HDBC, INT, void *);
DBINT SQL_API bcp_done (HDBC);
RETCODE SQL_API bcp_exec (HDBC, LPDBINT);
RETCODE SQL_API bcp_getcolfmt (HDBC, INT, INT, void *, INT, INT *);
RETCODE SQL_API bcp_initA (HDBC, LPCSTR, LPCSTR, LPCSTR, INT);
RETCODE SQL_API bcp_initW (HDBC, LPCWSTR, LPCWSTR, LPCWSTR, INT);
RETCODE SQL_API bcp_moretext (HDBC, DBINT, LPCBYTE);
RETCODE SQL_API bcp_readfmtA (HDBC, LPCSTR);
RETCODE SQL_API bcp_readfmtW (HDBC, LPCWSTR);
RETCODE SQL_API bcp_sendrow (HDBC);
RETCODE SQL_API bcp_setcolfmt (HDBC, INT, INT, void *, INT);
RETCODE SQL_API bcp_writefmtA (HDBC, LPCSTR);
RETCODE SQL_API bcp_writefmtW (HDBC, LPCWSTR);
CHAR* SQL_API dbprtypeA (INT);
WCHAR* SQL_API dbprtypeW (INT);
CHAR* SQL_API bcp_gettypenameA (INT, DBBOOL);
WCHAR* SQL_API bcp_gettypenameW (INT, DBBOOL);
#ifdef UNICODE
#define bcp_init bcp_initW
#define bcp_readfmt bcp_readfmtW
#define bcp_writefmt bcp_writefmtW
#define dbprtype dbprtypeW
#define bcp_gettypename bcp_gettypenameW
#define BCPHINTS BCPHINTSW
#else
#define bcp_init bcp_initA
#define bcp_readfmt bcp_readfmtA
#define bcp_writefmt bcp_writefmtA
#define dbprtype dbprtypeA
#define bcp_gettypename bcp_gettypenameA
#define BCPHINTS BCPHINTSA
#endif // UNICODE
#endif // SQLNCLI_NO_BCP
// The following options have been deprecated
#define SQL_FAST_CONNECT (SQL_COPT_SS_BASE+0)
// Defines for use with SQL_FAST_CONNECT - only useable before connecting
#define SQL_FC_OFF 0L // Fast connect is off
#define SQL_FC_ON 1L // Fast connect is on
#define SQL_FC_DEFAULT SQL_FC_OFF
#define SQL_COPT_SS_ANSI_OEM (SQL_COPT_SS_BASE+6)
#define SQL_AO_OFF 0L
#define SQL_AO_ON 1L
#define SQL_AO_DEFAULT SQL_AO_OFF
#define SQL_CA_SS_BASE_COLUMN_NAME SQL_DESC_BASE_COLUMN_NAME
#endif // ODBCVER
#endif // defined(_SQLNCLI_ODBC_) || !defined(_SQLNCLI_OLEDB_)
// ODBC part of SQL Server Native Client header - end here!
//The following facilitates opening a handle to a SQL filestream
typedef enum _SQL_FILESTREAM_DESIRED_ACCESS {
SQL_FILESTREAM_READ = 0,
SQL_FILESTREAM_WRITE = 1,
SQL_FILESTREAM_READWRITE = 2
} SQL_FILESTREAM_DESIRED_ACCESS;
#define SQL_FILESTREAM_OPEN_FLAG_ASYNC 0x00000001L
#define SQL_FILESTREAM_OPEN_FLAG_NO_BUFFERING 0x00000002L
#define SQL_FILESTREAM_OPEN_FLAG_NO_WRITE_THROUGH 0x00000004L
#define SQL_FILESTREAM_OPEN_FLAG_SEQUENTIAL_SCAN 0x00000008L
#define SQL_FILESTREAM_OPEN_FLAG_RANDOM_ACCESS 0x00000010L
HANDLE __stdcall OpenSqlFilestream (
LPCWSTR FilestreamPath,
SQL_FILESTREAM_DESIRED_ACCESS DesiredAccess,
ULONG OpenOptions,
LPBYTE FilestreamTransactionContext,
SSIZE_T FilestreamTransactionContextLength,
PLARGE_INTEGER AllocationSize);
#define FSCTL_SQL_FILESTREAM_FETCH_OLD_CONTENT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2392, METHOD_BUFFERED, FILE_ANY_ACCESS)
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0010_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_sqlncli_0000_0010_v0_0_s_ifspec;
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -3,7 +3,7 @@
//
// Contents: Routines that use statement handles
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -112,6 +112,18 @@ namespace SSCursorTypes {
const char QUERY_OPTION_SCROLLABLE_DYNAMIC[] = "dynamic";
const char QUERY_OPTION_SCROLLABLE_KEYSET[] = "keyset";
const char QUERY_OPTION_SCROLLABLE_FORWARD[] = "forward";
const char QUERY_OPTION_SCROLLABLE_BUFFERED[] = "buffered";
}
ss_sqlsrv_stmt::ss_sqlsrv_stmt( sqlsrv_conn* c, SQLHANDLE handle, error_callback e, void* drv TSRMLS_DC ) :
sqlsrv_stmt( c, handle, e, drv TSRMLS_CC ),
prepared( false ),
conn_index( -1 ),
params_z( NULL ),
fetch_field_names( NULL ),
fetch_fields_count ( 0 )
{
core_sqlsrv_set_buffered_query_limit( this, SQLSRV_G( buffered_query_limit ) TSRMLS_CC );
}
ss_sqlsrv_stmt::~ss_sqlsrv_stmt( void )
@ -132,8 +144,8 @@ ss_sqlsrv_stmt::~ss_sqlsrv_stmt( void )
}
// to be called whenever a new result set is created, such as after an
// execute or next_result. Resets the state variables.
void ss_sqlsrv_stmt::new_result_set( void )
// execute or next_result. Resets the state variables and calls the subclass.
void ss_sqlsrv_stmt::new_result_set( TSRMLS_D )
{
if( fetch_field_names != NULL ) {
@ -146,7 +158,7 @@ void ss_sqlsrv_stmt::new_result_set( void )
fetch_field_names = NULL;
fetch_fields_count = 0;
sqlsrv_stmt::new_result_set();
sqlsrv_stmt::new_result_set( TSRMLS_C );
}
// Returns a php type for a given sql type. Also sets the encoding wherever applicable.
@ -164,6 +176,7 @@ sqlsrv_phptype ss_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUIN
case SQL_GUID:
case SQL_NUMERIC:
case SQL_WCHAR:
case SQL_SS_VARIANT:
ss_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
ss_phptype.typeinfo.encoding = this->conn->encoding();
break;
@ -272,7 +285,7 @@ PHP_FUNCTION( sqlsrv_execute )
// to prepare to execute the next statement, we skip any remaining results (and skip parameter finalization too)
while( stmt->past_next_result_end == false ) {
core_sqlsrv_next_result( stmt TSRMLS_CC, false );
core_sqlsrv_next_result( stmt TSRMLS_CC, false, false );
}
}
@ -597,11 +610,11 @@ PHP_FUNCTION( sqlsrv_rows_affected )
// make sure it is not scrollable. This function should only work for inserts, updates, and deletes,
// but this is the best we can do to enforce that.
CHECK_CUSTOM_ERROR( stmt->scrollable, stmt, SS_SQLSRV_ERROR_STATEMENT_SCROLLABLE ) {
CHECK_CUSTOM_ERROR( stmt->cursor_type != SQL_CURSOR_FORWARD_ONLY, stmt, SS_SQLSRV_ERROR_STATEMENT_SCROLLABLE ) {
throw ss::SSException();
}
rows = core::SQLRowCount( stmt TSRMLS_CC );
rows = stmt->current_results->row_count( TSRMLS_C );
RETURN_LONG( rows );
}
@ -645,11 +658,12 @@ PHP_FUNCTION( sqlsrv_num_rows )
// make sure that the statement is scrollable and the cursor is not dynamic.
// if the cursor is dynamic, then the number of rows returned is always -1.
CHECK_CUSTOM_ERROR( !stmt->scrollable || stmt->scroll_is_dynamic, stmt, SS_SQLSRV_ERROR_STATEMENT_NOT_SCROLLABLE ) {
CHECK_CUSTOM_ERROR( stmt->cursor_type == SQL_CURSOR_FORWARD_ONLY || stmt->cursor_type == SQL_CURSOR_DYNAMIC, stmt,
SS_SQLSRV_ERROR_STATEMENT_NOT_SCROLLABLE ) {
throw ss::SSException();
}
rows = core::SQLRowCount( stmt TSRMLS_CC );
rows = stmt->current_results->row_count( TSRMLS_C );
RETURN_LONG( rows );
}
@ -1147,7 +1161,7 @@ PHP_FUNCTION(SQLSRV_SQLTYPE_VARCHAR)
void mark_params_by_reference( ss_sqlsrv_stmt* stmt, zval* params_z TSRMLS_DC )
{
SQLSRV_ASSERT( stmt->params_z == NULL, "mark_params_by_reference: parameters list shouldn't be present" );
SQLSRV_ASSERT( stmt->params_z == NULL, "mark_params_by_reference: parameters list shouldn't be present" );
if( params_z == NULL ) {
return;
@ -1259,7 +1273,7 @@ void bind_params( ss_sqlsrv_stmt* stmt TSRMLS_DC )
zval** var = NULL;
int zr = zend_hash_index_find( Z_ARRVAL_PP( param_z ), 0, reinterpret_cast<void**>( &var ));
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index ) {
CHECK_CUSTOM_ERROR( zr == FAILURE, stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index + 1 ) {
zval_ptr_dtor( &params_z );
throw ss::SSException();
}
@ -1413,7 +1427,8 @@ PHP_FUNCTION( sqlsrv_free_stmt )
}
// verify the resource so we know we're deleting a statement
stmt = static_cast<ss_sqlsrv_stmt*>( zend_fetch_resource( &stmt_r TSRMLS_CC, -1, ss_sqlsrv_stmt::resource_name, NULL, 1, ss_sqlsrv_stmt::descriptor ));
stmt = static_cast<ss_sqlsrv_stmt*>( zend_fetch_resource( &stmt_r TSRMLS_CC, -1, ss_sqlsrv_stmt::resource_name, NULL,
1, ss_sqlsrv_stmt::descriptor ));
if( stmt == NULL ) {
@ -1472,6 +1487,11 @@ void stmt_option_scrollable:: operator()( sqlsrv_stmt* stmt, stmt_option const*
cursor_type = SQL_CURSOR_FORWARD_ONLY;
}
else if( !stricmp( scroll_type, SSCursorTypes::QUERY_OPTION_SCROLLABLE_BUFFERED )) {
cursor_type = SQLSRV_CURSOR_BUFFERED;
}
else {
THROW_SS_ERROR( stmt, SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE );
@ -1534,6 +1554,11 @@ zval* convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void** in_val, SQLLEN fie
out_zval = ( reinterpret_cast<zval*>( *in_val ));
break;
case SQLSRV_PHPTYPE_NULL:
ALLOC_INIT_ZVAL( out_zval );
ZVAL_NULL( out_zval );
break;
default:
DIE( "Unknown php type" );
break;
@ -1764,22 +1789,22 @@ void determine_stmt_has_rows( ss_sqlsrv_stmt* stmt TSRMLS_DC )
// if the statement is scrollable, our work is easier though less performant. We simply
// fetch the first row, and then roll the cursor back to be prior to the first row
if( stmt->scrollable ) {
if( stmt->cursor_type != SQL_CURSOR_FORWARD_ONLY ) {
r = core::SQLFetchScroll( stmt, SQL_FETCH_FIRST, 0 TSRMLS_CC );
r = stmt->current_results->fetch( SQL_FETCH_FIRST, 0 TSRMLS_CC );
if( SQL_SUCCEEDED( r )) {
stmt->has_rows = true;
CHECK_SQL_WARNING( r, stmt );
// restore the cursor to its original position.
r = SQLFetchScroll( stmt->handle(), SQL_FETCH_ABSOLUTE, 0 );
r = stmt->current_results->fetch( SQL_FETCH_ABSOLUTE, 0 TSRMLS_CC );
SQLSRV_ASSERT(( r == SQL_NO_DATA ), "core_sqlsrv_has_rows: Should have scrolled the cursor to the beginning "
"of the result set." );
}
}
else {
// otherwise, we fetch the first row, but record that we di. sqlsrv_fetch checks this
// otherwise, we fetch the first row, but record that we did. sqlsrv_fetch checks this
// flag and simply skips the first fetch, knowing it was already done. It records its own
// flags to know if it should fetch on subsequent calls.
@ -1823,7 +1848,7 @@ void fetch_fields_common( __inout ss_sqlsrv_stmt* stmt, int fetch_type, __out zv
core::SQLColAttribute( stmt, i + 1, SQL_DESC_NAME, field_name_temp, SS_MAXCOLNAMELEN+1, &field_name_len, NULL
TSRMLS_CC );
field_names[ i ].name = static_cast<char*>( sqlsrv_malloc( field_name_len + 1 ));
field_names[ i ].name = static_cast<char*>( sqlsrv_malloc( field_name_len, sizeof( char ), 1 ));
memcpy( (void*) field_names[ i ].name, field_name_temp, field_name_len );
field_names[ i ].name[ field_name_len ] = '\0'; // null terminate the field name since SQLColAttribute doesn't.
field_names[ i ].len = field_name_len + 1;
@ -1908,7 +1933,7 @@ void parse_param_array( ss_sqlsrv_stmt* stmt, __inout zval* param_array, unsigne
if( zend_hash_has_more_elements( param_ht ) == FAILURE ||
zend_hash_get_current_data( param_ht, (void**) &var_or_val ) == FAILURE ) {
THROW_SS_ERROR( stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index );
THROW_SS_ERROR( stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index + 1 );
}
// if the direction is included, then use what they gave, otherwise INPUT is assumed
@ -1921,7 +1946,7 @@ void parse_param_array( ss_sqlsrv_stmt* stmt, __inout zval* param_array, unsigne
}
direction = Z_LVAL_PP( temp );
CHECK_CUSTOM_ERROR( direction != SQL_PARAM_INPUT && direction != SQL_PARAM_OUTPUT && direction != SQL_PARAM_INPUT_OUTPUT,
stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION, index ) {
stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION, index + 1 ) {
throw ss::SSException();
}
}

View file

@ -3,7 +3,7 @@
//
// Contents: Version resource
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -65,7 +65,7 @@ BEGIN
VALUE "FileDescription", "Microsoft Drivers for PHP for SQL Server (SQLSRV Driver)\0"
VALUE "FileVersion", STRVER4(SQLVERSION_MAJOR,SQLVERSION_MINOR, SQLVERSION_MMDD, SQLVERSION_REVISION)
VALUE "InternalName", FILE_NAME "\0"
VALUE "LegalCopyright", "Copyright 2010 Microsoft Corporation.\0"
VALUE "LegalCopyright", "Copyright Microsoft Corporation.\0"
VALUE "OriginalFilename", FILE_NAME "\0"
VALUE "ProductName", "Microsoft Drivers for PHP for SQL Server\0"
VALUE "ProductVersion", STRVER3(SQLVERSION_MAJOR,SQLVERSION_MINOR, SQLVERSION_MMDD)

View file

@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
// Copyright 2010 Microsoft Corporation
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -218,8 +218,8 @@ ss_error SS_ERRORS[] = {
// these three errors are returned for invalid options, so they are given the same number for compatibility with 1.1
{
SQLSRV_ERROR_INVALID_OPTION_VALUE,
{ IMSSP, (SQLCHAR*) "Invalid value specified for option %1!s!.", -33, true }
SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE,
{ IMSSP, (SQLCHAR*) "Invalid value %1!s! specified for option SQLSRV_QUERY_TIMEOUT.", -33, true }
},
{
@ -301,9 +301,8 @@ ss_error SS_ERRORS[] = {
{
SQLSRV_ERROR_DRIVER_NOT_INSTALLED,
{ IMSSP, (SQLCHAR*) "This extension requires either the Microsoft SQL Server 2008 Native Client (SP1 or later) or the "
"Microsoft SQL Server 2008 R2 Native Client ODBC Driver to communicate with SQL Server. Neither of those ODBC Drivers are currently installed. "
"Access the following URL to download the Microsoft SQL Server 2008 R2 Native Client ODBC driver for %1!s!: "
{ IMSSP, (SQLCHAR*) "This extension requires the Microsoft SQL Server 2011 Native Client. "
"Access the following URL to download the Microsoft SQL Server 2011 Native Client ODBC driver for %1!s!: "
"http://go.microsoft.com/fwlink/?LinkId=163712", -49, true }
},
@ -332,7 +331,7 @@ ss_error SS_ERRORS[] = {
{
SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE,
{ IMSSP, (SQLCHAR*)"The value passed for the 'Scrollable' statement option is invalid. Please use 'static', 'dynamic', "
"'keyset', or 'forward'.", -54, false }
"'keyset', 'forward', or 'buffered'.", -54, false }
},
{
@ -354,6 +353,14 @@ ss_error SS_ERRORS[] = {
SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED,
{ IMSSP, (SQLCHAR*) "String data, right truncated for output parameter %1!d!.", -58, true }
},
{
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED,
{ IMSSP, (SQLCHAR*) "Memory limit of %1!d! KB exceeded for buffered query", -59, true }
},
{
SQLSRV_ERROR_INVALID_BUFFER_LIMIT,
{ IMSSP, (SQLCHAR*) "Setting for " INI_BUFFERED_QUERY_LIMIT " was non-int or non-positive.", -60, false }
},
// internal warning definitions
{
@ -402,7 +409,8 @@ bool ss_error_handler(sqlsrv_context& ctx, unsigned int sqlsrv_error_code, bool
severity = SEV_WARNING;
}
return handle_errors_and_warnings( ctx, &SQLSRV_G( errors ), &SQLSRV_G( warnings ), severity, sqlsrv_error_code, warning, print_args TSRMLS_CC );
return handle_errors_and_warnings( ctx, &SQLSRV_G( errors ), &SQLSRV_G( warnings ), severity, sqlsrv_error_code, warning,
print_args TSRMLS_CC );
}
// sqlsrv_errors( [int $errorsAndOrWarnings] )
@ -595,6 +603,25 @@ PHP_FUNCTION( sqlsrv_configure )
RETURN_TRUE;
}
else if( !stricmp( option, INI_BUFFERED_QUERY_LIMIT )) {
CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_LONG ), error_ctx, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, _FN_ ) {
throw ss::SSException();
}
long buffered_query_limit = Z_LVAL_P( value_z );
CHECK_CUSTOM_ERROR( buffered_query_limit < 0, error_ctx, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, _FN_ ) {
throw ss::SSException();
}
SQLSRV_G( buffered_query_limit ) = buffered_query_limit;
LOG( SEV_NOTICE, INI_PREFIX INI_BUFFERED_QUERY_LIMIT " = %1!d!", SQLSRV_G( buffered_query_limit ));
RETURN_TRUE;
}
else {
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
@ -666,6 +693,11 @@ PHP_FUNCTION( sqlsrv_get_config )
ZVAL_LONG( return_value, SQLSRV_G( log_subsystems ));
return;
}
else if( !stricmp( option, INI_BUFFERED_QUERY_LIMIT )) {
ZVAL_LONG( return_value, SQLSRV_G( buffered_query_limit ));
return;
}
else {
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
@ -773,8 +805,6 @@ bool handle_errors_and_warnings( sqlsrv_context& ctx, zval** reported_chain, zva
zval* error_z = NULL;
sqlsrv_error_auto_ptr error;
error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error;
// array of reported errors
if( Z_TYPE_P( *reported_chain ) == IS_NULL ) {

View file

@ -1,9 +1,9 @@
//---------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
// File: version.h
//
// Contents: Version information for compile and resources
//
// Copyright 2010 Microsoft Corporation
// Contents: Version number constants
//
// Copyright Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -16,11 +16,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//---------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
#define VER_FILEVERSION_STR "2.0.0.200"
#define _FILEVERSION 2,0,0,200
#define SQLVERSION_MAJOR 2
#define VER_FILEVERSION_STR "3.0.0.0"
#define _FILEVERSION 3,0,0,0
#define SQLVERSION_MAJOR 3
#define SQLVERSION_MINOR 0
#define SQLVERSION_MMDD 0
#define SQLVERSION_REVISION 200
#define SQLVERSION_REVISION 0