void bind_params()

in source/sqlsrv/stmt.cpp [1181:1274]


void bind_params( _Inout_ ss_sqlsrv_stmt* stmt )
{
    // if there's nothing to do, just return
    if( stmt->params_z == NULL ) {
        return;
    }

    try {

        stmt->executed = false;

        zval* params_z = stmt->params_z;

        HashTable* params_ht = Z_ARRVAL_P( params_z );

        zend_ulong index = -1;
        zend_string *key = NULL;
        zval* param_z = NULL;

        ZEND_HASH_FOREACH_KEY_VAL( params_ht, index, key, param_z ) {
            // make sure it's an integer index
            int type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
            CHECK_CUSTOM_ERROR(type != HASH_KEY_IS_LONG, stmt, SS_SQLSRV_ERROR_PARAM_INVALID_INDEX) {
                throw ss::SSException();
            }

            zval* value_z = NULL;
            SQLSMALLINT direction = SQL_PARAM_INPUT;
            SQLSRV_ENCODING encoding = stmt->encoding();
            if( stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) {
                encoding = stmt->conn->encoding();
            }
            SQLSMALLINT sql_type = SQL_UNKNOWN_TYPE;
            SQLULEN column_size = SQLSRV_UNKNOWN_SIZE;
            SQLSMALLINT decimal_digits = 0;
            SQLSRV_PHPTYPE php_out_type = SQLSRV_PHPTYPE_INVALID;

            // if it's a parameter array
            if (Z_TYPE_P(param_z) == IS_ARRAY) {
                try {
                    HashTable* param_ht = Z_ARRVAL_P(param_z);
                    // Check the number of elements in the array
                    int num_elems = zend_hash_num_elements(param_ht);
                    if (num_elems > 1) {
                        value_z = parse_param_array(stmt, param_ht, index, direction, php_out_type, encoding, sql_type, column_size, decimal_digits);
                    } else {
                        // Simply get the first variable and use the defaults
                        value_z = zend_hash_index_find(param_ht, 0);
                        if (value_z == NULL) {
                            THROW_SS_ERROR(stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index + 1);
                        }
                    }
                } catch (core::CoreException&) {
                    SQLFreeStmt(stmt->handle(), SQL_RESET_PARAMS);
                    throw;
                }
            }
            else {
                CHECK_CUSTOM_ERROR(!stmt->prepared && stmt->conn->ce_option.enabled, stmt, SS_SQLSRV_ERROR_AE_QUERY_SQLTYPE_REQUIRED) {
                    throw ss::SSException();
                }
                value_z = param_z;
            }

            // If the user specifies a certain type for an output parameter, we have to convert the zval
            // to that type so that when the buffer is filled, the type is correct. But first,
            // should check if a LOB type is specified.
            CHECK_CUSTOM_ERROR(direction != SQL_PARAM_INPUT && (sql_type == SQL_LONGVARCHAR
                || sql_type == SQL_WLONGVARCHAR || sql_type == SQL_LONGVARBINARY),
                stmt, SQLSRV_ERROR_OUTPUT_PARAM_TYPES_NOT_SUPPORTED) {
                throw core::CoreException();
            }

            // Table-valued parameters are input-only
            CHECK_CUSTOM_ERROR(direction != SQL_PARAM_INPUT && (sql_type == SQL_SS_TABLE || php_out_type == SQLSRV_PHPTYPE_TABLE), stmt, SQLSRV_ERROR_TVP_INPUT_PARAM_ONLY) {
                throw ss::SSException();
            }

            // bind the parameter
            core_sqlsrv_bind_param( stmt, static_cast<SQLUSMALLINT>( index ), direction, value_z, php_out_type, encoding, sql_type, column_size,
                decimal_digits );

        } ZEND_HASH_FOREACH_END();
    }
    catch( core::CoreException& ) {
        stmt->free_param_data();

        SQLFreeStmt( stmt->handle(), SQL_RESET_PARAMS );
        zval_ptr_dtor( stmt->params_z );
        sqlsrv_free( stmt->params_z );
        stmt->params_z = NULL;
        throw;
    }
}