Class Node
- java.lang.Object
-
- org.gjt.cuspy.JarX
-
- org.postgresql.pljava.packaging.Node
-
public class Node extends JarX
Extends the JarX extraction tool to provide aresolve
method that replaces prefixespljava/foo/
in path names stored in the archive with the result ofpg_config --foo
.As this represents a second extra
.class
file that has to be added to the installer jar anyway, it will also contain some methods intended to be useful for tasks related to installation and testing. The idea is not to go overboard, but supply a few methods largely modeled on the most basic ones of PostgreSQL'sPostgreSQL::Test::Cluster
Perl module (formerly namedPostgresNode
, from which the name of this class was taken). The methods can be invoked fromjshell
if its classpath includes the installer jar (and one of the PostgreSQL JDBC drivers).An introduction with examples is available.
Unlike the many capabilities of
PostgreSQL::Test::Cluster
, this only deals in TCP sockets bound tolocalhost
(StandardProtocolFamily.UNIX
finally arrived in Java 16 but this class does not support it yet) and only a few of the most basic operations.As in JarX itself, some liberties with coding style may be taken here to keep this one extra
.class
file from proliferating into a bunch of them.As the testing-related methods here are intended for ad-hoc or scripted use in
jshell
, they are typically declared to throw any checked exception, without further specifics. There are many overloads of methods namedq
andqp
(mnemonic of query and query-print), to make interactive use injshell
comfortable with just a few static imports.
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from class org.gjt.cuspy.JarX
JarX.Build
-
-
Field Summary
Fields Modifier and Type Field Description static InvocationHandler
NOTHING_OR_PGJDBC_ZERO_COUNT
A state (seestateMachine
) that expects nothing (if the driver is pgjdbc-ng) or a zero row count (if the driver is PGJDBC).static boolean
s_isWindows
True if the platform is determined to be Windows.static int
s_urlForm
The first form of PostgreSQL JDBC driver connection URL found to be recognized by an available driver, orURL_FORM_NONE
.static int
URL_FORM_NONE
Value ofs_urlForm
indicating no available JDBC driver was found to accept any of the supported connection URL forms.static int
URL_FORM_PGJDBC
Value ofs_urlForm
indicating an available JDBC driver reported accepting a connection URL in the PGJDBC form starting with"jdbc:postgresql:"
.static int
URL_FORM_PGJDBCNG
Value ofs_urlForm
indicating an available JDBC driver reported accepting a connection URL in the pgjdbc-ng form starting with"jdbc:pgsql:"
.-
Fields inherited from class org.gjt.cuspy.JarX
ALL, ARCHIVE_CHARSET, archiveCharset, ATOM, BYTES, CHARACTERS, COMMENT, defaultArchiveCharset, defaultExecutePermission, defaultReadPermission, defaultTreatment, defaultUnpackedCharset, defaultWritePermission, DOMAINLITERAL, executePermission, LINES, mainAttributes, manifestCode, manifestName, NONE, OWNER, PATHRESOLVER, PERMISSIONS, QUOTEDSTRING, readPermission, resolverEngine, resolverScript, treatment, TSPECIAL, type, UNPACKED_CHARSET, unpackedCharset, value, writePermission
-
-
Method Summary
Modifier and Type Method Description static Stream<Object>
appendClasspathIf(Connection c, String schema, String jarName)
Appends a jar to a schema's class path if not already included.static <T> T
as(Class<T> clazz, Object o)
Casts o to class clazz, testing it also for null.static ProcessBuilder
asPgCtlInvocation(ProcessBuilder pb)
Adjusts the command arguments of aProcessBuilder
that would directly invokepostgres
to start a server, so that it will instead startpostgres
viapg_ctl
.static String[]
classify(Throwable t)
Returns an array of threeString
s, element, sqlState, and message, as would be printed byqp(Throwable)
.void
clean_node()
Recursively removes the basedir and its descendants.void
clean_node(boolean keepRoot)
Recursively removes the basedir (unless keepRoot) and its descendants.Connection
connect()
Returns aConnection
to the server associated with this Node, using default properties appropriate for this setting.Connection
connect(Map<String,String> suppliedProperties)
Returns aConnection
to the server associated with this Node, with suppliedProperties overriding or supplementing the ones that would be passed by default.Connection
connect(Properties p)
Returns aConnection
to the server associated with this Node, with supplied properties p overriding or supplementing the ones that would be passed by default.Path
data_dir()
Returns the directory name to be used as the PostgreSQL data directory for this node.static boolean
examplesNeedSaxon()
Returns true if the examples jar includes theorg.postgresql.pljava.example.saxon.S9
class (meaning the appropriate Saxon jar must be installed and on the classpath first before the examples jar can be deployed, unlesscheck_function_bodies
isoff
to skip dependency checking).void
extract()
Extracts the jar contents, just as done in the normal case of running this class withjava -jar
.static Stream<Object>
flattenDiagnostics(Object oneResult)
A flat-mapping function to expand anySQLException
orSQLWarning
instance in a result stream into the stream of possibly multiple linked diagnostics and causes in the encounter order of theSQLException
iterator.static ProcessBuilder
forWindowsCRuntime(ProcessBuilder pb)
Adjusts the command arguments of aProcessBuilder
so that they will be recovered correctly on Windows by a target C/C++ program using the argument parsing algorithm of the usual C run-time code, when it is known that the command will not be handled first bycmd
.static int
get_free_port()
Returns a TCP port on the loopback interface that is free at the moment this method is called.static Node
get_new_node(String name)
Returns a newNode
that can be used to initialize and start a PostgreSQL instance.void
init()
Invokesinitdb
for the node, passing default options appropriate for this setting.void
init(UnaryOperator<ProcessBuilder> tweaks)
Invokesinitdb
for the node, passing default options appropriate for this setting, and tweaks to be applied to theProcessBuilder
before it is started.void
init(Map<String,String> suppliedOptions)
Invokesinitdb
for the node, with suppliedOptions overriding or supplementing the ones that would be passed by default.void
init(Map<String,String> suppliedOptions, UnaryOperator<ProcessBuilder> tweaks)
Invokesinitdb
for the node, with suppliedOptions overriding or supplementing the ones that would be passed by default, and tweaks to be applied to theProcessBuilder
before it is started.AutoCloseable
initialized_cluster()
Likeinit()
but returns anAutoCloseable
that will recursively remove the files and directories under the basedir (but not the basedir itself) on the exit of a calling try-with-resources scope.AutoCloseable
initialized_cluster(UnaryOperator<ProcessBuilder> tweaks)
Likeinit()
but returns anAutoCloseable
that will recursively remove the files and directories under the basedir (but not the basedir itself) on the exit of a calling try-with-resources scope.AutoCloseable
initialized_cluster(Map<String,String> suppliedOptions)
Likeinit()
but returns anAutoCloseable
that will recursively remove the files and directories under the basedir (but not the basedir itself) on the exit of a calling try-with-resources scope.AutoCloseable
initialized_cluster(Map<String,String> suppliedOptions, UnaryOperator<ProcessBuilder> tweaks)
Likeinit()
but returns anAutoCloseable
that will recursively remove the files and directories under the basedir (but not the basedir itself) on the exit of a calling try-with-resources scope.static Stream<Object>
installExamples(Connection c, boolean deploy)
Installs the examples jar, under the nameexamples
.static Stream<Object>
installExamplesAndPath(Connection c, boolean deploy)
Installs the examples jar, under the nameexamples
, and appends it to the class path for schemapublic
.static Stream<Object>
installJar(Connection c, String uri, String jarName, boolean deploy)
Installs a jar.static Stream<Object>
installSaxon(Connection c, String repo, String version)
Installs a Saxon jar under the namesaxon
, given the path to a local Maven repo and the needed version of Saxon, assuming the jar has been downloaded there already.static Stream<Object>
installSaxonAndExamplesAndPath(Connection c, String repo, String version, boolean deploy)
A four-fer: installs Saxon, adds it to the class path, then installs the examples jar, and updates the classpath to include both.static Stream<Object>
installSaxonAndPath(Connection c, String repo, String version)
Installs a Saxon jar under the namesaxon
, and appends it to the class path for schemapublic
.static boolean
isVoidResultSet(Object o, int rows, int columns)
A predicate testing that an object is aResultSet
that has only columns ofvoid
type, and the expected number of rows and columns.static Stream<Object>
loadPLJava(Connection c)
Loads PL/Java (with aLOAD
command, notCREATE EXTENSION
).static void
main(String[] args)
Performs an ordinary installation, usingpg_config
or the corresponding system properties to learn where the files belong, and unpacking the files (not including this class or its ancestors) there.static void
peek(Object o)
Prints an object in the manner ofqp
, but in a way suitable for use inStream.peek
.void
prepareResolver(String v)
Prepares the resolver, ignoring the passed string (ordinarily a script or rules); this resolver's rules are hardcoded.static Stream<Object>
q(Connection c, String sql)
Executes some arbitrary SQLstatic Stream<Object>
q(ParameterMetaData pmd)
Produces aStream
with an element for each parameter of aPreparedStatement
.static Stream<Object>
q(ResultSet rs)
Analogously toq(Statement,...)
, produces aStream
with an element for each row of aResultSet
, interleaved with anySQLWarning
s reported on the result set, or anSQLException
if one is thrown.static Stream<Object>
q(ResultSetMetaData rsmd)
Produces aStream
with an element for each column of aResultSet
.static Stream<Object>
q(Statement s, Callable<Boolean> work)
Produces aStream
of the (in JDBC, possibly multiple) results from someexecute
method on aStatement
.static void
qp(Object o)
Overload ofqp
for direct application to any oneObject
obtained from a result stream.static void
qp(Throwable t)
Prints aThrowable
retrieved from a result stream, with special handling forSQLException
andSQLWarning
.static void
qp(Connection c, String sql)
Executes some arbitrary SQL and passes the result stream toqp(Stream)
for printing to standard output.static void
qp(ParameterMetaData md)
Overload ofqp
for examiningParameterMetaData
.static void
qp(ResultSet rs)
Overload ofqp
for direct application to aResultSet
.static void
qp(ResultSetMetaData md)
Overload ofqp
for examiningResultSetMetaData
.static void
qp(Statement s, Callable<Boolean> work)
Invokes someexecute
method on aStatement
and passes the result stream toqp(Stream)
for printing to standard output.static void
qp(Stream<Object> s)
Prints streamed results of aStatement
in (somewhat) readable fashion.static void
qp(Stream<Object> s, Function<Object,Stream<Object>> flattener)
Prints streamed results of aStatement
in (somewhat) readable fashion, with a choice of flattener for diagnostics.static Stream<Object>
removeJar(Connection c, String jarName, boolean undeploy)
Removes a jar.String
resolve(String storedPath, String platformPath)
Replaces a prefixpljava/
key in a path to be extracted with the value of thepgconfig.
key system property, or the result of invokingpg_config
(or the exact executable named in thepgconfig
system property, if present) with the option--
key.static Stream<Object>
semiFlattenDiagnostics(Object oneResult)
A flat-mapping function to expand anySQLException
orSQLWarning
instance in a result stream into the stream of possibly multiple linked diagnostics in the order produced bygetNextException
orgetNextWarning
.static void
set_WARNING_localized(String s)
Changes the severity string used to recognize when the backend is sending aWARNING
.static Stream<Object>
setClasspath(Connection c, String schema, String... jarNames)
Sets the class path for a schema.static Stream<Object>
setConfig(Connection c, String settingName, String newValue, boolean isLocal)
Sets a configuration variable on the server.void
start()
Starts a PostgreSQL server for the node with default options appropriate for this setting.void
start(UnaryOperator<ProcessBuilder> tweaks)
Starts a PostgreSQL server for the node, passing default options appropriate for this setting, and tweaks to be applied to theProcessBuilder
before it is started.void
start(Map<String,String> suppliedOptions)
Starts a PostgreSQL server for the node, with suppliedOptions overriding or supplementing the ones that would be passed by default.void
start(Map<String,String> suppliedOptions, UnaryOperator<ProcessBuilder> tweaks)
Starts a PostgreSQL server for the node, with suppliedOptions overriding or supplementing the ones that would be passed by default, and tweaks to be applied to theProcessBuilder
before it is started.AutoCloseable
started_server()
Likestart()
but returns anAutoCloseable
that will stop the server on the exit of a calling try-with-resources scope.AutoCloseable
started_server(UnaryOperator<ProcessBuilder> tweaks)
Likestart()
but returns anAutoCloseable
that will stop the server on the exit of a calling try-with-resources scope.AutoCloseable
started_server(Map<String,String> suppliedOptions)
Likestart()
but returns anAutoCloseable
that will stop the server on the exit of a calling try-with-resources scope.AutoCloseable
started_server(Map<String,String> suppliedOptions, UnaryOperator<ProcessBuilder> tweaks)
Likestart()
but returns anAutoCloseable
that will stop the server on the exit of a calling try-with-resources scope.static boolean
stateMachine(String name, Consumer<String> reporter, Stream<Object> input, InvocationHandler... states)
Executes a state machine specified in the form of a list of lambdas representing its states, to verify that a result stream is as expected.void
stop()
Stops the server instance associated with this Node.void
stop(UnaryOperator<ProcessBuilder> tweaks)
Stops the server instance associated with this Node.String
toString()
Identifying information for a "node" instance, or for the singleton extractor instance.void
use_pg_ctl(boolean setting)
Sets whether to usepg_ctl
to start and stop the server (if true), or startpostgres
and stop it directly (if false, the default).static int[]
voidResultSetDims(Object o)
Equivalent tovoidResultSetDims(o,false)
;static int[]
voidResultSetDims(Object o, boolean peek)
Determines whether an object is aResultSet
with no columns of any type other thanvoid
, to allow abbreviated output of result sets produced by the common case of queries that callvoid
functions.-
Methods inherited from class org.gjt.cuspy.JarX
archiveCharsetFromType, classify, describeTranscoding, extract, holds, holdsIgnoreCase, is, notMe, setDefaults, shovel, shovelBytes, shovelChars, shovelLines, shovelText, structuredFieldBody
-
-
-
-
Field Detail
-
s_isWindows
public static final boolean s_isWindows
True if the platform is determined to be Windows.On Windows,
forWindowsCRuntime
should be applied to anyProcessBuilder
before invoking it; the details of the transformation applied byasPgCtlInvocation
change, anduse_pg_ctl
may prove useful, aspg_ctl
on Windows is able to drop administrative privileges that would otherwise preventpostgres
from starting.
-
s_urlForm
public static final int s_urlForm
The first form of PostgreSQL JDBC driver connection URL found to be recognized by an available driver, orURL_FORM_NONE
.
-
URL_FORM_NONE
public static final int URL_FORM_NONE
Value ofs_urlForm
indicating no available JDBC driver was found to accept any of the supported connection URL forms.- See Also:
- Constant Field Values
-
URL_FORM_PGJDBC
public static final int URL_FORM_PGJDBC
Value ofs_urlForm
indicating an available JDBC driver reported accepting a connection URL in the PGJDBC form starting with"jdbc:postgresql:"
.- See Also:
- Constant Field Values
-
URL_FORM_PGJDBCNG
public static final int URL_FORM_PGJDBCNG
Value ofs_urlForm
indicating an available JDBC driver reported accepting a connection URL in the pgjdbc-ng form starting with"jdbc:pgsql:"
.- See Also:
- Constant Field Values
-
NOTHING_OR_PGJDBC_ZERO_COUNT
public static final InvocationHandler NOTHING_OR_PGJDBC_ZERO_COUNT
A state (seestateMachine
) that expects nothing (if the driver is pgjdbc-ng) or a zero row count (if the driver is PGJDBC).For some utility statements (such as
CREATE EXTENSION
) with no result, the pgjdbc-ng driver will produce no result, while the PGJDBC driver produces a zero count, as it would for a DML statement that did not affect any rows. This state handles either case.When
URL_FORM_PGJDBCNG == s_urlForm
, this state consumes nothing and moves to the numerically next state. Otherwise (JDBC), it checks that the current object is a zero row count, consuming it and moving to the numerically next state if it is, returning false otherwise.
-
-
Method Detail
-
main
public static void main(String[] args) throws Exception
Performs an ordinary installation, usingpg_config
or the corresponding system properties to learn where the files belong, and unpacking the files (not including this class or its ancestors) there.- Throws:
Exception
-
extract
public void extract() throws Exception
Extracts the jar contents, just as done in the normal case of running this class withjava -jar
.Only to be called on the singleton instance
s_jarxHelper
.For a version that doesn't really extract anything, but still primes the
resolve
method to know where things should be extracted, seedryExtract()
.
-
prepareResolver
public void prepareResolver(String v) throws Exception
Prepares the resolver, ignoring the passed string (ordinarily a script or rules); this resolver's rules are hardcoded.- Overrides:
prepareResolver
in classJarX
- Parameters:
v
- value of the _JarX_PathResolver main attribute- Throws:
Exception
- this implementation throws no checked exceptions, but an overriding implementation may
-
resolve
public String resolve(String storedPath, String platformPath) throws Exception
Replaces a prefixpljava/
key in a path to be extracted with the value of thepgconfig.
key system property, or the result of invokingpg_config
(or the exact executable named in thepgconfig
system property, if present) with the option--
key.- Overrides:
resolve
in classJarX
- Parameters:
storedPath
- The path as stored in the archive, always /-separatedplatformPath
- The path after only replacing / with the platform separator- Returns:
- plat unchanged, or a corrected location for extracting the entry, or null to suppress extracting the entry
- Throws:
Exception
- this implementation may throw ScriptException, an overriding implementation may throw others
-
set_WARNING_localized
public static void set_WARNING_localized(String s)
Changes the severity string used to recognize when the backend is sending aWARNING
.When the driver is PGJDBC, the classification done here of
SQLWarning
instances into actual warning messages or informative ones depends on a tag ("WARNING" in English) that the backend delivers in the local language. For the classification to happen correctly when a different language is selected, use this method to supply the string (for example, "PERINGATAN" in Indonesian) that the backend uses for warnings in that language.
-
toString
public String toString()
Identifying information for a "node" instance, or for the singleton extractor instance.
-
get_new_node
public static Node get_new_node(String name) throws Exception
Returns a newNode
that can be used to initialize and start a PostgreSQL instance.Establishes a VM shutdown hook that will stop the server (if started) and recursively remove the basedir before the VM exits.
- Throws:
Exception
-
get_free_port
public static int get_free_port() throws Exception
Returns a TCP port on the loopback interface that is free at the moment this method is called.- Throws:
Exception
-
clean_node
public void clean_node() throws Exception
Recursively removes the basedir and its descendants.- Throws:
Exception
-
clean_node
public void clean_node(boolean keepRoot) throws Exception
Recursively removes the basedir (unless keepRoot) and its descendants.- Parameters:
keepRoot
- if true, the descendants are removed, but not the basedir itself.- Throws:
Exception
-
data_dir
public Path data_dir()
Returns the directory name to be used as the PostgreSQL data directory for this node.
-
initialized_cluster
public AutoCloseable initialized_cluster() throws Exception
Likeinit()
but returns anAutoCloseable
that will recursively remove the files and directories under the basedir (but not the basedir itself) on the exit of a calling try-with-resources scope.- Throws:
Exception
-
initialized_cluster
public AutoCloseable initialized_cluster(Map<String,String> suppliedOptions) throws Exception
Likeinit()
but returns anAutoCloseable
that will recursively remove the files and directories under the basedir (but not the basedir itself) on the exit of a calling try-with-resources scope.- Throws:
Exception
-
initialized_cluster
public AutoCloseable initialized_cluster(UnaryOperator<ProcessBuilder> tweaks) throws Exception
Likeinit()
but returns anAutoCloseable
that will recursively remove the files and directories under the basedir (but not the basedir itself) on the exit of a calling try-with-resources scope.- Throws:
Exception
-
initialized_cluster
public AutoCloseable initialized_cluster(Map<String,String> suppliedOptions, UnaryOperator<ProcessBuilder> tweaks) throws Exception
Likeinit()
but returns anAutoCloseable
that will recursively remove the files and directories under the basedir (but not the basedir itself) on the exit of a calling try-with-resources scope.- Throws:
Exception
-
init
public void init() throws Exception
Invokesinitdb
for the node, passing default options appropriate for this setting.- Throws:
Exception
-
init
public void init(Map<String,String> suppliedOptions) throws Exception
Invokesinitdb
for the node, with suppliedOptions overriding or supplementing the ones that would be passed by default.- Throws:
Exception
-
init
public void init(UnaryOperator<ProcessBuilder> tweaks) throws Exception
Invokesinitdb
for the node, passing default options appropriate for this setting, and tweaks to be applied to theProcessBuilder
before it is started.- Throws:
Exception
-
init
public void init(Map<String,String> suppliedOptions, UnaryOperator<ProcessBuilder> tweaks) throws Exception
Invokesinitdb
for the node, with suppliedOptions overriding or supplementing the ones that would be passed by default, and tweaks to be applied to theProcessBuilder
before it is started.By default,
postgres
will be the name of the superuser, UTF-8 will be the encoding,auth-local
will bepeer
andauth-host
will bemd5
. The initialization will skipfsync
for speed rather than safety (if something goes wrong, justclean_node()
and start over).The
initdb
that will be run is the one in thebindir
reported bypg_config
(or set by-Dpgconfig.bindir
).- Parameters:
suppliedOptions
- a Map where each key is an option to initdb (for example, --encoding), and the value corresponds.tweaks
- a lambda applicable to theProcessBuilder
to further configure it. On Windows, the tweaks will be applied ahead of transformation of the arguments byforWindowsCRuntime
.- Throws:
Exception
-
started_server
public AutoCloseable started_server() throws Exception
Likestart()
but returns anAutoCloseable
that will stop the server on the exit of a calling try-with-resources scope.- Throws:
Exception
-
started_server
public AutoCloseable started_server(Map<String,String> suppliedOptions) throws Exception
Likestart()
but returns anAutoCloseable
that will stop the server on the exit of a calling try-with-resources scope.- Throws:
Exception
-
started_server
public AutoCloseable started_server(UnaryOperator<ProcessBuilder> tweaks) throws Exception
Likestart()
but returns anAutoCloseable
that will stop the server on the exit of a calling try-with-resources scope.Supplied tweaks will be applied to the
ProcessBuilder
used to start the server; ifpg_ctl
is being used, they will also be applied when runningpg_ctl stop
to stop it.- Throws:
Exception
-
started_server
public AutoCloseable started_server(Map<String,String> suppliedOptions, UnaryOperator<ProcessBuilder> tweaks) throws Exception
Likestart()
but returns anAutoCloseable
that will stop the server on the exit of a calling try-with-resources scope.Supplied tweaks will be applied to the
ProcessBuilder
used to start the server; ifpg_ctl
is being used, they will also be applied when runningpg_ctl stop
to stop it.- Throws:
Exception
-
start
public void start() throws Exception
Starts a PostgreSQL server for the node with default options appropriate for this setting.- Throws:
Exception
-
start
public void start(Map<String,String> suppliedOptions) throws Exception
Starts a PostgreSQL server for the node, with suppliedOptions overriding or supplementing the ones that would be passed by default.- Throws:
Exception
-
start
public void start(UnaryOperator<ProcessBuilder> tweaks) throws Exception
Starts a PostgreSQL server for the node, passing default options appropriate for this setting, and tweaks to be applied to theProcessBuilder
before it is started.- Throws:
Exception
-
start
public void start(Map<String,String> suppliedOptions, UnaryOperator<ProcessBuilder> tweaks) throws Exception
Starts a PostgreSQL server for the node, with suppliedOptions overriding or supplementing the ones that would be passed by default, and tweaks to be applied to theProcessBuilder
before it is started.By default, the server will listen only on the loopback interface and not on any Unix-domain socket, on the port selected when this Node was created, and for a maximum of 16 connections. Its cluster name will be the name given to this Node, and fsync will be off to favor speed over durability. The log line prefix will be shortened to just the node name and (when connected) the
application_name
.The server that will be run is the one in the
bindir
reported bypg_config
(or set by-Dpgconfig.bindir
).If the server is PostgreSQL 10 or later, it is definitely ready to accept connections when this method returns. If not, it is highly likely to be ready, but no test connection has been made to confirm it.
- Parameters:
suppliedOptions
- a Map where the key is a configuration variable name as seen inpostgresql.conf
or passed to the server with-c
and the value corresponds.tweaks
- a lambda applicable to theProcessBuilder
to further configure it. Underuse_pg_ctl(true)
, the tweaks are applied after the arguments have been transformed byasPgCtlInvocation
. On Windows, they are applied ahead of transformation of the arguments byforWindowsCRuntime
.- Throws:
Exception
-
stop
public void stop() throws Exception
Stops the server instance associated with this Node.Has the effect of
stop(tweaks)
without any tweaks.- Throws:
Exception
-
stop
public void stop(UnaryOperator<ProcessBuilder> tweaks) throws Exception
Stops the server instance associated with this Node.No effect if it has not been started or has already been stopped, but a message to standard error is logged if the server had been started and the process is found to have exited unexpectedly.
- Parameters:
tweaks
- tweaks to apply to a ProcessBuilder; unused unlesspg_ctl
will be used to stop the server. When used, they are applied ahead of the transformation of the arguments byforWindowsCRuntime
used on Windows.- Throws:
Exception
-
use_pg_ctl
public void use_pg_ctl(boolean setting)
Sets whether to usepg_ctl
to start and stop the server (if true), or startpostgres
and stop it directly (if false, the default).On Windows,
pg_ctl
is able to drop administrator rights and start the server from an account that would otherwise trigger the server's refusal to start from a privileged account.
-
connect
public Connection connect() throws Exception
Returns aConnection
to the server associated with this Node, using default properties appropriate for this setting.- Throws:
Exception
-
connect
public Connection connect(Map<String,String> suppliedProperties) throws Exception
Returns aConnection
to the server associated with this Node, with suppliedProperties overriding or supplementing the ones that would be passed by default.- Throws:
Exception
-
connect
public Connection connect(Properties p) throws Exception
Returns aConnection
to the server associated with this Node, with supplied properties p overriding or supplementing the ones that would be passed by default.By default, the connection is to the
postgres
database as thepostgres
user, using the password internally generated for this node, and with anapplication_name
generated from a counter of connections for this node.- Throws:
Exception
-
setConfig
public static Stream<Object> setConfig(Connection c, String settingName, String newValue, boolean isLocal) throws Exception
Sets a configuration variable on the server.This deserves a convenience method because the most familiar PostgreSQL syntax for SET doesn't lend itself to parameterization.
- Returns:
- a result stream from executing the statement
- Throws:
Exception
-
loadPLJava
public static Stream<Object> loadPLJava(Connection c) throws Exception
Loads PL/Java (with aLOAD
command, notCREATE EXTENSION
).This was standard procedure in PostgreSQL versions that pre-dated the extension support. It is largely obsolete with the advent of
CREATE EXTENSION
, but still has one distinct use case: this is what will work if you do not have administrative access to install PL/Java's files in the standard directories whereCREATE EXTENSION
expects them, but can only place them in some other location the server can read. Then you simply have to make sure thatpljava.module_path
is set correctly to locate the jar files, and give the correct shared-object path toLOAD
(which this method does).It is also useful to see better diagnostics if something is going wrong, as PostgreSQL severely suppresses diagnostic messages during
CREATE EXTENSION
.- Returns:
- a result stream from executing the statement
- Throws:
Exception
-
installJar
public static Stream<Object> installJar(Connection c, String uri, String jarName, boolean deploy) throws Exception
Installs a jar.- Returns:
- a result stream from executing the statement
- Throws:
Exception
-
removeJar
public static Stream<Object> removeJar(Connection c, String jarName, boolean undeploy) throws Exception
Removes a jar.- Returns:
- a result stream from executing the statement
- Throws:
Exception
-
setClasspath
public static Stream<Object> setClasspath(Connection c, String schema, String... jarNames) throws Exception
Sets the class path for a schema.- Returns:
- a result stream from executing the statement
- Throws:
Exception
-
appendClasspathIf
public static Stream<Object> appendClasspathIf(Connection c, String schema, String jarName) throws Exception
Appends a jar to a schema's class path if not already included.- Returns:
- a result stream that
includes, on success, a one-column
void
result set with a single row if the jar was added to the path, and no rows if the jar was already included. - Throws:
Exception
-
q
public static Stream<Object> q(Connection c, String sql) throws Exception
Executes some arbitrary SQL- Returns:
- a result stream from executing the statement
- Throws:
Exception
-
q
public static Stream<Object> q(Statement s, Callable<Boolean> work) throws Exception
Produces aStream
of the (in JDBC, possibly multiple) results from someexecute
method on aStatement
.This is how, for example, to prepare, then examine the results of, a
PreparedStatement
:PreparedStatement ps = conn.prepareStatement("select foo(?,?)"); ps.setInt(1, 42); ps.setString(2, "surprise!"); q(ps, ps::execute);
Each result in the stream will be an instance of one of:
ResultSet
,Long
(an update count, positive or zero),SQLWarning
, or some otherSQLException
. A warning or exception may have others chained to it, which its owniterator
orforEach
methods should be used to traverse; or, useflatMap(
Node::flattenDiagnostics
) to obtain a stream presenting each diagnostic in a chain in turn. TheCallable
interface supplying the work to be done allows any checked exception, but anyThrowable
outside theSQLException
hierarchy will simply be rethrown from here rather than delivered in the stream. AnyThrowable
thrown by work will result in theStatement
being closed. Otherwise, it remains open until the returned stream is closed.Exists mainly to encapsulate the rather fiddly logic of extracting that sequence of results using the
Statement
API.- Parameters:
s
- the Statement from which to extract resultswork
- a Callable that will invoke one of the Statement's execute methods returning a boolean that indicates whether the first result is a ResultSet. Although the Callable interface requires the boolean result to be boxed, it must not return null.- Returns:
- a Stream as described above.
- Throws:
Exception
-
q
public static Stream<Object> q(ResultSet rs) throws Exception
Analogously toq(Statement,...)
, produces aStream
with an element for each row of aResultSet
, interleaved with anySQLWarning
s reported on the result set, or anSQLException
if one is thrown.This is supplied chiefly for use driving a
state machine
to verify contents of a result set. For each row, the element in the stream will be an instance ofLong
, counting up from 1 (intended to match the result set'sgetRow
but without relying on it, as JDBC does not require every implementation to support it). By itself, of course, this does not convey any of the content of the row; the lambdas representing the machine states should close over the result set and query it for content, perhaps not even using the object supplied here (except to detect when it is a warning or exception rather than a row number). The row position of the result set will have been updated, and should not be otherwise modified when this method is being used to walk through the results.For the same reason, don't try any funny business like sorting the stream in any way. The
ResultSet
will only be read forward, and each row only once. Simple filtering,dropWhile
/takeWhile
, and so on will work, but may be more conveniently rolled into the design of astate machine
, as nearly any use of aResultSet
can throwSQLException
and therefore isn't convenient in the stream API.Passing this result to
qp
as if it came from aStatement
could lead to confusion, as theLong
elements would be printed as update counts rather than row numbers.- Parameters:
rs
- a ResultSet- Returns:
- a Stream as described above
- Throws:
Exception
-
q
public static Stream<Object> q(ResultSetMetaData rsmd) throws Exception
Produces aStream
with an element for each column of aResultSet
.This is another convenience method for use chiefly in driving a
state machine
to check per-column values or metadata for aResultSet
. It is, in fact, nothing other thanIntStream.rangeClosed(1, rsmd.getColumnCount()).boxed()
but typed asStream<Object>
.As with
q(ResultSet)
, the column number supplied here conveys no actual column data or metadata. The lambdas representing the machine states should close over theResultSetMetaData
or correspondingResultSet
object, or both, and use the column number from this stream to index them.- Parameters:
rsmd
- a ResultSetMetaData object- Returns:
- a Stream as described above
- Throws:
Exception
-
q
public static Stream<Object> q(ParameterMetaData pmd) throws Exception
Produces aStream
with an element for each parameter of aPreparedStatement
.This is another convenience method for use chiefly in driving a
state machine
to check per-parameter metadata. It is, in fact, nothing other thanIntStream.rangeClosed(1, rsmd.getParameterCount()).boxed()
but typed asStream<Object>
.As with
q(ResultSet)
, the column number supplied here conveys no actual parameter metadata. The lambdas representing the machine states should close over theParameterMetaData
object and use the parameter number from this stream to index it.- Parameters:
pmd
- a ParameterMetaData object- Returns:
- a Stream as described above
- Throws:
Exception
-
qp
public static void qp(Connection c, String sql) throws Exception
Executes some arbitrary SQL and passes the result stream toqp(Stream)
for printing to standard output.- Throws:
Exception
-
qp
public static void qp(Statement s, Callable<Boolean> work) throws Exception
Invokes someexecute
method on aStatement
and passes the result stream toqp(Stream)
for printing to standard output.This is how, for example, to prepare, then print the results of, a
PreparedStatement
:PreparedStatement ps = conn.prepareStatement("select foo(?,?)"); ps.setInt(1, 42); ps.setString(2, "surprise!"); qp(ps, ps::execute);
TheStatement
will be closed.- Throws:
Exception
-
examplesNeedSaxon
public static boolean examplesNeedSaxon() throws Exception
Returns true if the examples jar includes theorg.postgresql.pljava.example.saxon.S9
class (meaning the appropriate Saxon jar must be installed and on the classpath first before the examples jar can be deployed, unlesscheck_function_bodies
isoff
to skip dependency checking).- Throws:
Exception
-
installExamples
public static Stream<Object> installExamples(Connection c, boolean deploy) throws Exception
Installs the examples jar, under the nameexamples
.The jar is specified by a
file:
URI and the path is the one where this installer installed (or would have installed) it.- Returns:
- a result stream from executing the statement
- Throws:
Exception
-
installExamplesAndPath
public static Stream<Object> installExamplesAndPath(Connection c, boolean deploy) throws Exception
Installs the examples jar, under the nameexamples
, and appends it to the class path for schemapublic
.The return of a concatenated result stream from two consecutive statements might be likely to fail in cases where the first statement has any appreciable data to return, but the drivers seem to handle it at least in this case where each statement just returns one row / one column of
void
. And it is convenient.- Returns:
- a combined result stream from executing the statements
- Throws:
Exception
-
installSaxon
public static Stream<Object> installSaxon(Connection c, String repo, String version) throws Exception
Installs a Saxon jar under the namesaxon
, given the path to a local Maven repo and the needed version of Saxon, assuming the jar has been downloaded there already.- Returns:
- a result stream from executing the statement
- Throws:
Exception
-
installSaxonAndPath
public static Stream<Object> installSaxonAndPath(Connection c, String repo, String version) throws Exception
Installs a Saxon jar under the namesaxon
, and appends it to the class path for schemapublic
.- Returns:
- a combined result stream from executing the statements
- Throws:
Exception
-
installSaxonAndExamplesAndPath
public static Stream<Object> installSaxonAndExamplesAndPath(Connection c, String repo, String version, boolean deploy) throws Exception
A four-fer: installs Saxon, adds it to the class path, then installs the examples jar, and updates the classpath to include both.- Parameters:
repo
- the base directory of a local Maven repository into which the Saxon jar has been downloadedversion
- the needed version of Saxondeploy
- whether to run the example jar's deployment code- Returns:
- a combined result stream from executing the statements
- Throws:
Exception
-
flattenDiagnostics
public static Stream<Object> flattenDiagnostics(Object oneResult)
A flat-mapping function to expand anySQLException
orSQLWarning
instance in a result stream into the stream of possibly multiple linked diagnostics and causes in the encounter order of theSQLException
iterator.Any other object is returned in a singleton stream.
To flatten just the chain of
SQLWarning
orSQLException
but with each of those retaining its own list ofcause
s, seesemiFlattenDiagnostics
.
-
semiFlattenDiagnostics
public static Stream<Object> semiFlattenDiagnostics(Object oneResult)
A flat-mapping function to expand anySQLException
orSQLWarning
instance in a result stream into the stream of possibly multiple linked diagnostics in the order produced bygetNextException
orgetNextWarning
.Unlike
flattenDiagnostics
, this method does not descend into chains of causes; those may be retrieved in the usual way from the throwables returned on this stream.Any other object is returned in a singleton stream.
-
qp
public static void qp(Stream<Object> s) throws Exception
Prints streamed results of aStatement
in (somewhat) readable fashion.Uses
writeXml
ofWebRowSet
, which is very verbose, but about the easiest way to readably dump aResultSet
in just a couple lines of code.The supplied stream is flattened (see
semiFlattenDiagnostics
) so that any chainedSQLException
s orSQLWarning
s are printed in sequence.- Throws:
Exception
-
qp
public static void qp(Stream<Object> s, Function<Object,Stream<Object>> flattener) throws Exception
Prints streamed results of aStatement
in (somewhat) readable fashion, with a choice of flattener for diagnostics.For flattener, see
flattenDiagnostics
orsemiFlattenDiagnostics
.- Throws:
Exception
-
qp
public static void qp(Object o) throws Exception
Overload ofqp
for direct application to any oneObject
obtained from a result stream.Simply applies the specialized treatment appropriate to the class of the object.
- Throws:
Exception
-
peek
public static void peek(Object o)
Prints an object in the manner ofqp
, but in a way suitable for use inStream.peek
.If o is a
ResultSet
, only its metadata will be printed; its position will not be disturbed and it will not be closed. This method throws no checked exceptions, as theStream
API requires; any that is caught will be printed as if byqp
.
-
qp
public static void qp(ResultSet rs) throws Exception
Overload ofqp
for direct application to aResultSet
.Sometimes one has a
ResultSet
that didn't come from executing a query, such as from a JDBC metadata method. This prints it the same wayqp
on a query result would. TheResultSet
is not closed (but will have been read through the last row).A result set with no columns of type other than
void
will be printed in an abbreviated form, showing its number of rows and columns as reported byvoidResultSetDims
.- Throws:
Exception
-
qp
public static void qp(ParameterMetaData md) throws Exception
Overload ofqp
for examiningParameterMetaData
.Continuing in the spirit of getting something reasonably usable without a lot of code, this fakes up a
ResultSetMetaData
with the same values present in theParameterMetaData
(and nothing for the ones that aren't, like names), and then usesWebRowSet.writeXml
as if dumping a result set.For getting a quick idea what the parameters are, it's good enough.
- Throws:
Exception
-
qp
public static void qp(ResultSetMetaData md) throws Exception
Overload ofqp
for examiningResultSetMetaData
.This makes an empty
WebRowSet
with the copied metadata, and dumps it withwriteXml
. Owing to a few missing setters on Java'sRowSetMetaDataImpl
, a fewResultSetMetaData
attributes will not have been copied; they'll be wrong (unless the real values happen to match the defaults). That could be fixed by extending that class, but that would require yet another extra class file added to the installer jar.- Throws:
Exception
-
qp
public static void qp(Throwable t)
Prints aThrowable
retrieved from a result stream, with special handling forSQLException
andSQLWarning
.In keeping with the XMLish vibe established by
qp
for other items in a result stream, this will render aThrowable
as anerror
,warning
, orinfo
element (PostgreSQL's finer distinctions of severity are not exposed by every JDBC driver's API.)An element will have a
message
attribute if it has a message. It will have acode
attribute containing the SQLState, if it is an instance ofSQLException
, unless it is rendered as aninfo
element and the state is00000
. An instance ofSQLWarning
will be rendered as awarning
unless its class (two leftmost code positions) is00
, in which case it will beinfo
. Anything else is anerror
.
-
classify
public static String[] classify(Throwable t)
Returns an array of threeString
s, element, sqlState, and message, as would be printed byqp(Throwable)
.The first string will be: (1) if the throwable is an
SQLWarning
, "info" if its class (leftmost two positions of SQLState) is 00, otherwise "warning"; (2) for any other throwable, "error". These are constant strings and therefore interned.The second string will be null if the throwable is outside the
SQLException
hierarchy, or if the first string is "info" and the SQLState is exactly 00000; otherwise it will be the SQLState.The third string will be as returned by
getMessage
, and may be null if the throwable was not constructed with a message.If an
SQLWarning
is of the PGJDBC driver'sPSQLWarning
class and the backend's severity tag is available, it will be used to determine the first string, in place of the "starts with 00" rule. A tag of "WARNING" (or null) produces "warning", while any other tag produces "info".
-
voidResultSetDims
public static int[] voidResultSetDims(Object o, boolean peek) throws Exception
Determines whether an object is aResultSet
with no columns of any type other thanvoid
, to allow abbreviated output of result sets produced by the common case of queries that callvoid
functions.Returns null if o is not a
ResultSet
, or if its columns are not all ofvoid
type. Otherwise, returns a two-element integer array giving the rows (index 0 in the array) and columns (index 1) of the result set.If this method returns non-null, the result set is left positioned on its last row.
- Parameters:
o
- Object to checkpeek
- whether to avoid moving the row cursor. If true, and all of the columns are indeed void, the result array will have the column count at index 1 and -1 at index 0.- Returns:
- null or a two-element int[], as described above
- Throws:
Exception
-
voidResultSetDims
public static int[] voidResultSetDims(Object o) throws Exception
Equivalent tovoidResultSetDims(o,false)
;- Throws:
Exception
-
isVoidResultSet
public static boolean isVoidResultSet(Object o, int rows, int columns) throws Exception
A predicate testing that an object is aResultSet
that has only columns ofvoid
type, and the expected number of rows and columns.The expected result of a query that calls one
void
-typed, non-set-returning function could be checked withisVoidResultSet(rs, 1, 1)
.- Throws:
Exception
-
stateMachine
public static boolean stateMachine(String name, Consumer<String> reporter, Stream<Object> input, InvocationHandler... states) throws Exception
Executes a state machine specified in the form of a list of lambdas representing its states, to verify that a result stream is as expected.Treats the list of lambdas as a set of consecutively-numbered states (the first in the list is state number 1, and is the initial state). At each step of the machine, the current state is applied to the current input object, and may return an
Integer
or aBoolean
.If an integer, its absolute value selects the next state. A positive integer consumes the current input item, so the next state will be applied to the next item of input. A negative integer transitions to the selected next state without consuming the current input item, so it will be examined again in the newly selected state.
If boolean,
false
indicates that the machine cannot proceed; the supplied reporter will be passed an explanatory string and this method returns false. A state that returnstrue
indicates the machine has reached an accepting state.No item of input is allowed to be null; null is reserved to be the end-of-input symbol. If a state returns
true
(accept) when applied to null at the end of input, the machine has matched and this method returns true. A state may also return a negative integer in this case, to shift to another state while looking at the end of input. A positive integer (attempting to consume the end of input), or a false, return will cause an explanatory message to the reporter and a false return from this method.A state may return
true
(accept) when looking at a non-null input item, but the input will be checked to confirm it has no more elements. Otherwise, the machine has tried to accept before matching all the input, and this method will return false.To avoid defining a new functional interface, each state is represented by
InvocationHandler
, an existing functional interface with a versatile argument list and permissivethrows
clause. Each state must be represented as a lambda with three parameters (the convention(o,p,q)
is suggested), of which only the first is normally used. If Java ever completes the transition to_
as an unused-parameter marker, the suggested convention will be(o,_,_)
, unless the third (q) is also needed for special purposes (more below).As the input item passed to each state is typed
Object
, and as null can only represent the end of input, it may be common for a state to both cast an input to an expected type and confirm it is not null. Theas
method combines those operations. If its argument either is null or cannot be cast to the wanted type,as
will throw a specific instance ofClassCastException
, which will be treated, when caught bystateMachine
, just as if the state had returnedfalse
.The third parameter to an
InvocationHandler
is anObject
array, and is here used to pass additional information that may at times be of use in a state. The first element of the array holds the boxed form of the current (1-based) state number. As a state must indicate the next state by returning an absolute state number, having the state's own number available opens the possibility of reusable presupplied state implementations that do not depend on their absolute position.- Parameters:
name
- A name for this state machine, used only in exception messages if it fails to match all the inputreporter
- a Consumer to accept a diagnostic string if the machine fails to match, defaulting if null toSystem.err::println
input
- A Stream of input items, of which none may be nullstates
- Lambdas representing states of the machine- Returns:
- true if an accepting state was reached coinciding with the end of input
- Throws:
Exception
- Anything that could be thrown during evaluation of the input stream or any state
-
as
public static <T> T as(Class<T> clazz, Object o)
Casts o to class clazz, testing it also for null.This is meant as a shorthand in implementing states for
stateMachine
. If o either is null or is not castable to the desired type, a distinguished instance ofClassCastException
will be thrown, which is treated specially if caught bystateMachine
while evaluating a state.
-
forWindowsCRuntime
public static ProcessBuilder forWindowsCRuntime(ProcessBuilder pb)
Adjusts the command arguments of aProcessBuilder
so that they will be recovered correctly on Windows by a target C/C++ program using the argument parsing algorithm of the usual C run-time code, when it is known that the command will not be handled first bycmd
.This transformation must account for the way the C runtime will ultimately parse the parameters apart, and also for the behavior of Java's runtime in assembling the command line that the invoked process will receive.
- Parameters:
pb
- a ProcessBuilder whose command has been set to an executable that parses parameters using the C runtime rules, and arguments as they should result from parsing.- Returns:
- The same ProcessBuilder, with the argument list rewritten as necessary to produce the original list as a result of Windows C runtime parsing,
- Throws:
IllegalArgumentException
- if the ProcessBuilder does not have at least the first command element (the executable to run)UnsupportedOperationException
- if the arguments passed, or system properties in effect, produce a case this transformation cannot handle
-
asPgCtlInvocation
public static ProcessBuilder asPgCtlInvocation(ProcessBuilder pb)
Adjusts the command arguments of aProcessBuilder
that would directly invokepostgres
to start a server, so that it will instead startpostgres
viapg_ctl
.pg_ctl
constructs a command line forcmd.exe
(on Windows) or/bin/sh
(elsewhere), which in turn will launchpostgres
. The waypg_ctl
handles options (-o
) requires this transformation to be platform-aware and quote them correctly forsh
orcmd
as appropriate.The result of this transformation still has to be received intact by
pg_ctl
itself, which requires (on Windows) a subsequent application offorWindowsCRuntime
as well.- Parameters:
pb
- a ProcessBuilder whose command has been set to an executable path forpostgres
, with only-D
and-c
options.- Returns:
- The same ProcessBuilder, with the argument list rewritten to
invoke
pg_ctl start
with the same-D
and any other options supplied by-o
. - Throws:
IllegalArgumentException
- if the ProcessBuilder does not have at least the first command element (the executable to run)UnsupportedOperationException
- if the arguments passed produce a case this transformation cannot handle
-
-