Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update CI and improve discard_results #500

Merged
merged 7 commits into from
Feb 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ install:
- ps: |
if ($env:RUBYDOWNLOAD -ne $null) {
$(new-object net.webclient).DownloadFile("https://github.com/oneclick/rubyinstaller2/releases/download/rubyinstaller-head/rubyinstaller-head-$env:RUBYDOWNLOAD.exe", "$pwd/ruby-setup.exe")
cmd /c ruby-setup.exe /verysilent /dir=C:/Ruby$env:ruby_version
cmd /c ruby-setup.exe /currentuser /verysilent /dir=C:/Ruby$env:ruby_version
}
- cmd: |
ridk enable
c:/msys64/usr/bin/bash -lc "pacman -S --noconfirm --needed ${MINGW_PACKAGE_PREFIX}-pkgconf ${MINGW_PACKAGE_PREFIX}-libyaml ${MINGW_PACKAGE_PREFIX}-gcc"
- ruby --version
- gem --version
- gem install bundler --conservative
Expand All @@ -18,19 +21,22 @@ install:
{
$(new-object net.webclient).DownloadFile('http://get.enterprisedb.com/postgresql/postgresql-' + $env:PGVERSION + '.exe', 'C:/postgresql-setup.exe')
cmd /c "C:/postgresql-setup.exe" --mode unattended --extract-only 1

$env:PATH = 'C:/Program Files/PostgreSQL/' + $env:PGVER + '/bin;' + $env:PATH
$env:PATH = 'C:/Program Files (x86)/PostgreSQL/' + $env:PGVER + '/bin;' + $env:PATH
} else {
c:/msys64/usr/bin/bash -lc "pacman -S --noconfirm --needed `${MINGW_PACKAGE_PREFIX}-postgresql"
}
$env:PATH = 'C:/Program Files/PostgreSQL/' + $env:PGVER + '/bin;' + $env:PATH
$env:PATH = 'C:/Program Files (x86)/PostgreSQL/' + $env:PGVER + '/bin;' + $env:PATH
- echo %PATH%
- pg_config
build_script:
- bundle exec rake -rdevkit compile --trace
test_script:
- bundle exec rake test PG_DEBUG=0
on_failure:
- find -name mkmf.log | xargs cat
environment:
matrix:
- ruby_version: "head"
RUBYDOWNLOAD: x86
PGVERSION: 10.20-1-windows
PGVER: 10
- ruby_version: "25"
PGVERSION: 9.3.25-1-windows
PGVER: 9.3
- ruby_version: "30-x64"
49 changes: 40 additions & 9 deletions .github/workflows/binary-gems.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: Binary gems

on: [push, pull_request]
on:
push:
pull_request:
workflow_dispatch:
schedule:
- cron: "0 5 * * 3" # At 05:00 on Wednesday # https://crontab.guru/#0_5_*_*_3

jobs:
job_build_x64:
Expand All @@ -12,12 +17,13 @@ jobs:
include:
- platform: "x64-mingw-ucrt"
- platform: "x64-mingw32"
- platform: "x86-mingw32"
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.1"
ruby-version: "3.2"
- run: bundle install

- name: Create a dummy cert to satisfy the build
Expand All @@ -31,7 +37,7 @@ jobs:
run: bundle exec rake gem:windows:${{ matrix.platform }}

- name: Upload binary gem
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: binary-gem
path: pkg/*.gem
Expand All @@ -43,25 +49,43 @@ jobs:
fail-fast: false
matrix:
include:
- ruby: "3.1"
- os: windows-latest
ruby: "3.2"
platform: "x64-mingw-ucrt"
PGVERSION: 15.1-1-windows-x64
- ruby: "2.5"
- os: windows-latest
ruby: "3.1.3-1"
platform: "x86-mingw32"
PGVERSION: 10.20-1-windows
- os: windows-latest
ruby: "2.5"
platform: "x64-mingw32"
PGVERSION: 10.20-1-windows

runs-on: windows-latest
runs-on: ${{ matrix.os }}
env:
PGVERSION: ${{ matrix.PGVERSION }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Ruby
if: matrix.platform != 'x86-mingw32'
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}

- name: Set up 32 bit x86 Ruby
if: matrix.platform == 'x86-mingw32'
run: |
$(new-object net.webclient).DownloadFile("https://github.com/oneclick/rubyinstaller2/releases/download/RubyInstaller-${{ matrix.ruby }}/rubyinstaller-${{ matrix.ruby }}-x86.exe", "$pwd/ruby-setup.exe")
cmd /c ruby-setup.exe /currentuser /verysilent /dir=C:/Ruby-${{ matrix.ruby }}
echo "c:/ruby-${{ matrix.ruby }}/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

c:/ruby-${{ matrix.ruby }}/bin/ridk enable
c:/msys64/usr/bin/bash -lc "pacman -S --noconfirm --needed make `${MINGW_PACKAGE_PREFIX}-pkgconf `${MINGW_PACKAGE_PREFIX}-libyaml `${MINGW_PACKAGE_PREFIX}-gcc `${MINGW_PACKAGE_PREFIX}-make"
echo "C:/msys64/$env:MSYSTEM_PREFIX/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Download gem from build job
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: binary-gem

Expand All @@ -79,8 +103,15 @@ jobs:
echo "PGUSER=$env:USERNAME" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "PGPASSWORD=" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- run: echo $env:PATH
- run: gem update --system 3.3.26
- run: bundle install
- run: gem install --local pg-*${{ matrix.platform }}.gem --verbose
- name: Run specs
run: ruby -rpg -S rspec -fd spec/**/*_spec.rb

- name: Print logs if job failed
if: ${{ failure() && matrix.os == 'windows-latest' }}
run: |
ridk enable
find "$(ruby -e"puts RbConfig::CONFIG[%q[libdir]]")" -name mkmf.log -print0 | xargs -0 cat
19 changes: 12 additions & 7 deletions .github/workflows/source-gem.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
name: Source gem

on: [push, pull_request]
on:
push:
pull_request:
workflow_dispatch:
schedule:
- cron: "0 5 * * 3" # At 05:00 on Wednesday # https://crontab.guru/#0_5_*_*_3

jobs:
job_build_gem:
name: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.1"
ruby-version: "3.2"

- name: Build source gem
run: gem build pg.gemspec

- name: Upload source gem
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: source-gem
path: "*.gem"
Expand All @@ -41,7 +46,7 @@ jobs:
ruby: "head"
PGVER: "15"
- os: ubuntu
ruby: "3.1"
ruby: "3.2"
PGVER: "12"
- os: ubuntu
os_ver: "20.04"
Expand All @@ -65,14 +70,14 @@ jobs:
MAKE: make -j2 V=1

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}

- name: Download gem from build job
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: source-gem

Expand Down
53 changes: 39 additions & 14 deletions ext/pg_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -2446,8 +2446,9 @@ pgconn_async_flush(VALUE self)
VALUE socket_io = pgconn_socket_io(self);
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));

if (events & PG_RUBY_IO_READABLE)
if (events & PG_RUBY_IO_READABLE){
pgconn_consume_input(self);
}
}
return Qtrue;
}
Expand Down Expand Up @@ -3126,17 +3127,27 @@ pgconn_async_get_last_result(VALUE self)
* conn.discard_results()
*
* Silently discard any prior query result that application didn't eat.
* This is done prior of Connection#exec and sibling methods and can
* be called explicitly when using the async API.
* This is internally used prior to Connection#exec and sibling methods.
* It doesn't raise an exception on connection errors, but returns +false+ instead.
*
* Returns:
* * +nil+ when the connection is already idle
* * +true+ when some results have been discarded
* * +false+ when a failure occured and the connection was closed
*
*/
static VALUE
pgconn_discard_results(VALUE self)
{
PGconn *conn = pg_get_pgconn(self);
VALUE socket_io;

if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
return Qnil;
switch( PQtransactionStatus(conn) ) {
case PQTRANS_IDLE:
case PQTRANS_INTRANS:
case PQTRANS_INERROR:
return Qnil;
default:;
}

socket_io = pgconn_socket_io(self);
Expand All @@ -3149,10 +3160,21 @@ pgconn_discard_results(VALUE self)
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
*/
while( gvl_PQisBusy(conn) ){
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
if ( PQconsumeInput(conn) == 0 ) {
pgconn_close_socket_io(self);
return Qfalse;
int events;

switch( PQflush(conn) ) {
case 1:
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
if (events & PG_RUBY_IO_READABLE){
if ( PQconsumeInput(conn) == 0 ) goto error;
}
break;
case 0:
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
if ( PQconsumeInput(conn) == 0 ) goto error;
break;
default:
goto error;
}
}

Expand All @@ -3162,7 +3184,9 @@ pgconn_discard_results(VALUE self)
status = PQresultStatus(cur);
PQclear(cur);
if (status == PGRES_COPY_IN){
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
while( gvl_PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
pgconn_async_flush(self);
}
}
if (status == PGRES_COPY_OUT){
for(;;) {
Expand All @@ -3171,10 +3195,7 @@ pgconn_discard_results(VALUE self)
if( st == 0 ) {
/* would block -> wait for readable data */
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
if ( PQconsumeInput(conn) == 0 ) {
pgconn_close_socket_io(self);
return Qfalse;
}
if ( PQconsumeInput(conn) == 0 ) goto error;
} else if( st > 0 ) {
/* some data retrieved -> discard it */
PQfreemem(buffer);
Expand All @@ -3187,6 +3208,10 @@ pgconn_discard_results(VALUE self)
}

return Qtrue;

error:
pgconn_close_socket_io(self);
return Qfalse;
}

/*
Expand Down
2 changes: 1 addition & 1 deletion spec/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ def with_env_vars(**kwargs)
config.filter_run_excluding( :postgresql_12 ) if PG.library_version < 120000
config.filter_run_excluding( :postgresql_14 ) if PG.library_version < 140000
config.filter_run_excluding( :unix_socket ) if RUBY_PLATFORM=~/mingw|mswin/i
config.filter_run_excluding( :scheduler ) if RUBY_VERSION < "3.0" || !Fiber.respond_to?(:scheduler)
config.filter_run_excluding( :scheduler ) if RUBY_VERSION < "3.0" || (RUBY_PLATFORM =~ /mingw|mswin/ && RUBY_VERSION < "3.1") || !Fiber.respond_to?(:scheduler)
config.filter_run_excluding( :scheduler_address_resolve ) if RUBY_VERSION < "3.1"
config.filter_run_excluding( :ipv6 ) if Addrinfo.getaddrinfo("localhost", nil, nil, :STREAM).size < 2

Expand Down
41 changes: 33 additions & 8 deletions spec/pg/connection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@
skip "this spec depends on out-of-memory condition in put_copy_data, which is not reliable on all platforms"
end

run_with_gate(60) do |conn, gate|
run_with_gate(200) do |conn, gate|
conn.setnonblocking(true)

res = nil
Expand All @@ -668,7 +668,7 @@
end

it "needs to flush data after send_query" do
run_with_gate(60) do |conn, gate|
run_with_gate(200) do |conn, gate|
conn.setnonblocking(true)

gate.stop
Expand Down Expand Up @@ -1510,12 +1510,37 @@
expect( conn.connect_poll ).to eq( PG::PGRES_POLLING_FAILED )
end

it "discards previous results at #discard_results" do
@conn.send_query( "select 1" )
@conn.discard_results
@conn.send_query( "select 41 as one" )
res = @conn.get_last_result
expect( res.to_a ).to eq( [{ 'one' => '41' }] )
describe "#discard_results" do

it "discards previous results" do
@conn.send_query( "select 1" )
expect( @conn.discard_results ).to eq( true )
@conn.send_query( "select 41 as one" )
res = @conn.get_last_result
expect( res.to_a ).to eq( [{ 'one' => '41' }] )
end

it "returns nil when in idle state", :without_transaction do
expect( @conn.discard_results ).to eq( nil )

@conn.transaction do
expect( @conn.discard_results ).to eq( nil )
end

@conn.transaction do
@conn.send_query( "WRONG COMMAND" )
@conn.get_result
@conn.get_result

expect( @conn.discard_results ).to be_nil
end
end

it "returns false on connection failures" do
conn = PG.connect(@conninfo)
conn.send_query("select pg_terminate_backend(pg_backend_pid());")
expect( conn.discard_results ).to eq( false )
end
end

it "discards previous results (if any) before waiting on #exec" do
Expand Down