I need to make sure that an available PostgreSQL version is not lower than required one. The version string could be requested as follows:
SELECT VERSION();
It returns me something like:
PostgreSQL 9.5.4, compiled by Visual C++ build 1800, 64-bit
Theoretically I could parse this string, but I am not sure that future versions of PostgreSQL server will keep this word order.
Does PostgreSQL have some predictable version report possibly split in major and minor version number?
show server_version_num; --returns 90602::text
show server_version; --returns 9.6.2::text
https://blog.2ndquadrant.com/finding-postgresql-version/ says:
You can use that more easily within an SQL query like this
SELECT current_setting('server_version_num');
You can query the PostreSql View pg_settings which is present at pg_catalog
select * from pg_settings where name like '%version%';
The query above will bring you two settings:
name other columns .....
server_version .....
server_version_num .....
For your specific case you will want the following configuration:
select name, setting, min_val, max_val
from pg_settings
where name = 'server_version_num';
name setting min_val max_val
--------------------------------------------------
server_version_num 90503 90503 90503
From here you can work with min_val and max_val
This query is equivalent to the answer provided by #ŁukaszKamiński with some more detail (if you select all columns.)
Related
My table:
CREATE TABLE public.software
(
software_name text COLLATE pg_catalog."default",
version text COLLATE pg_catalog."default",
)
In that table I store software and their versions which I use in some projects and I check whenever they updated by comparing their version. I need to store the version informations as string because some versions contains strings like "1.0.1-beta".
I still couldn't find the best way to compare the strings. I use following (simplified) query:
SELECT '1.2.3' < '1.2.4' -- true
SELECT '1.2.3a' < '1.2.4B'
When i run following query:
select '3.0.0' > '26752' -- true
select '1.2.3a' < '1.2.3A' -- true
select 'i dont know' >= '2' --true
But 3.0.0 is smaller than 26752. 1.2.3a is (maybe) false, if I use lower() function I can solve it. How about select '3.0.0' > '26752' or the last query?
In general, the best solution for that is to translate version numbers into something numerical.
The best I can offer you is an ICU collation for “natural comparison” (available from PostgreSQL v10 on):
CREATE COLLATION en_natural (
provider = icu,
locale = 'en-US-u-kn-true'
);
ALTER TABLE public.software
ALTER version TYPE text COLLATE en_natural;
That will make a best effort.
Of course, 1.0.1 will still be less than 1.0.1-beta3, as well as less than 1.0.1a, because there is no built-in knowledge that “beta” is less than an empty string, while other strings are not.
I installed semver extension, which works great! thanks #arun
I'm currently writing some installer script that fires SQL files against different database types depending on the system's configuration (the webapplication supports multiple database server like MySQL, MSSQL and PostgreSQL).
One of those types is PostgreSQL. I'm not fluent with it and I would like to know if it's possible to make a statement into a define/populate SQL file that makes an SQL query conditional to a specific PostgreSQL server version.
How to make an SQL statement conditionally in plain PGSQL so that it is only executed in version 9? The command is:
ALTER DATABASE dbname SET bytea_output='escape';
The version check is to compare the version with 9.
Postgres does have version() function, however there is no major_vesion(). Assuming that output string always includes version number as number(s).number(s).number(s) you could write your own wrapper as:
CREATE OR REPLACE FUNCTION major_version() RETURNS smallint
AS $BODY$
SELECT substring(version() from $$(\d+)\.\d+\.\d+$$)::smallint;
$BODY$ LANGUAGE SQL;
Example:
=> Select major_version();
major_version
---------------
9
(1 row)
However real issue here is that AFAIK you can't execute your commands conditionally in "pure" SQL and best what you can do is to write some stored function like this:
CREATE OR REPLACE FUNCTION conditionalInvoke() RETURNS void
AS $BODY$
BEGIN
IF major_version() = 9 THEN
ALTER DATABASE postgres SET bytea_output='escape';
END IF;
RETURN;
END;
$BODY$ LANGUAGE plpgsql;
I think that you should rather use some scripting language and generate appropriate SQL with it.
Or you could just use
select setting from pg_settings where name = 'server_version'
Or
select setting from pg_settings where name = 'server_version_num'
If you need major version only
select Substr(setting, 1, 1) from pg_settings where name = 'server_version_num'
or
select Substr(setting, 1, strpos(setting, '.')-1) from pg_settings where name = 'server_version'
if you want it to be compatible with two digit versions.
Maybe you could make things dependent on the output of
select version();
(probably you'll have to trim and substring that a bit)
BTW (some) DDL statements may not be issued from within functions; maybe you'll have to escape to shell-programming and here-documents.
Does Intersystems Cache database have a dummy table similar to Oracle's DUAL?
I want to do something similar to:
SELECT 1; -- mysql
-- or
SELECT 1 FROM DUAL; -- oracle
Older versions of Cache do not support this. You can create a dummy table yourself called DUAL or DUMMY. Newer versions of Cache (2009.1+) support select with no FROM clause.
Which is the fastest way to search within string in PostgreSQL (case insensivity):
SELECT col FROM table WHERE another_col ILIKE '%typed%'
or
SELECT col FROM table WHERE another_col ~* 'typed'
How can I turn on showing the time which query need to return results? Something like is on default in mySQL (I am thinking about CLI client).
Both queries are the same, PostgreSQL rewrites ILIKE to ~*. Check the results from EXPLAIN to see this behaviour.
I'm not sure about your question, but the psql-client can show you some timing of the query, using \timing.
Regarding the timing:
One solution is to use the switch for psql that Frank has already mentioned.
When you use EXPLAIN ANALZYE it also includes the total runtime of the query on the server.
I prefer this when comparing the runtime for different versions of a query as it removes the network from the equation.
In relation to my other question "What’s the best way to audit log DELETEs?". What's the PostgreSQL equivalent of CONTEXT_INFO?
I want to log deletes using a trigger, but since I'm not using the database user as my app's logical user, I cannot log the CURRENT_USER from the trigger code as the user who deleted the record. But for INSERT and UPDATE it is possible to log the record changes from trigger since you can just add a user field in the record, say inserted_by and last_updated_by, and use these fields to log to audit table.
http://www.postgres.cz/index.php/PostgreSQL_SQL_Tricks_II#Any_other_session_variables
PostgreSQL provides more variants, please, look to this site.
The accepted answer is outdated.
In recent versions of postgresql (since 9.3 or 9.4 I think), one can set / retrieve config variables are only alive for the current session [or transaction]. Documentation Reference
example of setting a session variable:
hal=# select set_config('myvar.foo', 'bar', false);
set_config
------------
bar
(1 row)
hal=# select current_setting('myvar.foo');
current_setting
-----------------
bar
(1 row)
It is possible to use the function current_setting as one would use other set returning functions.
example:
create table customers (id int);
insert into customers values (1), (2), (3), (4);
select c.*, s.*
from customers c
left join current_setting('myvar.foo') s
on c.id = length(s)