1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-18 04:58:51 +02:00

Add Perl interface to C PgQuery object.

This validates that all current queries work with the new interface and removes the dependency on DBD::Pg.
This commit is contained in:
David Steele 2019-07-25 17:05:39 -04:00
parent 415542b4a3
commit d8ca0e5c5b
16 changed files with 362 additions and 234 deletions

View File

@ -458,24 +458,24 @@
</execute-list>
<!-- Perl installation -->
<p><backrest/> contains embedded Perl which requires some additional modules.</p>
<p><backrest/> contains embedded Perl which requires some additional packages.</p>
<execute-list host="{[br-install-host]}">
<title>Install required Perl packages</title>
<execute if="{[os-type-is-debian]}" user="root" pre="y">
<exe-cmd>apt-get install libdbd-pg-perl</exe-cmd>
<exe-cmd>apt-get install perl</exe-cmd>
<exe-cmd-extra>-y 2>&amp;1</exe-cmd-extra>
</execute>
<execute if="{[os-type-is-centos6]}" user="root" pre="y">
<exe-cmd>yum install perl perl-Time-HiRes perl-parent perl-JSON
perl-Digest-SHA perl-DBD-Pg</exe-cmd>
perl-Digest-SHA</exe-cmd>
<exe-cmd-extra>-y 2>&amp;1</exe-cmd-extra>
</execute>
<execute if="{[os-type-is-centos7]}" user="root" pre="y">
<exe-cmd>yum install perl perl-Time-HiRes perl-Digest-SHA perl-DBD-Pg perl-JSON-PP</exe-cmd>
<exe-cmd>yum install perl perl-Time-HiRes perl-Digest-SHA perl-JSON-PP</exe-cmd>
<exe-cmd-extra>-y 2>&amp;1</exe-cmd-extra>
</execute>
</execute-list>

View File

@ -6,13 +6,13 @@ package pgBackRest::Db;
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';
use DBD::Pg ':async';
use DBI;
use Exporter qw(import);
our @EXPORT = qw();
use Fcntl qw(O_RDONLY);
use File::Basename qw(dirname);
use JSON::PP;
use pgBackRest::DbVersion;
use pgBackRest::Common::Exception;
@ -126,10 +126,10 @@ sub DESTROY
# Assign function parameters, defaults, and log debug info
my ($strOperation) = logDebugParam(__PACKAGE__ . '->DESTROY');
if (defined($self->{hDb}))
if (defined($self->{oDb}))
{
$self->{hDb}->disconnect();
undef($self->{hDb});
$self->{oDb}->close();
undef($self->{oDb});
}
# Return from function and log return values if any
@ -167,63 +167,46 @@ sub connect
# Else run locally
else
{
if (!defined($self->{hDb}))
if (!defined($self->{oDb}))
{
# Connect to the db
my $strDbName = 'postgres';
my $strDbSocketPath = cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $self->{iRemoteIdx}), false);
$self->{oDb} = new pgBackRest::LibC::PgClient(
cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $self->{iRemoteIdx}), false),
cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $self->{iRemoteIdx})), 'postgres',
cfgOption(CFGOPT_DB_TIMEOUT) * 1000);
# Make sure the socket path is absolute
if (defined($strDbSocketPath) && $strDbSocketPath !~ /^\//)
if ($bWarnOnError)
{
confess &log(ERROR, "'${strDbSocketPath}' is not valid for '" . cfgOptionName(CFGOPT_PG_SOCKET_PATH) . "' option:" .
" path must be absolute", ERROR_OPTION_INVALID_VALUE);
}
# Construct the URI
my $strDbUri =
"dbi:Pg:dbname=${strDbName};port=" . cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $self->{iRemoteIdx})) .
(defined($strDbSocketPath) ? ";host=${strDbSocketPath}" : '');
logDebugMisc
(
$strOperation, undef,
{name => 'strDbUri', value => $strDbUri},
);
$self->{hDb} = DBI->connect($strDbUri, undef, undef,
{AutoCommit => 1, RaiseError => 0, PrintError => 0, Warn => 0});
# If db handle is not valid then check error
if (!$self->{hDb})
{
# Throw an error unless a warning was requested
if (!$bWarnOnError)
eval
{
confess &log(ERROR, $DBI::errstr, ERROR_DB_CONNECT);
$self->{oDb}->open();
return true;
}
or do
{
&log(WARN, exceptionMessage($EVAL_ERROR));
$bResult = false;
# Log a warning
&log(WARN, $DBI::errstr);
$bResult = false;
undef($self->{hDb});
undef($self->{oDb});
}
}
else
{
$self->{oDb}->open();
}
if (defined($self->{oDb}))
{
my ($fDbVersion) = $self->versionGet();
if ($fDbVersion >= PG_VERSION_APPLICATION_NAME)
{
# Set application name for monitoring and debugging
$self->{hDb}->do(
$self->{oDb}->query(
"set application_name = '" . PROJECT_NAME . ' [' .
(cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())) . "]'")
or confess &log(ERROR, $self->{hDb}->errstr, ERROR_DB_QUERY);
(cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())) . "]'");
# Clear search path to prevent possible function overrides
$self->{hDb}->do("set search_path = 'pg_catalog'")
or confess &log(ERROR, $self->{hDb}->errstr, ERROR_DB_QUERY);
$self->{oDb}->query("set search_path = 'pg_catalog'");
}
}
}
@ -273,73 +256,11 @@ sub executeSql
else
{
$self->connect();
my $strResult = $self->{oDb}->query($strSql);
# Prepare the query
my $hStatement = $self->{hDb}->prepare($strSql, {pg_async => PG_ASYNC})
or confess &log(ERROR, $DBI::errstr . ":\n${strSql}", ERROR_DB_QUERY);
# Execute the query
$hStatement->execute()
or confess &log(ERROR, $DBI::errstr. ":\n${strSql}", ERROR_DB_QUERY);
# Wait for the query to return
my $oWait = waitInit(cfgOption(CFGOPT_DB_TIMEOUT));
my $bTimeout = true;
do
if (defined($strResult))
{
# Is the statement done?
if ($hStatement->pg_ready())
{
# return now if there is no result expected
if (!$bResult)
{
return \@stryResult;
}
if (!$hStatement->pg_result())
{
# Return if the error should be ignored
if ($bIgnoreError)
{
return \@stryResult;
}
# Else report it
confess &log(ERROR, $DBI::errstr . ":\n${strSql}", ERROR_DB_QUERY);
}
# Get rows and return them
my @stryRow;
do
{
# Get next row
@stryRow = $hStatement->fetchrow_array;
# If the row has data then add it to the result
if (@stryRow)
{
push(@{$stryResult[@stryResult]}, @stryRow);
}
# Else check for error
elsif ($hStatement->err)
{
confess &log(ERROR, $DBI::errstr . ":\n${strSql}", ERROR_DB_QUERY);
}
}
while (@stryRow);
$bTimeout = false;
}
} while ($bTimeout && waitMore($oWait));
# If timeout then cancel the query and confess
if ($bTimeout)
{
$hStatement->pg_cancel();
confess &log(ERROR, 'statement timed out after ' . waitInterval($oWait) .
" second(s):\n${strSql}", ERROR_DB_TIMEOUT);
@stryResult = @{JSON::PP->new()->allow_nonref()->decode($strResult)};
}
}
@ -864,7 +785,7 @@ sub walSwitch
# the user if there have been no writes since the last WAL switch.
if ($self->{strDbVersion} >= PG_VERSION_91)
{
$self->executeSql("select pg_create_restore_point('" . PROJECT_NAME . " Archive Check');");
$self->executeSql("select pg_create_restore_point('" . PROJECT_NAME . " Archive Check')::text;");
}
my $strWalFileName = $self->executeSqlOne(
@ -1005,7 +926,7 @@ sub replayWait
if ($self->{strDbVersion} >= PG_VERSION_96)
{
$strCheckpointLSN = $self->executeSqlOne('select checkpoint_' . $self->lsnId() .' from pg_control_checkpoint()');
$strCheckpointLSN = $self->executeSqlOne('select checkpoint_' . $self->lsnId() .'::text from pg_control_checkpoint()');
if (lsnNormalize($strCheckpointLSN) le lsnNormalize($strTargetLSN))
{

View File

@ -72,6 +72,7 @@ These includes define data structures that are required for the C to Perl interf
***********************************************************************************************************************************/
#include "xs/crypto/hash.xsh"
#include "xs/common/encode.xsh"
#include "xs/postgres/client.xsh"
#include "xs/storage/storage.xsh"
#include "xs/storage/storageRead.xsh"
#include "xs/storage/storageWrite.xsh"
@ -102,6 +103,7 @@ INCLUDE: xs/config/configTest.xs
INCLUDE: xs/config/define.xs
INCLUDE: xs/crypto/hash.xs
INCLUDE: xs/crypto/random.xs
INCLUDE: xs/postgres/client.xs
INCLUDE: xs/postgres/pageChecksum.xs
INCLUDE: xs/storage/storage.xs
INCLUDE: xs/storage/storageRead.xs

View File

@ -99,6 +99,7 @@ my @stryCFile =
'protocol/parallel.c',
'protocol/parallelJob.c',
'protocol/server.c',
'postgres/client.c',
'postgres/pageChecksum.c',
'storage/posix/read.c',
'storage/posix/storage.c',
@ -132,6 +133,7 @@ WriteMakefile
-D_POSIX_C_SOURCE=200112L
-D_FILE_OFFSET_BITS=64
`xml2-config --cflags`
-I`pg_config --includedir`
)),
INC => join(' ', qw(
@ -141,7 +143,7 @@ WriteMakefile
C => \@stryCFile,
LIBS => '-lcrypto -lssl -lxml2',
LIBS => '-lcrypto -lpq -lssl -lxml2',
OBJECT => '$(O_FILES)',
);

View File

@ -1,3 +1,4 @@
pgBackRest::LibC::PgClient T_PTROBJ
pgBackRest::LibC::Storage T_PTROBJ
pgBackRest::LibC::StorageRead T_PTROBJ
pgBackRest::LibC::StorageWrite T_PTROBJ

View File

@ -0,0 +1,89 @@
# ----------------------------------------------------------------------------------------------------------------------------------
# PostgreSQL Query Client
# ----------------------------------------------------------------------------------------------------------------------------------
MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC::PgClient
####################################################################################################################################
pgBackRest::LibC::PgClient
new(class, host, port, database, queryTimeout)
PREINIT:
MEM_CONTEXT_XS_TEMP_BEGIN()
{
INPUT:
const String *class = STR_NEW_SV($arg);
const String *host = STR_NEW_SV($arg);
U32 port
const String *database = STR_NEW_SV($arg);
UV queryTimeout
CODE:
CHECK(strEqZ(class, PACKAGE_NAME_LIBC "::PgClient"));
memContextSwitch(MEM_CONTEXT_XS_OLD());
RETVAL = pgClientNew(host, port, database, NULL, queryTimeout);
memContextSwitch(MEM_CONTEXT_XS_TEMP());
OUTPUT:
RETVAL
CLEANUP:
}
MEM_CONTEXT_XS_TEMP_END();
####################################################################################################################################
void
open(self)
PREINIT:
MEM_CONTEXT_XS_TEMP_BEGIN()
{
INPUT:
pgBackRest::LibC::PgClient self
CODE:
pgClientOpen(self);
CLEANUP:
}
MEM_CONTEXT_XS_TEMP_END();
####################################################################################################################################
const char *
query(self, query)
PREINIT:
MEM_CONTEXT_XS_TEMP_BEGIN()
{
INPUT:
pgBackRest::LibC::PgClient self
const String *query = STR_NEW_SV($arg);
CODE:
VariantList *result = pgClientQuery(self, query);
RETVAL = result ? strPtr(jsonFromVar(varNewVarLst(result), 0)) : NULL;
OUTPUT:
RETVAL
CLEANUP:
}
MEM_CONTEXT_XS_TEMP_END();
####################################################################################################################################
void
close(self)
PREINIT:
MEM_CONTEXT_XS_TEMP_BEGIN()
{
INPUT:
pgBackRest::LibC::PgClient self
CODE:
pgClientClose(self);
CLEANUP:
}
MEM_CONTEXT_XS_TEMP_END();
####################################################################################################################################
void
DESTROY(self)
PREINIT:
MEM_CONTEXT_XS_TEMP_BEGIN()
{
INPUT:
pgBackRest::LibC::PgClient self
CODE:
pgClientFree(self);
CLEANUP:
}
MEM_CONTEXT_XS_TEMP_END();

View File

@ -0,0 +1,6 @@
/***********************************************************************************************************************************
PostgreSQL Query Client Header
***********************************************************************************************************************************/
#include "postgres/client.h"
typedef PgClient *pgBackRest__LibC__PgClient;

View File

@ -447,7 +447,7 @@ main.o: main.c build.auto.h command/archive/get/get.h command/archive/push/push.
perl/config.o: perl/config.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c perl/config.c -o perl/config.o
perl/exec.o: perl/exec.c ../libc/LibC.h build.auto.h common/assert.h common/compress/gzip/compress.h common/compress/gzip/decompress.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.h common/debug.h common/encode.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/filter/size.h common/io/http/client.h common/io/http/header.h common/io/http/query.h common/io/io.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h config/parse.h perl/config.h perl/embed.auto.c perl/exec.h perl/libc.auto.c postgres/interface.h postgres/pageChecksum.h storage/helper.h storage/info.h storage/posix/storage.h storage/read.h storage/read.intern.h storage/s3/storage.h storage/s3/storage.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h ../libc/xs/common/encode.xsh ../libc/xs/crypto/hash.xsh ../libc/xs/storage/storage.xsh ../libc/xs/storage/storageRead.xsh ../libc/xs/storage/storageWrite.xsh
perl/exec.o: perl/exec.c ../libc/LibC.h build.auto.h common/assert.h common/compress/gzip/compress.h common/compress/gzip/decompress.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.h common/debug.h common/encode.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/filter/size.h common/io/http/client.h common/io/http/header.h common/io/http/query.h common/io/io.h common/io/read.h common/io/read.intern.h common/io/write.h common/io/write.intern.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h config/parse.h perl/config.h perl/embed.auto.c perl/exec.h perl/libc.auto.c postgres/client.h postgres/interface.h postgres/pageChecksum.h storage/helper.h storage/info.h storage/posix/storage.h storage/read.h storage/read.intern.h storage/s3/storage.h storage/s3/storage.intern.h storage/storage.h storage/storage.intern.h storage/write.h storage/write.intern.h version.h ../libc/xs/common/encode.xsh ../libc/xs/crypto/hash.xsh ../libc/xs/postgres/client.xsh ../libc/xs/storage/storage.xsh ../libc/xs/storage/storageRead.xsh ../libc/xs/storage/storageWrite.xsh
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c perl/exec.c -o perl/exec.o
postgres/client.o: postgres/client.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h postgres/client.h

View File

@ -6889,13 +6889,13 @@ static const EmbeddedModule embeddedModule[] =
"use strict;\n"
"use warnings FATAL => qw(all);\n"
"use Carp qw(confess);\n"
"use English '-no_match_vars';\n"
"\n"
"use DBD::Pg ':async';\n"
"use DBI;\n"
"use Exporter qw(import);\n"
"our @EXPORT = qw();\n"
"use Fcntl qw(O_RDONLY);\n"
"use File::Basename qw(dirname);\n"
"use JSON::PP;\n"
"\n"
"use pgBackRest::DbVersion;\n"
"use pgBackRest::Common::Exception;\n"
@ -6984,10 +6984,10 @@ static const EmbeddedModule embeddedModule[] =
"\n\n"
"my ($strOperation) = logDebugParam(__PACKAGE__ . '->DESTROY');\n"
"\n"
"if (defined($self->{hDb}))\n"
"if (defined($self->{oDb}))\n"
"{\n"
"$self->{hDb}->disconnect();\n"
"undef($self->{hDb});\n"
"$self->{oDb}->close();\n"
"undef($self->{oDb});\n"
"}\n"
"\n\n"
"return logDebugReturn($strOperation);\n"
@ -7018,58 +7018,45 @@ static const EmbeddedModule embeddedModule[] =
"\n"
"else\n"
"{\n"
"if (!defined($self->{hDb}))\n"
"if (!defined($self->{oDb}))\n"
"{\n"
"$self->{oDb} = new pgBackRest::LibC::PgClient(\n"
"cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $self->{iRemoteIdx}), false),\n"
"cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $self->{iRemoteIdx})), 'postgres',\n"
"cfgOption(CFGOPT_DB_TIMEOUT) * 1000);\n"
"\n"
"my $strDbName = 'postgres';\n"
"my $strDbSocketPath = cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_SOCKET_PATH, $self->{iRemoteIdx}), false);\n"
"\n\n"
"if (defined($strDbSocketPath) && $strDbSocketPath !~ /^\\//)\n"
"if ($bWarnOnError)\n"
"{\n"
"confess &log(ERROR, \"'${strDbSocketPath}' is not valid for '\" . cfgOptionName(CFGOPT_PG_SOCKET_PATH) . \"' option:\" .\n"
"\" path must be absolute\", ERROR_OPTION_INVALID_VALUE);\n"
"eval\n"
"{\n"
"$self->{oDb}->open();\n"
"return true;\n"
"}\n"
"\n\n"
"my $strDbUri =\n"
"\"dbi:Pg:dbname=${strDbName};port=\" . cfgOption(cfgOptionIdFromIndex(CFGOPT_PG_PORT, $self->{iRemoteIdx})) .\n"
"(defined($strDbSocketPath) ? \";host=${strDbSocketPath}\" : '');\n"
"\n"
"logDebugMisc\n"
"(\n"
"$strOperation, undef,\n"
"{name => 'strDbUri', value => $strDbUri},\n"
");\n"
"\n"
"$self->{hDb} = DBI->connect($strDbUri, undef, undef,\n"
"{AutoCommit => 1, RaiseError => 0, PrintError => 0, Warn => 0});\n"
"\n\n"
"if (!$self->{hDb})\n"
"or do\n"
"{\n"
"\n"
"if (!$bWarnOnError)\n"
"{\n"
"confess &log(ERROR, $DBI::errstr, ERROR_DB_CONNECT);\n"
"}\n"
"\n\n"
"&log(WARN, $DBI::errstr);\n"
"\n"
"&log(WARN, exceptionMessage($EVAL_ERROR));\n"
"$bResult = false;\n"
"undef($self->{hDb});\n"
"\n"
"undef($self->{oDb});\n"
"}\n"
"}\n"
"else\n"
"{\n"
"$self->{oDb}->open();\n"
"}\n"
"\n"
"if (defined($self->{oDb}))\n"
"{\n"
"my ($fDbVersion) = $self->versionGet();\n"
"\n"
"if ($fDbVersion >= PG_VERSION_APPLICATION_NAME)\n"
"{\n"
"\n"
"$self->{hDb}->do(\n"
"$self->{oDb}->query(\n"
"\"set application_name = '\" . PROJECT_NAME . ' [' .\n"
"(cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())) . \"]'\")\n"
"or confess &log(ERROR, $self->{hDb}->errstr, ERROR_DB_QUERY);\n"
"(cfgOptionValid(CFGOPT_COMMAND) ? cfgOption(CFGOPT_COMMAND) : cfgCommandName(cfgCommandGet())) . \"]'\");\n"
"\n\n"
"$self->{hDb}->do(\"set search_path = 'pg_catalog'\")\n"
"or confess &log(ERROR, $self->{hDb}->errstr, ERROR_DB_QUERY);\n"
"$self->{oDb}->query(\"set search_path = 'pg_catalog'\");\n"
"}\n"
"}\n"
"}\n"
@ -7112,66 +7099,11 @@ static const EmbeddedModule embeddedModule[] =
"else\n"
"{\n"
"$self->connect();\n"
"\n\n"
"my $hStatement = $self->{hDb}->prepare($strSql, {pg_async => PG_ASYNC})\n"
"or confess &log(ERROR, $DBI::errstr . \":\\n${strSql}\", ERROR_DB_QUERY);\n"
"\n\n"
"$hStatement->execute()\n"
"or confess &log(ERROR, $DBI::errstr. \":\\n${strSql}\", ERROR_DB_QUERY);\n"
"\n\n"
"my $oWait = waitInit(cfgOption(CFGOPT_DB_TIMEOUT));\n"
"my $bTimeout = true;\n"
"my $strResult = $self->{oDb}->query($strSql);\n"
"\n"
"do\n"
"if (defined($strResult))\n"
"{\n"
"\n"
"if ($hStatement->pg_ready())\n"
"{\n"
"\n"
"if (!$bResult)\n"
"{\n"
"return \\@stryResult;\n"
"}\n"
"\n"
"if (!$hStatement->pg_result())\n"
"{\n"
"\n"
"if ($bIgnoreError)\n"
"{\n"
"return \\@stryResult;\n"
"}\n"
"\n\n"
"confess &log(ERROR, $DBI::errstr . \":\\n${strSql}\", ERROR_DB_QUERY);\n"
"}\n"
"\n\n"
"my @stryRow;\n"
"\n"
"do\n"
"{\n"
"\n"
"@stryRow = $hStatement->fetchrow_array;\n"
"\n\n"
"if (@stryRow)\n"
"{\n"
"push(@{$stryResult[@stryResult]}, @stryRow);\n"
"}\n"
"\n"
"elsif ($hStatement->err)\n"
"{\n"
"confess &log(ERROR, $DBI::errstr . \":\\n${strSql}\", ERROR_DB_QUERY);\n"
"}\n"
"}\n"
"while (@stryRow);\n"
"\n"
"$bTimeout = false;\n"
"}\n"
"} while ($bTimeout && waitMore($oWait));\n"
"\n\n"
"if ($bTimeout)\n"
"{\n"
"$hStatement->pg_cancel();\n"
"confess &log(ERROR, 'statement timed out after ' . waitInterval($oWait) .\n"
"\" second(s):\\n${strSql}\", ERROR_DB_TIMEOUT);\n"
"@stryResult = @{JSON::PP->new()->allow_nonref()->decode($strResult)};\n"
"}\n"
"}\n"
"\n\n"
@ -7593,7 +7525,7 @@ static const EmbeddedModule embeddedModule[] =
"\n\n\n"
"if ($self->{strDbVersion} >= PG_VERSION_91)\n"
"{\n"
"$self->executeSql(\"select pg_create_restore_point('\" . PROJECT_NAME . \" Archive Check');\");\n"
"$self->executeSql(\"select pg_create_restore_point('\" . PROJECT_NAME . \" Archive Check')::text;\");\n"
"}\n"
"\n"
"my $strWalFileName = $self->executeSqlOne(\n"
@ -7705,7 +7637,7 @@ static const EmbeddedModule embeddedModule[] =
"\n"
"if ($self->{strDbVersion} >= PG_VERSION_96)\n"
"{\n"
"$strCheckpointLSN = $self->executeSqlOne('select checkpoint_' . $self->lsnId() .' from pg_control_checkpoint()');\n"
"$strCheckpointLSN = $self->executeSqlOne('select checkpoint_' . $self->lsnId() .'::text from pg_control_checkpoint()');\n"
"\n"
"if (lsnNormalize($strCheckpointLSN) le lsnNormalize($strTargetLSN))\n"
"{\n"

View File

@ -80,6 +80,7 @@ These includes define data structures that are required for the C to Perl interf
***********************************************************************************************************************************/
#include "xs/crypto/hash.xsh"
#include "xs/common/encode.xsh"
#include "xs/postgres/client.xsh"
#include "xs/storage/storage.xsh"
#include "xs/storage/storageRead.xsh"
#include "xs/storage/storageWrite.xsh"
@ -268,7 +269,10 @@ XS_EUPXS(XS_pgBackRest__LibC_libcUvSize)
/* INCLUDE: Including 'xs/crypto/random.xs' from 'xs/crypto/hash.xs' */
/* INCLUDE: Including 'xs/postgres/pageChecksum.xs' from 'xs/crypto/random.xs' */
/* INCLUDE: Including 'xs/postgres/client.xs' from 'xs/crypto/random.xs' */
/* INCLUDE: Including 'xs/postgres/pageChecksum.xs' from 'xs/postgres/client.xs' */
/* INCLUDE: Including 'xs/storage/storage.xs' from 'xs/postgres/pageChecksum.xs' */
@ -1570,7 +1574,162 @@ XS_EUPXS(XS_pgBackRest__LibC_pageChecksum)
}
/* INCLUDE: Returning to 'xs/crypto/random.xs' from 'xs/postgres/pageChecksum.xs' */
/* INCLUDE: Returning to 'xs/postgres/client.xs' from 'xs/postgres/pageChecksum.xs' */
XS_EUPXS(XS_pgBackRest__LibC__PgClient_new); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_pgBackRest__LibC__PgClient_new)
{
dVAR; dXSARGS;
if (items != 5)
croak_xs_usage(cv, "class, host, port, database, queryTimeout");
{
MEM_CONTEXT_XS_TEMP_BEGIN()
{
const String * class = STR_NEW_SV(ST(0));
const String * host = STR_NEW_SV(ST(1));
U32 port = (unsigned long)SvUV(ST(2))
;
const String * database = STR_NEW_SV(ST(3));
UV queryTimeout = (UV)SvUV(ST(4))
;
pgBackRest__LibC__PgClient RETVAL;
CHECK(strEqZ(class, PACKAGE_NAME_LIBC "::PgClient"));
memContextSwitch(MEM_CONTEXT_XS_OLD());
RETVAL = pgClientNew(host, port, database, NULL, queryTimeout);
memContextSwitch(MEM_CONTEXT_XS_TEMP());
{
SV * RETVALSV;
RETVALSV = sv_newmortal();
sv_setref_pv(RETVALSV, "pgBackRest::LibC::PgClient", (void*)RETVAL);
ST(0) = RETVALSV;
}
}
MEM_CONTEXT_XS_TEMP_END();
}
XSRETURN(1);
}
XS_EUPXS(XS_pgBackRest__LibC__PgClient_open); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_pgBackRest__LibC__PgClient_open)
{
dVAR; dXSARGS;
if (items != 1)
croak_xs_usage(cv, "self");
{
MEM_CONTEXT_XS_TEMP_BEGIN()
{
pgBackRest__LibC__PgClient self;
if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::PgClient")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
self = INT2PTR(pgBackRest__LibC__PgClient,tmp);
}
else
Perl_croak_nocontext("%s: %s is not of type %s",
"pgBackRest::LibC::PgClient::open",
"self", "pgBackRest::LibC::PgClient")
;
pgClientOpen(self);
}
MEM_CONTEXT_XS_TEMP_END();
}
XSRETURN_EMPTY;
}
XS_EUPXS(XS_pgBackRest__LibC__PgClient_query); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_pgBackRest__LibC__PgClient_query)
{
dVAR; dXSARGS;
if (items != 2)
croak_xs_usage(cv, "self, query");
{
MEM_CONTEXT_XS_TEMP_BEGIN()
{
pgBackRest__LibC__PgClient self;
const String * query = STR_NEW_SV(ST(1));
const char * RETVAL;
dXSTARG;
if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::PgClient")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
self = INT2PTR(pgBackRest__LibC__PgClient,tmp);
}
else
Perl_croak_nocontext("%s: %s is not of type %s",
"pgBackRest::LibC::PgClient::query",
"self", "pgBackRest::LibC::PgClient")
;
VariantList *result = pgClientQuery(self, query);
RETVAL = result ? strPtr(jsonFromVar(varNewVarLst(result), 0)) : NULL;
sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
}
MEM_CONTEXT_XS_TEMP_END();
}
XSRETURN(1);
}
XS_EUPXS(XS_pgBackRest__LibC__PgClient_close); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_pgBackRest__LibC__PgClient_close)
{
dVAR; dXSARGS;
if (items != 1)
croak_xs_usage(cv, "self");
{
MEM_CONTEXT_XS_TEMP_BEGIN()
{
pgBackRest__LibC__PgClient self;
if (SvROK(ST(0)) && sv_derived_from(ST(0), "pgBackRest::LibC::PgClient")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
self = INT2PTR(pgBackRest__LibC__PgClient,tmp);
}
else
Perl_croak_nocontext("%s: %s is not of type %s",
"pgBackRest::LibC::PgClient::close",
"self", "pgBackRest::LibC::PgClient")
;
pgClientClose(self);
}
MEM_CONTEXT_XS_TEMP_END();
}
XSRETURN_EMPTY;
}
XS_EUPXS(XS_pgBackRest__LibC__PgClient_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_pgBackRest__LibC__PgClient_DESTROY)
{
dVAR; dXSARGS;
if (items != 1)
croak_xs_usage(cv, "self");
{
MEM_CONTEXT_XS_TEMP_BEGIN()
{
pgBackRest__LibC__PgClient self;
if (SvROK(ST(0))) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
self = INT2PTR(pgBackRest__LibC__PgClient,tmp);
}
else
Perl_croak_nocontext("%s: %s is not a reference",
"pgBackRest::LibC::PgClient::DESTROY",
"self")
;
pgClientFree(self);
}
MEM_CONTEXT_XS_TEMP_END();
}
XSRETURN_EMPTY;
}
/* INCLUDE: Returning to 'xs/crypto/random.xs' from 'xs/postgres/client.xs' */
XS_EUPXS(XS_pgBackRest__LibC_cryptoRandomBytes); /* prototype to pass -Wmissing-prototypes */
@ -2142,6 +2301,11 @@ XS_EXTERNAL(boot_pgBackRest__LibC)
newXS_deffile("pgBackRest::LibC::Storage::type", XS_pgBackRest__LibC__Storage_type);
newXS_deffile("pgBackRest::LibC::storageRepoFree", XS_pgBackRest__LibC_storageRepoFree);
newXS_deffile("pgBackRest::LibC::pageChecksum", XS_pgBackRest__LibC_pageChecksum);
newXS_deffile("pgBackRest::LibC::PgClient::new", XS_pgBackRest__LibC__PgClient_new);
newXS_deffile("pgBackRest::LibC::PgClient::open", XS_pgBackRest__LibC__PgClient_open);
newXS_deffile("pgBackRest::LibC::PgClient::query", XS_pgBackRest__LibC__PgClient_query);
newXS_deffile("pgBackRest::LibC::PgClient::close", XS_pgBackRest__LibC__PgClient_close);
newXS_deffile("pgBackRest::LibC::PgClient::DESTROY", XS_pgBackRest__LibC__PgClient_DESTROY);
newXS_deffile("pgBackRest::LibC::cryptoRandomBytes", XS_pgBackRest__LibC_cryptoRandomBytes);
newXS_deffile("pgBackRest::LibC::cryptoHashOne", XS_pgBackRest__LibC_cryptoHashOne);
newXS_deffile("pgBackRest::LibC::cfgCommandId", XS_pgBackRest__LibC_cfgCommandId);

View File

@ -13,10 +13,8 @@
# - docker tag pgbackrest/test:{vm}-base pgbackrest/test:{vm}-base-YYYYMMDDA
# - docker push pgbackrest/test:{vm}-base-YYYYMMDDA
# **********************************************************************************************************************************
20190705A:
u18: de2136d4a4ed6a7b8eaf6934c7e6f8e5c59f5ad4
20190701A:
co6: b3812cda61c33e959f309a9eceb23ef731fc0da2
co7: d645dbac2f094d980ac266094d0c26e84aca3ca6
u12: c919aa8562ff89713ee9ecf7dd41479798dde4d7
20190725A:
u18: 91252e3e21ff553b231094194e13966065c32d6b
co6: 194df5323239146733c51e77e9324b495bb2c727
co7: 3373903192a6dcf7c0b88c66ce9223da54ee2deb
u12: d3f1c8123b747b479586c2bbbf544c9a9cc42619

View File

@ -11,7 +11,6 @@ use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use DBI;
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);

View File

@ -11,7 +11,6 @@ use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use DBI;
use Exporter qw(import);
our @EXPORT = qw();
use Fcntl ':mode';

View File

@ -98,8 +98,7 @@ sub run
$self->optionTestSetBool(CFGOPT_ONLINE, true);
$self->configTestLoad(CFGCMD_STANZA_CREATE);
$self->testException(sub {(new pgBackRest::Stanza())}, ERROR_DB_CONNECT,
"could not connect to server: No such file or directory\n");
$self->testException(sub {(new pgBackRest::Stanza())}, ERROR_DB_CONNECT, "unable to connect to.*");
$self->optionTestSetBool(CFGOPT_ONLINE, false);
}

View File

@ -13,7 +13,13 @@
libxml2-dev,
txt2man,
zlib1g-dev
@@ -24,7 +22,7 @@
@@ -19,12 +18,12 @@
Package: pgbackrest
Architecture: any
-Depends: libdbd-pg-perl,
+Depends: perl,
postgresql-common,
${misc:Depends},
${perl:Depends},
${shlibs:Depends}

View File

@ -1,6 +1,6 @@
--- pgbackrest.spec
+++ pgbackrest.spec
@@ -10,7 +10,6 @@
@@ -10,15 +10,14 @@
Source0: https://github.com/pgbackrest/pgbackrest/archive/release/%{version}.tar.gz
Source1: pgbackrest-conf.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@ -8,3 +8,13 @@
%if 0%{?rhel} && 0%{?rhel} <= 6
Requires: perl-parent perl-JSON perl-Time-HiRes
%else
Requires: perl-JSON-PP
%endif
-Requires: perl-Digest-SHA perl-DBD-Pg perl-Time-HiRes zlib
+Requires: perl-Digest-SHA perl-Time-HiRes zlib libxml2
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
-BuildRequires: openssl-devel zlib-devel perl-ExtUtils-Embed
+BuildRequires: openssl-devel zlib-devel postgresql-libs perl-ExtUtils-Embed
%description
pgBackRest aims to be a simple, reliable backup and restore system that can