int pdo_sqlsrv_dbh_set_attr()

in source/pdo_sqlsrv/pdo_dbh.cpp [1160:1329]


int pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val)
#else
bool pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val)
#endif
{
    PDO_RESET_DBH_ERROR;
    PDO_VALIDATE_CONN;
    PDO_LOG_DBH_ENTRY;

    pdo_sqlsrv_dbh* driver_dbh = static_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
    SQLSRV_ASSERT( driver_dbh != NULL, "pdo_sqlsrv_dbh_set_attr: driver_data object was NULL.");

    try {

        switch( attr ) {

            case SQLSRV_ATTR_ENCODING:
            {
                zend_long attr_value;
                if( Z_TYPE_P( val ) != IS_LONG ) {
                    THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_INVALID_ENCODING );
                }
                attr_value = Z_LVAL_P( val );
                switch( attr_value ) {

                    case SQLSRV_ENCODING_DEFAULT:
                        // when default is applied to a connection, that means use UTF-8 encoding
                        driver_dbh->set_encoding( SQLSRV_ENCODING_UTF8 );
                        break;
                    case SQLSRV_ENCODING_SYSTEM:
                    case SQLSRV_ENCODING_UTF8:
                        driver_dbh->set_encoding( static_cast<SQLSRV_ENCODING>( attr_value ));
                        break;
                    default:
                        THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_INVALID_ENCODING );
                        break;
                }
            }
            break;

            case SQLSRV_ATTR_DIRECT_QUERY:
                driver_dbh->direct_query = zend_is_true(val);
                break;

            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_QUERY_TIMEOUT_VALUE, Z_STRVAL_P( val ));
                }
                driver_dbh->query_timeout = static_cast<long>( 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;

            case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
                driver_dbh->fetch_numeric = zend_is_true(val);
                break;

            case SQLSRV_ATTR_FETCHES_DATETIME_TYPE:
                driver_dbh->fetch_datetime = zend_is_true(val);
                break;

            case SQLSRV_ATTR_FORMAT_DECIMALS:
                driver_dbh->format_decimals = zend_is_true(val);
                break;

            case SQLSRV_ATTR_DECIMAL_PLACES:
            {
                // first check if the input is an integer
                if (Z_TYPE_P(val) != IS_LONG) {
                    THROW_PDO_ERROR(driver_dbh, SQLSRV_ERROR_INVALID_DECIMAL_PLACES);
                }

                zend_long decimal_places = Z_LVAL_P(val);
                if (decimal_places < 0 || decimal_places > SQL_SERVER_MAX_MONEY_SCALE) {
                    // ignore decimal_places as this is out of range
                    decimal_places = NO_CHANGE_DECIMAL_PLACES;
                }

                driver_dbh->decimal_places = static_cast<short>(decimal_places);
            }
            break;

#if PHP_VERSION_ID >= 70200
            case PDO_ATTR_DEFAULT_STR_PARAM:
            {
                if (Z_TYPE_P(val) != IS_LONG) {
                    THROW_PDO_ERROR(driver_dbh, PDO_SQLSRV_ERROR_EXTENDED_STRING_TYPE_INVALID);
                }

                zend_long value = Z_LVAL_P(val);
                if (value == PDO_PARAM_STR_NATL) {
                    driver_dbh->use_national_characters = 1;
                }
                else if (value == PDO_PARAM_STR_CHAR) {
                    driver_dbh->use_national_characters = 0;
                }
                else {
                    THROW_PDO_ERROR(driver_dbh, PDO_SQLSRV_ERROR_EXTENDED_STRING_TYPE_INVALID);
                }
            }
            break;
#endif

            // 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_CURSOR_NAME:  
            case PDO_ATTR_AUTOCOMMIT:
            case PDO_ATTR_PERSISTENT:
            case PDO_ATTR_TIMEOUT:
            {
                THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_UNSUPPORTED_DBH_ATTR );
            }

            // Read-only
            case PDO_ATTR_SERVER_VERSION:
            case PDO_ATTR_SERVER_INFO:  
            case PDO_ATTR_CLIENT_VERSION:
            case PDO_ATTR_DRIVER_NAME:
            case PDO_ATTR_CONNECTION_STATUS:    
            {
                THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_READ_ONLY_DBH_ATTR );
            }

            case PDO_ATTR_EMULATE_PREPARES:
                {
                    driver_dbh->emulate_prepare = zend_is_true(val);
                    if (driver_dbh->emulate_prepare && driver_dbh->ce_option.enabled) {
                        THROW_PDO_ERROR(driver_dbh, PDO_SQLSRV_ERROR_CE_EMULATE_PREPARE_UNSUPPORTED);
                    }
                }
                break;
            // Statement level only
            case PDO_ATTR_CURSOR:
            case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:    
            case SQLSRV_ATTR_DATA_CLASSIFICATION:
            {
                THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
            }

            default:
            {
                THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_INVALID_DBH_ATTR );
                break;
            }
        }
    }
    catch( pdo::PDOException& ) {
#if PHP_VERSION_ID < 80100
        return 0;
#else
        return false;
#endif
    }

#if PHP_VERSION_ID < 80100
    return 1;
#else
    return true;
#endif
}