pg 1.6.0.rc1 → 1.6.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/{History.md → CHANGELOG.md} +28 -0
- data/Gemfile +1 -1
- data/README.ja.md +1 -1
- data/README.md +2 -1
- data/Rakefile +31 -7
- data/ext/extconf.rb +51 -13
- data/ext/pg.h +1 -0
- data/ext/pg_binary_encoder.c +8 -1
- data/ext/pg_coder.c +49 -0
- data/ext/pg_connection.c +31 -10
- data/ext/pg_text_encoder.c +18 -5
- data/ext/pg_type_map_by_column.c +1 -0
- data/ext/pg_type_map_by_oid.c +2 -0
- data/lib/pg/basic_type_map_for_queries.rb +7 -3
- data/lib/pg/cancel_connection.rb +26 -3
- data/lib/pg/coder.rb +2 -1
- data/lib/pg/connection.rb +84 -19
- data/lib/pg/version.rb +1 -1
- data/misc/yugabyte/Dockerfile +9 -0
- data/misc/yugabyte/docker-compose.yml +28 -0
- data/misc/yugabyte/pg-test.rb +45 -0
- data/pg.gemspec +3 -1
- data/ports/patches/krb5/1.21.3/0001-Allow-static-linking-krb5-library.patch +30 -0
- data/ports/patches/openssl/3.5.1/0001-aarch64-mingw.patch +21 -0
- data/ports/patches/postgresql/17.5/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
- data/ports/patches/postgresql/17.5/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
- data/rakelib/pg_gem_helper.rb +64 -0
- data.tar.gz.sig +0 -0
- metadata +26 -19
- metadata.gz.sig +0 -0
- data/Manifest.txt +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 956a534d3545f2d25ab922f903042bf6ae160f97c2b0e67a535d70559ce78cde
|
4
|
+
data.tar.gz: facd2045b9f51620fd66f407202d4b5d4f1ad31f991eef7b5eb4c2f4606416ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfbeb91b593698fbce35d3d7eb54b1c918ab741f96568faedcc045ddf0fe9917735d411df339f4fc2b7ced6d5fb4e9fb4845c56ee17d8b5880b30620741650c1
|
7
|
+
data.tar.gz: 71524df43d1c3891d9ecd052153f93e8e563b0ab5f4324292fe176bc8c93ace60be175fe275fb7546420d996b8cc7eecf27a254729029d566bcbe67c34ad67bc
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/{History.md → CHANGELOG.md}
RENAMED
@@ -1,3 +1,31 @@
|
|
1
|
+
## v1.6.0.rc2 [2025-07-16] Lars Kanis <lars@greiz-reinsdorf.de>
|
2
|
+
|
3
|
+
Added:
|
4
|
+
|
5
|
+
- Add binary gems for Ruby 3.4.
|
6
|
+
- Add fat binary gem for platform `aarch64-mingw-ucrt` aka Windows on ARM [#626](https://github.com/ged/ruby-pg/pull/626), for platform Macos on Intel and ARM [#643](https://github.com/ged/ruby-pg/pull/643) and for platform `aarch64-linux` [#646](https://github.com/ged/ruby-pg/pull/646).
|
7
|
+
- Update fat binary gem to OpenSSL-3.5.1 and PostgreSQL-17.5.
|
8
|
+
- Add a patch to libpq to avoid starvation on bigger SSL records, which some database engines other than vanilla PostgreSQL use.
|
9
|
+
This patch applies to platform specific binary gems only.
|
10
|
+
[#616](https://github.com/ged/ruby-pg/pull/616)
|
11
|
+
- Fix missing array input verification in PG::TypeMapByColumn.
|
12
|
+
This could cause a segfault.
|
13
|
+
[#620](https://github.com/ged/ruby-pg/pull/620)
|
14
|
+
- Add possibility to define the number of array dimensions to be encoded.
|
15
|
+
Setting dimensions is especially useful, when a Record shall be encoded into an Array, since the Array encoder can not distinguish if the array shall be encoded as a higher dimension or as a record otherwise.
|
16
|
+
[#622](https://github.com/ged/ruby-pg/pull/622)
|
17
|
+
- Add MINGW package dependency which is resolved by RubyInstaller.
|
18
|
+
[#617](https://github.com/ged/ruby-pg/pull/617)
|
19
|
+
- Change `conn.server_version` and `conn.protocol_version` to raise instead of return 0 on error.
|
20
|
+
[#632](https://github.com/ged/ruby-pg/pull/632)
|
21
|
+
- Fix making PG::BasicTypeMapForQueries shareable for Ractor in ruby-3.5.
|
22
|
+
[#636](https://github.com/ged/ruby-pg/pull/636)
|
23
|
+
- Rename `History.md` to `CHANGELOG.md`, which is more common.
|
24
|
+
[#642](https://github.com/ged/ruby-pg/pull/642)
|
25
|
+
- Fix connecting to multiple hosts after `connnect_timeout`.
|
26
|
+
[#637](https://github.com/ged/ruby-pg/pull/637)
|
27
|
+
|
28
|
+
|
1
29
|
## v1.6.0.rc1 [2024-11-28] Lars Kanis <lars@greiz-reinsdorf.de>
|
2
30
|
|
3
31
|
Added:
|
data/Gemfile
CHANGED
@@ -13,7 +13,7 @@ end
|
|
13
13
|
group :test do
|
14
14
|
gem "bundler", ">= 1.16", "< 3.0"
|
15
15
|
gem "rake-compiler", "~> 1.0"
|
16
|
-
gem "rake-compiler-dock", "~> 1.
|
16
|
+
gem "rake-compiler-dock", "~> 1.9.1"
|
17
17
|
gem "rspec", "~> 3.5"
|
18
18
|
# "bigdecimal" is a gem on ruby-3.4+ and it's optional for ruby-pg.
|
19
19
|
# Specs should succeed without it, but 4 examples are then excluded.
|
data/README.ja.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
* ホーム :: https://github.com/ged/ruby-pg
|
4
4
|
* ドキュメント :: http://deveiate.org/code/pg (英語)、 https://deveiate.org/code/pg/README_ja_md.html (日本語)
|
5
|
-
* 変更履歴 :: link:/
|
5
|
+
* 変更履歴 :: link:/CHANGELOG.md
|
6
6
|
|
7
7
|
[](https://gitter.im/ged/ruby-pg?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
* home :: https://github.com/ged/ruby-pg
|
4
4
|
* docs :: http://deveiate.org/code/pg (English) ,
|
5
5
|
https://deveiate.org/code/pg/README_ja_md.html (Japanese)
|
6
|
-
* clog :: link:/
|
6
|
+
* clog :: link:/CHANGELOG.md
|
7
7
|
|
8
8
|
[](https://gitter.im/ged/ruby-pg?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
9
9
|
|
@@ -175,6 +175,7 @@ The following type maps are prefilled with type mappings from the PG::BasicTypeR
|
|
175
175
|
* PG::BasicTypeMapBasedOnResult - a PG::TypeMapByOid prefilled with encoders for common PostgreSQL column types
|
176
176
|
* PG::BasicTypeMapForQueries - a PG::TypeMapByClass prefilled with encoders for common Ruby value classes
|
177
177
|
|
178
|
+
Several type maps can be chained by setting PG::TypeMap::DefaultTypeMappable#default_type_map .
|
178
179
|
|
179
180
|
## Thread support
|
180
181
|
|
data/Rakefile
CHANGED
@@ -11,6 +11,7 @@ require 'rake/clean'
|
|
11
11
|
require 'rspec/core/rake_task'
|
12
12
|
require 'bundler'
|
13
13
|
require 'bundler/gem_helper'
|
14
|
+
require_relative "rakelib/pg_gem_helper"
|
14
15
|
|
15
16
|
# Build directory constants
|
16
17
|
BASEDIR = Pathname( __FILE__ ).dirname
|
@@ -32,9 +33,9 @@ CLEAN.include "lib/*/libpq.dll"
|
|
32
33
|
CLEAN.include "lib/pg_ext.*"
|
33
34
|
CLEAN.include "lib/pg/postgresql_lib_path.rb"
|
34
35
|
CLEAN.include "ports/*.installed"
|
35
|
-
CLEAN.include "ports/*mingw*", "ports/*linux*"
|
36
|
+
CLEAN.include "ports/*mingw*", "ports/*linux*", "ports/*darwin*"
|
36
37
|
|
37
|
-
|
38
|
+
PgGemHelper.install_tasks
|
38
39
|
$gem_spec = Bundler.load_gemspec(GEMSPEC)
|
39
40
|
|
40
41
|
desc "Turn on warnings and debugging in the build."
|
@@ -44,14 +45,21 @@ end
|
|
44
45
|
|
45
46
|
CrossLibrary = Struct.new :platform, :openssl_config, :toolchain
|
46
47
|
CrossLibraries = [
|
48
|
+
['aarch64-mingw-ucrt', 'mingwarm64', 'aarch64-w64-mingw32'],
|
47
49
|
['x64-mingw-ucrt', 'mingw64', 'x86_64-w64-mingw32'],
|
48
50
|
['x86-mingw32', 'mingw', 'i686-w64-mingw32'],
|
49
51
|
['x64-mingw32', 'mingw64', 'x86_64-w64-mingw32'],
|
50
|
-
['x86_64-linux', 'linux-x86_64', 'x86_64-
|
52
|
+
['x86_64-linux', 'linux-x86_64', 'x86_64-linux-gnu'],
|
53
|
+
['aarch64-linux', 'linux-aarch64', 'aarch64-linux-gnu'],
|
54
|
+
['x86_64-darwin', 'darwin64-x86_64', 'x86_64-apple-darwin'],
|
55
|
+
['arm64-darwin', 'darwin64-arm64', 'arm64-apple-darwin'],
|
51
56
|
].map do |platform, openssl_config, toolchain|
|
52
57
|
CrossLibrary.new platform, openssl_config, toolchain
|
53
58
|
end
|
54
59
|
|
60
|
+
# Register binary gems to be pushed to rubygems.org
|
61
|
+
Bundler::GemHelper.instance.cross_platforms = CrossLibraries.map(&:platform)
|
62
|
+
|
55
63
|
# Rake-compiler task
|
56
64
|
Rake::ExtensionTask.new do |ext|
|
57
65
|
ext.name = 'pg_ext'
|
@@ -75,6 +83,7 @@ Rake::ExtensionTask.new do |ext|
|
|
75
83
|
# Add libpq.dll/.so to fat binary gemspecs
|
76
84
|
ext.cross_compiling do |spec|
|
77
85
|
spec.files << "ports/#{spec.platform.to_s}/lib/libpq-ruby-pg.so.1" if spec.platform.to_s =~ /linux/
|
86
|
+
spec.files << "ports/#{spec.platform.to_s}/lib/libpq-ruby-pg.1.dylib" if spec.platform.to_s =~ /darwin/
|
78
87
|
spec.files << "ports/#{spec.platform.to_s}/lib/libpq.dll" if spec.platform.to_s =~ /mingw|mswin/
|
79
88
|
end
|
80
89
|
end
|
@@ -95,18 +104,33 @@ task 'gem:native:prepare' do
|
|
95
104
|
end
|
96
105
|
end
|
97
106
|
|
107
|
+
task 'install_darwin_mig', [:arch] do |t, args|
|
108
|
+
sh <<~EOT
|
109
|
+
rm -rf bootstrap_cmds &&
|
110
|
+
git clone --branch=cross_platform https://github.com/markmentovai/bootstrap_cmds &&
|
111
|
+
cd bootstrap_cmds &&
|
112
|
+
autoreconf --install &&
|
113
|
+
sh configure &&
|
114
|
+
make &&
|
115
|
+
sed -E -i 's/^cppflags=(.*)/cppflags=(\\1 "-D#{args[:arch]}" "-I\\/opt\\/osxcross\\/target\\/SDK\\/MacOSX11.1.sdk\\/usr\\/include")/' migcom.tproj/mig.sh &&
|
116
|
+
sudo make install
|
117
|
+
EOT
|
118
|
+
end
|
119
|
+
|
98
120
|
CrossLibraries.each do |xlib|
|
99
121
|
platform = xlib.platform
|
100
122
|
desc "Build fat binary gem for platform #{platform}"
|
101
123
|
task "gem:native:#{platform}" => ['gem:native:prepare'] do
|
102
124
|
RakeCompilerDock.sh <<-EOT, platform: platform
|
103
|
-
#{ "sudo
|
125
|
+
#{ "sudo apt-get update && sudo apt-get install -y bison flex &&" if platform =~ /darwin/ }
|
104
126
|
#{ # remove nm on Linux to suppress PostgreSQL's check for exit which raises thread_exit as a false positive:
|
105
|
-
"sudo mv `which nm` `which nm`.bak &&
|
106
|
-
|
127
|
+
"sudo mv `which nm` `which nm`.bak &&" if platform =~ /linux/ }
|
128
|
+
sudo apt-get update && sudo apt-get install -y bison flex &&
|
107
129
|
(cp build/gem/gem-*.pem ~/.gem/ || true) &&
|
108
130
|
bundle install --local &&
|
109
|
-
rake
|
131
|
+
#{ "rake install_darwin_mig[__arm64__]" if platform =~ /arm64-darwin/ }
|
132
|
+
#{ "rake install_darwin_mig[__x86_64__]" if platform =~ /x86_64-darwin/ }
|
133
|
+
rake native:#{platform} pkg/#{$gem_spec.full_name}-#{platform}.gem MAKEOPTS=-j`nproc` RUBY_CC_VERSION=#{RakeCompilerDock.ruby_cc_version("~>2.7", "~>3.0")}
|
110
134
|
EOT
|
111
135
|
end
|
112
136
|
desc "Build the native binary gems"
|
data/ext/extconf.rb
CHANGED
@@ -27,13 +27,13 @@ if gem_platform=with_config("cross-build")
|
|
27
27
|
gem 'mini_portile2', '~>2.1'
|
28
28
|
require 'mini_portile2'
|
29
29
|
|
30
|
-
OPENSSL_VERSION = ENV['OPENSSL_VERSION'] || '3.
|
30
|
+
OPENSSL_VERSION = ENV['OPENSSL_VERSION'] || '3.5.1'
|
31
31
|
OPENSSL_SOURCE_URI = "http://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
|
32
32
|
|
33
33
|
KRB5_VERSION = ENV['KRB5_VERSION'] || '1.21.3'
|
34
34
|
KRB5_SOURCE_URI = "http://kerberos.org/dist/krb5/#{KRB5_VERSION[/^(\d+\.\d+)/]}/krb5-#{KRB5_VERSION}.tar.gz"
|
35
35
|
|
36
|
-
POSTGRESQL_VERSION = ENV['POSTGRESQL_VERSION'] || '17.
|
36
|
+
POSTGRESQL_VERSION = ENV['POSTGRESQL_VERSION'] || '17.5'
|
37
37
|
POSTGRESQL_SOURCE_URI = "http://ftp.postgresql.org/pub/source/v#{POSTGRESQL_VERSION}/postgresql-#{POSTGRESQL_VERSION}.tar.bz2"
|
38
38
|
|
39
39
|
class BuildRecipe < MiniPortile
|
@@ -69,7 +69,7 @@ if gem_platform=with_config("cross-build")
|
|
69
69
|
def configure
|
70
70
|
envs = []
|
71
71
|
envs << "CFLAGS=-DDSO_WIN32 -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /mingw|mswin/
|
72
|
-
envs << "CFLAGS=-fPIC -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /linux/
|
72
|
+
envs << "CFLAGS=-fPIC -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /linux|darwin/
|
73
73
|
execute('configure', ['env', *envs, "./Configure", openssl_platform, "threads", "-static", "CROSS_COMPILE=#{host}-", configure_prefix], altlog: "config.log")
|
74
74
|
end
|
75
75
|
def compile
|
@@ -85,22 +85,56 @@ if gem_platform=with_config("cross-build")
|
|
85
85
|
recipe.cook_and_activate
|
86
86
|
end
|
87
87
|
|
88
|
-
if RUBY_PLATFORM =~ /linux/
|
88
|
+
if RUBY_PLATFORM =~ /linux|darwin/
|
89
89
|
krb5_recipe = BuildRecipe.new("krb5", KRB5_VERSION, [KRB5_SOURCE_URI]).tap do |recipe|
|
90
90
|
class << recipe
|
91
91
|
def work_path
|
92
92
|
File.join(super, "src")
|
93
93
|
end
|
94
|
+
def configure
|
95
|
+
if RUBY_PLATFORM=~/darwin/
|
96
|
+
ENV["CC"] = host[/^.*[^\.\d]/] + "-clang"
|
97
|
+
ENV["CXX"] = host[/^.*[^\.\d]/] + "-c++"
|
98
|
+
|
99
|
+
# Manually set the correct values for configure checks that libkrb5 won't be
|
100
|
+
# able to perform because we're cross-compiling.
|
101
|
+
ENV["krb5_cv_attr_constructor_destructor"] = "yes"
|
102
|
+
ENV["ac_cv_func_regcomp"] = "yes"
|
103
|
+
ENV["ac_cv_printf_positional"] = "yes"
|
104
|
+
end
|
105
|
+
super
|
106
|
+
end
|
94
107
|
end
|
95
108
|
# We specify -fcommon to get around duplicate definition errors in recent gcc.
|
96
109
|
# See https://github.com/cockroachdb/cockroach/issues/49734
|
97
110
|
recipe.configure_options << "CFLAGS=-fcommon#{" -fPIC" if RUBY_PLATFORM =~ /linux/}"
|
111
|
+
recipe.configure_options << "LDFLAGS=-framework Kerberos" if RUBY_PLATFORM =~ /darwin/
|
98
112
|
recipe.configure_options << "--without-keyutils"
|
113
|
+
recipe.configure_options << "--disable-nls"
|
114
|
+
recipe.configure_options << "--disable-silent-rules"
|
115
|
+
recipe.configure_options << "--without-system-verto"
|
116
|
+
recipe.configure_options << "krb5_cv_attr_constructor_destructor=yes"
|
117
|
+
recipe.configure_options << "ac_cv_func_regcomp=yes"
|
118
|
+
recipe.configure_options << "ac_cv_printf_positional=yes"
|
99
119
|
recipe.host = toolchain
|
100
120
|
recipe.cook_and_activate
|
101
121
|
end
|
102
122
|
end
|
103
123
|
|
124
|
+
# We build a libpq library file which static links OpenSSL and krb5.
|
125
|
+
# Our builtin libpq is referenced in different ways depending on the OS:
|
126
|
+
# - Window: Add the ports directory at runtime per RubyInstaller::Runtime.add_dll_directory
|
127
|
+
# The file is called "libpq.dll"
|
128
|
+
# - Linux: Add a rpath to pg_ext.so which references the ports directory.
|
129
|
+
# The file is called "libpq-ruby-pg.so.1" to avoid loading of system libpq by accident.
|
130
|
+
# - Macos: Add a reference with relative path in pg_ext.so to the ports directory.
|
131
|
+
# The file is called "libpq-ruby-pg.1.dylib" to avoid loading of other libpq by accident.
|
132
|
+
libpq_orig, libpq_rubypg = case RUBY_PLATFORM
|
133
|
+
when /linux/ then ["libpq.so.5", "libpq-ruby-pg.so.1"]
|
134
|
+
when /darwin/ then ["libpq.5.dylib", "libpq-ruby-pg.1.dylib"]
|
135
|
+
# when /mingw/ then ["libpq.dll", "libpq.dll"] # renaming not needed
|
136
|
+
end
|
137
|
+
|
104
138
|
postgresql_recipe = BuildRecipe.new("postgresql", POSTGRESQL_VERSION, [POSTGRESQL_SOURCE_URI]).tap do |recipe|
|
105
139
|
class << recipe
|
106
140
|
def configure_defaults
|
@@ -108,9 +142,11 @@ if gem_platform=with_config("cross-build")
|
|
108
142
|
"--target=#{host}",
|
109
143
|
"--host=#{host}",
|
110
144
|
'--with-openssl',
|
111
|
-
*(RUBY_PLATFORM=~/linux/ ? ['--with-gssapi'] : []),
|
145
|
+
*(RUBY_PLATFORM=~/linux|darwin/ ? ['--with-gssapi'] : []),
|
112
146
|
'--without-zlib',
|
113
147
|
'--without-icu',
|
148
|
+
'--without-readline',
|
149
|
+
'ac_cv_search_gss_store_cred_into=',
|
114
150
|
]
|
115
151
|
end
|
116
152
|
def compile
|
@@ -121,23 +157,25 @@ if gem_platform=with_config("cross-build")
|
|
121
157
|
end
|
122
158
|
end
|
123
159
|
|
124
|
-
recipe.
|
125
|
-
recipe.configure_options << "
|
160
|
+
recipe.host = toolchain
|
161
|
+
recipe.configure_options << "CFLAGS=#{" -fPIC" if RUBY_PLATFORM =~ /linux|darwin/}"
|
162
|
+
recipe.configure_options << "LDFLAGS=-L#{openssl_recipe.path}/lib -L#{openssl_recipe.path}/lib64 -L#{openssl_recipe.path}/lib-arm64 #{"-Wl,-soname,#{libpq_rubypg} -lgssapi_krb5 -lkrb5 -lk5crypto -lkrb5support -ldl" if RUBY_PLATFORM =~ /linux/} #{"-Wl,-install_name,@loader_path/../../ports/#{gem_platform}/lib/#{libpq_rubypg} -lgssapi_krb5 -lkrb5 -lk5crypto -lkrb5support -lresolv -framework Kerberos" if RUBY_PLATFORM =~ /darwin/}"
|
126
163
|
recipe.configure_options << "LIBS=-lkrb5 -lcom_err -lk5crypto -lkrb5support -lresolv" if RUBY_PLATFORM =~ /linux/
|
127
164
|
recipe.configure_options << "LIBS=-lssl -lwsock32 -lgdi32 -lws2_32 -lcrypt32" if RUBY_PLATFORM =~ /mingw|mswin/
|
128
165
|
recipe.configure_options << "CPPFLAGS=-I#{openssl_recipe.path}/include"
|
129
|
-
recipe.host = toolchain
|
130
166
|
recipe.cook_and_activate
|
131
167
|
end
|
132
168
|
|
133
169
|
# Use our own library name for libpq to avoid loading of system libpq by accident.
|
134
|
-
FileUtils.ln_sf File.join(postgresql_recipe.port_path, "lib
|
135
|
-
File.join(postgresql_recipe.port_path, "lib
|
170
|
+
FileUtils.ln_sf File.join(postgresql_recipe.port_path, "lib/#{libpq_orig}"),
|
171
|
+
File.join(postgresql_recipe.port_path, "lib/#{libpq_rubypg}")
|
136
172
|
# Avoid dependency to external libgcc.dll on x86-mingw32
|
137
|
-
$LDFLAGS << " -static-libgcc"
|
138
|
-
#
|
173
|
+
$LDFLAGS << " -static-libgcc" if RUBY_PLATFORM =~ /mingw|mswin/
|
174
|
+
# Avoid: "libpq.so: undefined reference to `dlopen'" in cross-ruby-2.7.8
|
175
|
+
$LDFLAGS << " -Wl,--no-as-needed" if RUBY_PLATFORM !~ /aarch64|arm64|darwin/
|
176
|
+
# Find libpq in the ports directory coming from lib/3.x
|
139
177
|
# It is shared between all compiled ruby versions.
|
140
|
-
$LDFLAGS << " '-Wl,-rpath=$$ORIGIN/../../ports/#{gem_platform}/lib'"
|
178
|
+
$LDFLAGS << " '-Wl,-rpath=$$ORIGIN/../../ports/#{gem_platform}/lib'" if RUBY_PLATFORM =~ /linux/
|
141
179
|
# Don't use pg_config for cross build, but --with-pg-* path options
|
142
180
|
dir_config('pg', "#{postgresql_recipe.path}/include", "#{postgresql_recipe.path}/lib")
|
143
181
|
|
data/ext/pg.h
CHANGED
data/ext/pg_binary_encoder.c
CHANGED
@@ -320,6 +320,9 @@ pg_bin_enc_date(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, i
|
|
320
320
|
* This encoder expects an Array of values or sub-arrays as input.
|
321
321
|
* Other values are passed through as byte string without interpretation.
|
322
322
|
*
|
323
|
+
* It is possible to enforce a number of dimensions to be encoded by #dimensions= .
|
324
|
+
* Deeper nested arrays are then passed to the elements encoder and less nested arrays raise an ArgumentError.
|
325
|
+
*
|
323
326
|
* The accessors needs_quotation and delimiter are ignored for binary encoding.
|
324
327
|
*
|
325
328
|
*/
|
@@ -346,7 +349,8 @@ pg_bin_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
346
349
|
dim_sizes[ndim-1] = RARRAY_LENINT(el1);
|
347
350
|
nitems *= dim_sizes[ndim-1];
|
348
351
|
el2 = rb_ary_entry(el1, 0);
|
349
|
-
if (
|
352
|
+
if ( (this->dimensions < 0 || ndim < this->dimensions) &&
|
353
|
+
TYPE(el2) == T_ARRAY) {
|
350
354
|
ndim++;
|
351
355
|
if (ndim > MAXDIM)
|
352
356
|
rb_raise( rb_eArgError, "unsupported number of array dimensions: >%d", ndim );
|
@@ -356,6 +360,9 @@ pg_bin_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
356
360
|
el1 = el2;
|
357
361
|
}
|
358
362
|
}
|
363
|
+
if( this->dimensions >= 0 && (ndim==0 ? 1 : ndim) != this->dimensions ){
|
364
|
+
rb_raise(rb_eArgError, "less array dimensions to encode (%d) than expected (%d)", ndim, this->dimensions);
|
365
|
+
}
|
359
366
|
|
360
367
|
if(out){
|
361
368
|
/* Second encoder pass -> write data to `out` */
|
data/ext/pg_coder.c
CHANGED
@@ -135,6 +135,7 @@ pg_composite_encoder_allocate( VALUE klass )
|
|
135
135
|
this->elem = NULL;
|
136
136
|
this->needs_quotation = 1;
|
137
137
|
this->delimiter = ',';
|
138
|
+
this->dimensions = -1;
|
138
139
|
rb_iv_set( self, "@elements_type", Qnil );
|
139
140
|
return self;
|
140
141
|
}
|
@@ -157,6 +158,7 @@ pg_composite_decoder_allocate( VALUE klass )
|
|
157
158
|
this->elem = NULL;
|
158
159
|
this->needs_quotation = 1;
|
159
160
|
this->delimiter = ',';
|
161
|
+
this->dimensions = -1;
|
160
162
|
rb_iv_set( self, "@elements_type", Qnil );
|
161
163
|
return self;
|
162
164
|
}
|
@@ -421,6 +423,49 @@ pg_coder_delimiter_get(VALUE self)
|
|
421
423
|
return rb_str_new(&this->delimiter, 1);
|
422
424
|
}
|
423
425
|
|
426
|
+
/*
|
427
|
+
* call-seq:
|
428
|
+
* coder.dimensions = Integer
|
429
|
+
* coder.dimensions = nil
|
430
|
+
*
|
431
|
+
* Set number of array dimensions to be encoded.
|
432
|
+
*
|
433
|
+
* This property ensures, that this number of dimensions is always encoded.
|
434
|
+
* If less dimensions than this number are in the given value, an ArgumentError is raised.
|
435
|
+
* If more dimensions than this number are in the value, the Array value is passed to the next encoder.
|
436
|
+
*
|
437
|
+
* Setting dimensions is especially useful, when a Record shall be encoded into an Array, since the Array encoder can not distinguish if the array shall be encoded as a higher dimension or as a record otherwise.
|
438
|
+
*
|
439
|
+
* The default is +nil+.
|
440
|
+
*
|
441
|
+
* See #dimensions
|
442
|
+
*/
|
443
|
+
static VALUE
|
444
|
+
pg_coder_dimensions_set(VALUE self, VALUE dimensions)
|
445
|
+
{
|
446
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
447
|
+
rb_check_frozen(self);
|
448
|
+
if(!NIL_P(dimensions) && NUM2INT(dimensions) < 0)
|
449
|
+
rb_raise( rb_eArgError, "dimensions must be nil or >= 0");
|
450
|
+
this->dimensions = NIL_P(dimensions) ? -1 : NUM2INT(dimensions);
|
451
|
+
return dimensions;
|
452
|
+
}
|
453
|
+
|
454
|
+
/*
|
455
|
+
* call-seq:
|
456
|
+
* coder.dimensions -> Integer | nil
|
457
|
+
*
|
458
|
+
* Get number of enforced array dimensions or +nil+ if not set.
|
459
|
+
*
|
460
|
+
* See #dimensions=
|
461
|
+
*/
|
462
|
+
static VALUE
|
463
|
+
pg_coder_dimensions_get(VALUE self)
|
464
|
+
{
|
465
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
466
|
+
return this->dimensions < 0 ? Qnil : INT2NUM(this->dimensions);
|
467
|
+
}
|
468
|
+
|
424
469
|
/*
|
425
470
|
* call-seq:
|
426
471
|
* coder.elements_type = coder
|
@@ -602,6 +647,8 @@ init_pg_coder(void)
|
|
602
647
|
*
|
603
648
|
* This is the base class for all type cast classes of PostgreSQL types,
|
604
649
|
* that are made up of some sub type.
|
650
|
+
*
|
651
|
+
* See PG::TextEncoder::Array, PG::TextDecoder::Array, PG::BinaryEncoder::Array, PG::BinaryDecoder::Array, etc.
|
605
652
|
*/
|
606
653
|
rb_cPG_CompositeCoder = rb_define_class_under( rb_mPG, "CompositeCoder", rb_cPG_Coder );
|
607
654
|
rb_define_method( rb_cPG_CompositeCoder, "elements_type=", pg_coder_elements_type_set, 1 );
|
@@ -610,6 +657,8 @@ init_pg_coder(void)
|
|
610
657
|
rb_define_method( rb_cPG_CompositeCoder, "needs_quotation?", pg_coder_needs_quotation_get, 0 );
|
611
658
|
rb_define_method( rb_cPG_CompositeCoder, "delimiter=", pg_coder_delimiter_set, 1 );
|
612
659
|
rb_define_method( rb_cPG_CompositeCoder, "delimiter", pg_coder_delimiter_get, 0 );
|
660
|
+
rb_define_method( rb_cPG_CompositeCoder, "dimensions=", pg_coder_dimensions_set, 1 );
|
661
|
+
rb_define_method( rb_cPG_CompositeCoder, "dimensions", pg_coder_dimensions_get, 0 );
|
613
662
|
|
614
663
|
/* Document-class: PG::CompositeEncoder < PG::CompositeCoder */
|
615
664
|
rb_cPG_CompositeEncoder = rb_define_class_under( rb_mPG, "CompositeEncoder", rb_cPG_CompositeCoder );
|
data/ext/pg_connection.c
CHANGED
@@ -845,31 +845,52 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
|
|
845
845
|
* call-seq:
|
846
846
|
* conn.protocol_version -> Integer
|
847
847
|
*
|
848
|
-
*
|
849
|
-
*
|
850
|
-
*
|
848
|
+
* Interrogates the frontend/backend protocol being used.
|
849
|
+
*
|
850
|
+
* Applications might wish to use this function to determine whether certain features are supported.
|
851
|
+
* Currently, the only value is 3 (3.0 protocol).
|
852
|
+
* The protocol version will not change after connection startup is complete, but it could theoretically change during a connection reset.
|
853
|
+
* The 3.0 protocol is supported by PostgreSQL server versions 7.4 and above.
|
854
|
+
*
|
855
|
+
* PG::ConnectionBad is raised if the connection is bad.
|
851
856
|
*/
|
852
857
|
static VALUE
|
853
858
|
pgconn_protocol_version(VALUE self)
|
854
859
|
{
|
855
|
-
|
860
|
+
int protocol_version = PQprotocolVersion(pg_get_pgconn(self));
|
861
|
+
if (protocol_version == 0) {
|
862
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQprotocolVersion() can't get protocol version");
|
863
|
+
}
|
864
|
+
return INT2NUM(protocol_version);
|
856
865
|
}
|
857
866
|
|
858
867
|
/*
|
859
868
|
* call-seq:
|
860
869
|
* conn.server_version -> Integer
|
861
870
|
*
|
862
|
-
*
|
863
|
-
*
|
864
|
-
*
|
865
|
-
*
|
866
|
-
*
|
871
|
+
* Returns an integer representing the server version.
|
872
|
+
*
|
873
|
+
* Applications might use this function to determine the version of the database server they are connected to.
|
874
|
+
* The result is formed by multiplying the server's major version number by 10000 and adding the minor version number.
|
875
|
+
* For example, version 10.1 will be returned as 100001, and version 11.0 will be returned as 110000.
|
876
|
+
*
|
877
|
+
* PG::ConnectionBad is raised if the connection is bad.
|
878
|
+
*
|
879
|
+
* Prior to major version 10, PostgreSQL used three-part version numbers in which the first two parts together represented the major version.
|
880
|
+
* For those versions, PQserverVersion uses two digits for each part; for example version 9.1.5 will be returned as 90105, and version 9.2.0 will be returned as 90200.
|
881
|
+
*
|
882
|
+
* Therefore, for purposes of determining feature compatibility, applications should divide the result of PQserverVersion by 100 not 10000 to determine a logical major version number.
|
883
|
+
* In all release series, only the last two digits differ between minor releases (bug-fix releases).
|
867
884
|
*
|
868
885
|
*/
|
869
886
|
static VALUE
|
870
887
|
pgconn_server_version(VALUE self)
|
871
888
|
{
|
872
|
-
|
889
|
+
int server_version = PQserverVersion(pg_get_pgconn(self));
|
890
|
+
if (server_version == 0) {
|
891
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQserverVersion() can't get server version");
|
892
|
+
}
|
893
|
+
return INT2NUM(server_version);
|
873
894
|
}
|
874
895
|
|
875
896
|
/*
|
data/ext/pg_text_encoder.c
CHANGED
@@ -537,7 +537,7 @@ quote_string(t_pg_coder *this, VALUE value, VALUE string, char *current_out, int
|
|
537
537
|
}
|
538
538
|
|
539
539
|
static char *
|
540
|
-
write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE string, int quote, int enc_idx)
|
540
|
+
write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE string, int quote, int enc_idx, int dimension)
|
541
541
|
{
|
542
542
|
int i;
|
543
543
|
|
@@ -545,6 +545,10 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
|
|
545
545
|
current_out = pg_rb_str_ensure_capa( string, 2, current_out, NULL );
|
546
546
|
*current_out++ = '{';
|
547
547
|
|
548
|
+
if( RARRAY_LEN(value) == 0 && this->dimensions >= 0 && dimension != this->dimensions ){
|
549
|
+
rb_raise(rb_eArgError, "less array dimensions to encode (%d) than expected (%d)", dimension, this->dimensions);
|
550
|
+
}
|
551
|
+
|
548
552
|
for( i=0; i<RARRAY_LEN(value); i++){
|
549
553
|
VALUE entry = rb_ary_entry(value, i);
|
550
554
|
|
@@ -554,17 +558,26 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
|
|
554
558
|
}
|
555
559
|
|
556
560
|
switch(TYPE(entry)){
|
557
|
-
case T_ARRAY:
|
558
|
-
current_out = write_array(this, entry, current_out, string, quote, enc_idx);
|
559
|
-
break;
|
560
561
|
case T_NIL:
|
562
|
+
if( this->dimensions >= 0 && dimension != this->dimensions ){
|
563
|
+
rb_raise(rb_eArgError, "less array dimensions to encode (%d) than expected (%d)", dimension, this->dimensions);
|
564
|
+
}
|
561
565
|
current_out = pg_rb_str_ensure_capa( string, 4, current_out, NULL );
|
562
566
|
*current_out++ = 'N';
|
563
567
|
*current_out++ = 'U';
|
564
568
|
*current_out++ = 'L';
|
565
569
|
*current_out++ = 'L';
|
566
570
|
break;
|
571
|
+
case T_ARRAY:
|
572
|
+
if( this->dimensions < 0 || dimension < this->dimensions ){
|
573
|
+
current_out = write_array(this, entry, current_out, string, quote, enc_idx, dimension+1);
|
574
|
+
break;
|
575
|
+
}
|
576
|
+
/* Number of dimensions reached -> handle array as normal value */
|
567
577
|
default:
|
578
|
+
if( this->dimensions >= 0 && dimension != this->dimensions ){
|
579
|
+
rb_raise(rb_eArgError, "less array dimensions to encode (%d) than expected (%d)", dimension, this->dimensions);
|
580
|
+
}
|
568
581
|
current_out = quote_string( this->elem, entry, string, current_out, quote, quote_array_buffer, this, enc_idx );
|
569
582
|
}
|
570
583
|
}
|
@@ -596,7 +609,7 @@ pg_text_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
596
609
|
VALUE out_str = rb_str_new(NULL, 0);
|
597
610
|
PG_ENCODING_SET_NOCHECK(out_str, enc_idx);
|
598
611
|
|
599
|
-
end_ptr = write_array(this, value, RSTRING_PTR(out_str), out_str, this->needs_quotation, enc_idx);
|
612
|
+
end_ptr = write_array(this, value, RSTRING_PTR(out_str), out_str, this->needs_quotation, enc_idx, 1);
|
600
613
|
|
601
614
|
rb_str_set_len( out_str, end_ptr - RSTRING_PTR(out_str) );
|
602
615
|
*intermediate = out_str;
|
data/ext/pg_type_map_by_column.c
CHANGED
@@ -54,6 +54,7 @@ pg_tmbc_fit_to_query( VALUE self, VALUE params )
|
|
54
54
|
t_tmbc *this = RTYPEDDATA_DATA( self );
|
55
55
|
t_typemap *default_tm;
|
56
56
|
|
57
|
+
Check_Type(params, T_ARRAY);
|
57
58
|
nfields = (int)RARRAY_LEN( params );
|
58
59
|
if ( this->nfields != nfields ) {
|
59
60
|
rb_raise( rb_eArgError, "number of result fields (%d) does not match number of mapped columns (%d)",
|
data/ext/pg_type_map_by_oid.c
CHANGED
@@ -315,6 +315,8 @@ pg_tmbo_coders( VALUE self )
|
|
315
315
|
* The type map will do Hash lookups for each result value, if the number of rows
|
316
316
|
* is below or equal +number+.
|
317
317
|
*
|
318
|
+
* Default is 10.
|
319
|
+
*
|
318
320
|
*/
|
319
321
|
static VALUE
|
320
322
|
pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
|
@@ -53,14 +53,18 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
|
|
53
53
|
@coder_maps = build_coder_maps(connection_or_coder_maps, registry: registry)
|
54
54
|
@array_encoders_by_klass = array_encoders_by_klass
|
55
55
|
@encode_array_as = :array
|
56
|
-
@if_undefined = if_undefined ||
|
56
|
+
@if_undefined = if_undefined || UndefinedDefault
|
57
57
|
init_encoders
|
58
58
|
end
|
59
59
|
|
60
|
-
|
61
|
-
|
60
|
+
class UndefinedDefault
|
61
|
+
def self.call(oid_name, format)
|
62
|
+
raise UndefinedEncoder, "no encoder defined for type #{oid_name.inspect} format #{format}"
|
63
|
+
end
|
62
64
|
end
|
63
65
|
|
66
|
+
private_constant :UndefinedDefault
|
67
|
+
|
64
68
|
# Change the mechanism that is used to encode ruby array values
|
65
69
|
#
|
66
70
|
# Possible values:
|
data/lib/pg/cancel_connection.rb
CHANGED
@@ -7,8 +7,24 @@ if defined?(PG::CancelConnection)
|
|
7
7
|
class PG::CancelConnection
|
8
8
|
include PG::Connection::Pollable
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
alias c_initialize initialize
|
11
|
+
|
12
|
+
def initialize(conn)
|
13
|
+
c_initialize(conn)
|
14
|
+
|
15
|
+
# A cancel connection is always to one destination server only.
|
16
|
+
# Prepare conninfo_hash with just enough information to allow a shared polling_loop.
|
17
|
+
@host = conn.host
|
18
|
+
@hostaddr = conn.hostaddr
|
19
|
+
@port = conn.port
|
20
|
+
|
21
|
+
@conninfo_hash = {
|
22
|
+
host: @host,
|
23
|
+
hostaddr: @hostaddr,
|
24
|
+
port: @port.to_s,
|
25
|
+
connect_timeout: conn.conninfo_hash[:connect_timeout],
|
26
|
+
}
|
27
|
+
end
|
12
28
|
|
13
29
|
# call-seq:
|
14
30
|
# conn.cancel
|
@@ -23,8 +39,15 @@ if defined?(PG::CancelConnection)
|
|
23
39
|
#
|
24
40
|
def cancel
|
25
41
|
start
|
26
|
-
polling_loop(:poll
|
42
|
+
polling_loop(:poll)
|
27
43
|
end
|
28
44
|
alias async_cancel cancel
|
45
|
+
|
46
|
+
# These private methods are there to allow a shared polling_loop.
|
47
|
+
private
|
48
|
+
attr_reader :host
|
49
|
+
attr_reader :hostaddr
|
50
|
+
attr_reader :port
|
51
|
+
attr_reader :conninfo_hash
|
29
52
|
end
|
30
53
|
end
|
data/lib/pg/coder.rb
CHANGED
@@ -76,12 +76,13 @@ module PG
|
|
76
76
|
elements_type: elements_type,
|
77
77
|
needs_quotation: needs_quotation?,
|
78
78
|
delimiter: delimiter,
|
79
|
+
dimensions: dimensions,
|
79
80
|
}
|
80
81
|
end
|
81
82
|
|
82
83
|
def inspect
|
83
84
|
str = super
|
84
|
-
str[-1,0] = " elements_type=#{elements_type.inspect} #{needs_quotation? ? 'needs' : 'no'} quotation"
|
85
|
+
str[-1,0] = " elements_type=#{elements_type.inspect} #{needs_quotation? ? 'needs' : 'no'} quotation#{dimensions && " #{dimensions} dimensions"}"
|
85
86
|
str
|
86
87
|
end
|
87
88
|
end
|