diff --git a/CHANGELOG.md b/CHANGELOG.md index 136ed23f3..1f9e0a73c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Added: - Add PG::Connection#embed_params and keyword `:typename` for its parameter casting. [#726](https://github.com/ged/ruby-pg/pull/726) This allows to generate SQL strings with embedded parameters for easier debugging. -- Add PG:Connection#full_protocol_version which is new in PostgreSQL-18 [#695](https://github.com/ged/ruby-pg/pull/695) +- Add PG::Connection#full_protocol_version which is new in PostgreSQL-18 [#695](https://github.com/ged/ruby-pg/pull/695) - Add PG::Result#each_tuple [#675](https://github.com/ged/ruby-pg/pull/675) - Add PG::TypeMap#query_param_encoders to retrieve encoders. [#726](https://github.com/ged/ruby-pg/pull/726) - Deduplicate result field name strings for better performance. [#750](https://github.com/ged/ruby-pg/pull/750) diff --git a/ext/extconf.rb b/ext/extconf.rb index a2f26886a..cabaa924a 100644 --- a/ext/extconf.rb +++ b/ext/extconf.rb @@ -304,8 +304,9 @@ module PG end have_func 'PQencryptPasswordConn', 'libpq-fe.h' or # since PostgreSQL-10 - abort "Your PostgreSQL is too old. Either install an older version " + - "of this gem or upgrade your database to at least PostgreSQL-10." + abort "Your PostgreSQL client library (libpq) is too old. " + + "Either install an older version of this gem " + + "or upgrade your database to at least PostgreSQL-10." # optional headers/functions have_func 'PQresultMemorySize', 'libpq-fe.h' # since PostgreSQL-12 have_func 'timegm' diff --git a/ext/pg.c b/ext/pg.c index e6e4ef1ac..0c615581d 100644 --- a/ext/pg.c +++ b/ext/pg.c @@ -384,14 +384,10 @@ Init_pg_ext(void) rb_define_const(rb_mPGconstants, "CONNECTION_SSL_STARTUP", INT2FIX(CONNECTION_SSL_STARTUP)); /* Internal state - PG.connect() needed. */ rb_define_const(rb_mPGconstants, "CONNECTION_NEEDED", INT2FIX(CONNECTION_NEEDED)); -#if PG_MAJORVERSION_NUM >= 10 - /* Checking if session is read-write. Available since PostgreSQL-10. */ + /* Checking if session is read-write. */ rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_WRITABLE", INT2FIX(CONNECTION_CHECK_WRITABLE)); -#endif -#if PG_MAJORVERSION_NUM >= 10 - /* Consuming any extra messages. Available since PostgreSQL-10. */ + /* Consuming any extra messages. */ rb_define_const(rb_mPGconstants, "CONNECTION_CONSUME", INT2FIX(CONNECTION_CONSUME)); -#endif #if PG_MAJORVERSION_NUM >= 12 /* Negotiating GSSAPI. Available since PostgreSQL-12. */ rb_define_const(rb_mPGconstants, "CONNECTION_GSS_STARTUP", INT2FIX(CONNECTION_GSS_STARTUP)); diff --git a/ext/pg_connection.c b/ext/pg_connection.c index abc2ceaab..8b8ec7bed 100644 --- a/ext/pg_connection.c +++ b/ext/pg_connection.c @@ -887,6 +887,8 @@ pgconn_protocol_version(VALUE self) * The 3.0 protocol is supported by PostgreSQL server versions 7.4 and above. * * PG::ConnectionBad is raised if the connection is bad. + * + * Available since PostgreSQL-18. */ static VALUE pgconn_full_protocol_version(VALUE self) diff --git a/lib/pg/connection.rb b/lib/pg/connection.rb index c65a7632c..064111752 100644 --- a/lib/pg/connection.rb +++ b/lib/pg/connection.rb @@ -551,33 +551,30 @@ def pipeline_sync(*args) alias async_pipeline_sync pipeline_sync end - if method_defined? :sync_encrypt_password - # call-seq: - # conn.encrypt_password( password, username, algorithm=nil ) -> String - # - # This function is intended to be used by client applications that wish to send commands like ALTER USER joe PASSWORD 'pwd'. - # It is good practice not to send the original cleartext password in such a command, because it might be exposed in command logs, activity displays, and so on. - # Instead, use this function to convert the password to encrypted form before it is sent. - # - # The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for. - # +algorithm+ specifies the encryption algorithm to use to encrypt the password. - # Currently supported algorithms are +md5+ and +scram-sha-256+ (+on+ and +off+ are also accepted as aliases for +md5+, for compatibility with older server versions). - # Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions. - # If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting. - # That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query. - # If you wish to use the default algorithm for the server but want to avoid blocking, query +password_encryption+ yourself before calling #encrypt_password, and pass that value as the algorithm. - # - # Return value is the encrypted password. - # The caller can assume the string doesn't contain any special characters that would require escaping. - # - # Available since PostgreSQL-10. - # See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN]. - def encrypt_password( password, username, algorithm=nil ) - algorithm ||= exec("SHOW password_encryption").getvalue(0,0) - sync_encrypt_password(password, username, algorithm) - end - alias async_encrypt_password encrypt_password + # call-seq: + # conn.encrypt_password( password, username, algorithm=nil ) -> String + # + # This function is intended to be used by client applications that wish to send commands like ALTER USER joe PASSWORD 'pwd'. + # It is good practice not to send the original cleartext password in such a command, because it might be exposed in command logs, activity displays, and so on. + # Instead, use this function to convert the password to encrypted form before it is sent. + # + # The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for. + # +algorithm+ specifies the encryption algorithm to use to encrypt the password. + # Currently supported algorithms are +md5+ and +scram-sha-256+ (+on+ and +off+ are also accepted as aliases for +md5+, for compatibility with older server versions). + # Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions. + # If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting. + # That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query. + # If you wish to use the default algorithm for the server but want to avoid blocking, query +password_encryption+ yourself before calling #encrypt_password, and pass that value as the algorithm. + # + # Return value is the encrypted password. + # The caller can assume the string doesn't contain any special characters that would require escaping. + # + # See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN]. + def encrypt_password( password, username, algorithm=nil ) + algorithm ||= exec("SHOW password_encryption").getvalue(0,0) + sync_encrypt_password(password, username, algorithm) end + alias async_encrypt_password encrypt_password # call-seq: # conn.reset() @@ -971,7 +968,6 @@ def new(*args) # Resolve DNS in Ruby to avoid blocking state while connecting. # Multiple comma-separated values are generated, if the hostname resolves to both IPv4 and IPv6 addresses. - # This requires PostgreSQL-10+, so no DNS resolving is done on earlier versions. private def resolve_hosts(iopts) ihosts = iopts[:host].split(",", -1) iports = iopts[:port].split(",", -1) @@ -1027,8 +1023,8 @@ def new(*args) # So, pass params through and let libpq resolve the service, possibly blocking the Thread.scheduler. # This ensures the processing order of libpq which is: # connection string => service file => environment variable => compiled default - elsif iopts_with_defaults[:host] && !iopts_with_defaults[:host].empty? && PG.library_version >= 100000 - # Do host resolution to avoid blocking Thread.scheduler while DNS queries. + elsif iopts_with_defaults[:host] && !iopts_with_defaults[:host].empty? + # Do host resolution in Ruby to avoid blocking Thread.scheduler while DNS queries in libpq. iopts_for_reset = iopts_with_defaults iopts = resolve_hosts(iopts_with_defaults) else diff --git a/spec/pg/connection_spec.rb b/spec/pg/connection_spec.rb index 0f9b60243..2444a6aef 100644 --- a/spec/pg/connection_spec.rb +++ b/spec/pg/connection_spec.rb @@ -2848,14 +2848,8 @@ def wait_check_socket(conn) end it "shouldn't type map params unless requested" do - if @conn.server_version < 100000 - expect{ - @conn.exec_params( "SELECT $1", [5] ) - }.to raise_error(PG::IndeterminateDatatype){|err| expect(err).to have_attributes(connection: @conn) } - else - # PostgreSQL-10 maps to TEXT type (OID 25) - expect( @conn.exec_params( "SELECT $1", [5] ).ftype(0)).to eq(25) - end + # PostgreSQL maps to TEXT type (OID 25) + expect( @conn.exec_params( "SELECT $1", [5] ).ftype(0)).to eq(25) end it "should raise an error on invalid encoder to put_copy_data" do