How to save multiple functions as each files(*.sql) in Postgresql? - postgresql-8.2

I'm using PostgreSQL version 8.2 and trying to save all functions/views source code as each files on a local.
But it seems to be impossible to extract each function's code to each files.
example:
I'd like to save source files like below:
function a1, a2, a3 -----> a1.sql, a2.sql, a3.sql
How can I do it?

This is not a complete solution, but should get you started in the right direction.
Assuming you are using psql for this, you can save the source code of a single function by spooling the output of select procsrc from pg_proc where proname = '...' to a file, e.g.:
\t
\a
\o a1.sql
select prosrc from pg_proc where proname = 'a1';
\o
The \t \a configures psql to only output the content of the column prosrc. The \o a1.sql redirects the query result to a file.
As you want one file per function, you need to run this for each function. You can either do this manually or generate a script which does this by running a SQL statement:
\t \a \o extract_source.sql
select concat('\t '\a \o ', proname, '.sql', chr(10),
'select prosrc from pg_proc where proname = ''', proname, ''';',
chr(10),
'\o', chr(10))
from pg_proc;
\o
\i extract_source.sql
The query generates the first script for each procedure, then runs the generated script.
Not tested, you probably need to tweak that to meet your needs.
Note that the content of prosrc is NOT the complete function.
It lacks the return type, the arguments and the language definition. In more modern Postgres versions you could use pg_get_functiondef() for that, but with 8.2 you will need to put all those things together using the columns from pg_proc. The most complicated part is getting the function arguments right (because Postgres 8.2 also lacks, pg_get_function_arguments())
Without the arguments, it will be something like:
select concat('create or replace function ',
proname, '(......) ',
'returns ', rt.typname,
' as $$ ',
prosrc,
'$$ language ', l.lanname, ';')
from pg_proc p
join pg_language l on l.oid = p.prolang
join pg_type rt on rt.oid = p.prorettype
where proname = 'a1';
instead of "just" select prosrc .... from pg_proc.

Related

How to make a list of quoted strings from the string values of a column in postgresql?

select my_col from test;
Out:
my_col
x
y
z
How can I change the output of the three rows into an output of a list of three quoted strings in postgresql, so that it looks like:
Out:
'x','y','z'
If I run string_agg(my_val, ''','''), I get
Out:
x','y','z
If I run quote_literal() on top of this output, I get:
Out:
'x'',''y'',''z'
I need this list of quoted strings as an input for the argument of a function (stored procedure). The function works by passing the 'x','y','z' as the argument by hand. Therefore, it is all just about the missing leading and trailing quote.
Side remark, not for the question: it would then get read into the function as variadic _v text[] so that I can check for its values in the function with where t.v = any(_v).
You seem to want:
select string_agg('''' || my_val || '''', ',') my_val_agg
from test
That is: concatenate the quotes around the values before aggregating them - then all that is left is to add the , separator in between.
'''' is there to produce a single quote. We can also use the POSIX syntax in Postgres:
select string_agg(E'\'' || my_val || E'\'', ',') my_val_agg
from test

Replace all CRLF with \r\n using REXEXP_REPLACE

I have a process that needs to strip all CRLF from SQL statements and store them with literal characters \r\n and stores this in a .json file. Later, this process is reversed when the .json file is inserted back into the database.
I am using ORACLE 19c.
The original (abbreviated) SQL might look like this:
SELECT SPRIDEN_ID, SPRIDEN_LAST_NAME, SPRIDEN_FIRST_NAME
FROM sztdhof
LEFT JOIN SPRIDEN
ON sztdhof.SZTDHOF_PIDM = spriden.SPRIDEN_PIDM
RIGHT JOIN SSBSECT
ON sztdhof_CRN = SSBSECT_CRN
WHERE spriden_change_ind IS NULL
The resulting string should look like this:
SELECT SPRIDEN_ID, SPRIDEN_LAST_NAME, SPRIDEN_FIRST_NAME\r\nFROM sztdhof\r\nLEFT JOIN SPRIDEN\r\nON sztdhof.SZTDHOF_PIDM = spriden.SPRIDEN_PIDM\r\nRIGHT JOIN SSBSECT\r\nON sztdhof_CRN = SSBSECT_CRN \r\nWHERE spriden_change_ind IS NULL
I have tried numerous ways to get ORACLE REGEXP_REPLACE to recognize the carriage return and line feed together. None seem to work.
To start, I read the value from the db into a variable v_text. Then I attempt the conversion and placing the result into a second variable v_outtext. If I use two separate statements, each works separately. And I can live with that method, but I would like this to work as a single statement. (Note. I have also tried the REPLACE function with similar results.)
This code...
SELECT REPLACE (v_text, chr(13) , '\r\n')
INTO v_outtext
FROM dual;
produces...
SELECT SPRIDEN_ID, SPRIDEN_LAST_NAME, SPRIDEN_FIRST_NAME\r\n
FROM sztdhof\r\n
LEFT JOIN SPRIDEN\r\n
ON sztdhof.SZTDHOF_PIDM = spriden.SPRIDEN_PIDM\r\n
RIGHT JOIN SSBSECT\r\n
ON sztdhof_CRN = SSBSECT_CRN \r\n
WHERE spriden_change_ind IS NULL\r\n
SELECT REGEXP_REPLACE(v_text, chr(10) , '\r\n') --is similar to above, except the \r\n are at the front of each line.
SELECT REGEXP_REPLACE(v_text, (chr(13)chr(10) , '\r\n') gives me an error, missing right parenthesis.
SELECT REGEXP_REPLACE (v_text, '(\r\n)', '\r\n') replaces r with \r and n with \n, but only the first instance.
I have tried numerous iterations. None solve the problem. Any thoughts would be welcome.
You need to concatenate the two characters you want to replace, not just put them in parentheses (even if you supplied both):
SELECT REPLACE(v_text, chr(13) || chr(10) , '\r\n')
INTO v_outtext
FROM dual;
If if it's already in a PL/SQL variable you don't need to to the context switch to select from dual; you can simplify to:
v_outtext := REPLACE(v_text, chr(13) || chr(10) , '\r\n');
but it sounds like you can use the first method to read the value from the database into v_outtext in one go, without the intermediate v_text.
db<>fiddle

String regex on sql

I have "X1lNtWp4_e" type of string on SQL code.
I wanna convert like X1lNtWp4_e without the ( " ).
My DB Engine codes like MySQL I think.
I'm using http://chartio.com so i'm not sure which db engine.
Chartio is just a front end but assuming your DB is MySQL simply use:
Use the TRIM function with the BOTH argument:
SELECT TRIM(BOTH '"' FROM '"X1lNtWp4_e"')
FROM yourtable
Use the REPLACE function if the middle content contains " also and you want them removed:
SELECT REPLACE('"X1lNtWp4_e"', '"', '')
FROM yourtable

How to escape bind variable (from Markdown) in Query?

I created a markdown that will render a dropdown with values like these:
\server01\mis-home$\chq-blah\Scripts\Foo B Files.abc
\server02\mis-home$\chq-blah\Scripts\Bar G Files.abc
C:\Workspace\My_App\Resources\Export_Process.abc
When one of these values selected, subsequent query fails.
Markdown
Script = {!`MY AWESOME SELECT STATEMENT`}
Query
SELECT *
FROM myDB
WHERE scriptName =: Script
I suspect that's because of illegal characters such as space, backslash or underscore or dot. How do I tell Slamdata to escape those?
In order to reference a variable in SQL2, you must use the syntax :var_name, with no space between : and var_name.
If you change your query to the following:
SELECT * FROM myDB WHERE scriptName = :Script
Then it should function correctly.
SQL2 is more thoroughly documented on the Quasar Analytics website.

simple parameter substitution in regexp_matches postgreSQL function

I have a table with a structure like this...
the_geom data
geom1 data1+3000||data2+1000||data3+222
geom2 data1+500||data2+900||data3+22232
I want to create a function that returns the records by user request.
Example: for data2, retrieve geom1,1000 and geom2, 900
Till now I created this function (see below) which works quite good but I am facing a parameter substitution problem... (you can see I am not able to substitute 'data2' for $1 in... BUT yes I can use $1 later
regexp_matches(t::text, E'(data2[\+])([0-9]+)'::text)::text)[2]::integer
MY FUNCTION
create or replace function get_counts(taxa varchar(100))
returns setof record
as $$
SELECT t2.counter,t2.the_geom
FROM (
SELECT (regexp_matches(t.data::text, E'(data2[\+])([0-9]+)'::text)::text)[2]::integer as counter,the_geom
from (select the_geom,data from simple_inpn2 where data ~ $1::text) as t
) t2
$$
language sql;
SELECT get_counts('data2') will work **but we should be able to make this substitution**:
regexp_matches(t::text, E'($1... instead of E'(data2....
I think its more a syntaxis issue, as the function execution gives no error, just interprets $1 as a string and gives no result.
thanks in advance,
A E'$1' is a string literal (using the escape string syntax) containing a dollar sign followed by a one. An unquoted $1 is the first parameter to your function. So this:
regexp_matches(t, E'($1[\+])([0-9]+)'))[2]::integer
as you've found, won't interpolate the $1 with the function's first parameter.
The regex is just a string, a string with an internal structure but still just a string. If you know that $1 will be a normal word then you could say:
regexp_matches(t, E'(' || $1 || E'[\+])([0-9]+)'))[2]::integer
to paste your strings together into a suitable regex. However, it is better to be a little paranoid, sooner or later someone is going to call your function with a string like 'ha ha (' so you should be prepared for it. The easiest way that I can think of to add an arbitrary string to a regex is to escape all the non-word characters:
-- Don't forget to escape the escaped escapes! Hence all the backslashes.
str := regexp_replace($1, E'(\\W)', E'\\\\\\1', 'g');
and then paste str into the regex as above:
regexp_matches(t, E'(' || str || E'[\+])([0-9]+)'))[2]::integer
or better, build the regex outside the regexp_matches to cut down on the nested parentheses:
re := E'(' || str || E'[\+])([0-9]+)';
-- ...
select regexp_matches(t, re)[2]::integer ...
PostgreSQL doesn't have Perl's \Q...\E and the (?q) metasyntax applies until the end of the regex so I can't think of any better way to paste an arbitrary string into the middle of a regex as a non-regex literal value than to escape everything and let PostgreSQL sort it out.
Using this technique, we can do things like:
=> do $$
declare
m text[];
s text;
r text;
begin
s = E'''{ha)?';
r = regexp_replace(s, E'(\\W)', E'\\\\\\1', 'g');
r = '(ha' || r || ')';
raise notice '%', r;
select regexp_matches(E'ha''{ha)?', r) into m;
raise notice '%', m[1];
end$$;
and get the expected
NOTICE: ha'{ha)?
output. But if you leave out the regexp_replace escaping step, you'll just get an
invalid regular expression: parentheses () not balanced
error.
As an aside, I don't think you need all that casting so I removed it. The regexes and escaping are noisy enough, there's no need to throw a bunch of colons into the mix. Also, I don't know what your standard_conforming_strings is set to or which version of PostgreSQL you're using so I've gone with E'' strings everywhere. You'll also want to switch your procedure to PL/pgSQL (language plpgsql) to make the escaping easier.