What does this select statement actually do? - postgresql

I'm reviewing log of executed PostgreSQL statements and stumble upon one statement I can't totally understand. Can somebody explain what PostgreSQL actually do when such query is executed? What is siq_query?
select *
from siq_query('', '21:1', '', '("my search string")', False, True, 'http://siqfindex:8080/storediq/findex')
I'm running PostgreSQL 9.2

siq_query(...) is a server-side function taking 7 input parameters (or more). It's not part of any standard Postgres distribution I know (certainly not mainline Postgres 9.2), so it has to be user-defined or part of some extension you installed. It does whatever is defined in the function. This can include basically anything your Postgres user is allowed to do. Unless it's a SECURITY DEFINER function, then it ca do whatever the owner of the function is allowed to do.
The way it is called (SELECT * FROM), only makes sense if it returns multiple rows and/or columns, most likely a set of rows, making it a "set-returning function", which can be used almost like a table in SQL queries.
Since the function name is not schema-qualified, it has to reside in a visible schema. See:
How does the search_path influence identifier resolution and the "current schema"
Long story short, you need to see the function definition to know what it does exactly. You can use psql (\df+ siq_query), pgAdmin (browse and select it to see its definition in the SQL pane) or any other client tool to look it up. Or query the system catalog pg_proc directly:
SELECT * FROM pg_proc WHERE proname = 'siq_query';
Pay special attention to the column prosrc, which holds the function body for some languages like plpgsql.
There might be multiple variants of that name, Postgres allows function overloading.

Related

Is there such a thing as a "PostgreSQL-SQL-to-OtherDB-SQL" converter in PHP, or at all?

I use PostgreSQL exclusively. I have no plans to ever change this. However, I recognize that other people are not me, and they instead use MySQL, MS SQL, IBM SQL, SQLite SQL, Oracle SQL and ManyOthers SQL. I'm aware that they have different names in reality.
My queries look like:
SELECT * FROM table WHERE id = $1;
UPDATE table SET col = $1 WHERE col = $2;
INSERT INTO table (a, b, c) VALUES ($1, $2, $3);
My database wrapper functions currently support only PostgreSQL, by internally calling the pg_* functions.
I wish to support "the other databases" too. This would involve (the trivial part) to make my wrapper functions able to interact with the other databases by using the PHP functions for those.
The difficult part is to reconstruct the PostgreSQL-flavor SQL queries from the application into something that works identically yet will be understood by the other SQL database in use, such as MySQL. This obviously involves highly advanced parsing, analysis and final creation of the final query string. For example, this PostgreSQL SQL query:
SELECT * FROM table WHERE col ILIKE $1 ORDER BY random() LIMIT 1;
... will be turned into WeirdSQL like this:
SELECT * FROM table WHERE col ISEQUALTOKINDA %1 ORDER BY rnd() LIMIT 1;
I don't require support from any other input SQL flavor than PostgreSQL, but the output must be "all the big SQL database vendors".
Has anyone even attempted this? Or is it something that is never gonna happen as free software but might exist as a commercial offering? It sounds like it would be a thing. It would be insanely useful, and "crazier" projects have been attempted.
jOOQ is a Java library that aims to hide differences between databases. It has its own SQL grammar which tries to be compatible with everything (but parameter markers must be the JDBC ?), and generates DB-specific SQL from that.
There is an online translator, which generates the following from your query for Oracle:
select *
from table
where lower(cast(col as varchar2(4000))) like lower(cast(:1 as varchar2(4000)))
order by DBMS_RANDOM.RANDOM
fetch next 1 rows only
ODBC uses its own syntax on top on the database's syntax. ODBC drivers are required to convert ODBC parameter markers (?) to whatever the database uses, and to translate escape sequences for certain elements that are likely to have a non-standard syntax in the DB (time/GUID/interval literals, LIKE escape character, outer joins, procedure calls, function calls).
However, most escape sequences are optional, and this does not help with other syntax differences, such as the LIMIT 1.
ODBC drivers provide a long list of information about SQL syntax details, but it is the application's job to construct queries that conform to those restrictions, and not all differences can be described by this list. In practice, most ODBC applications restrict themselves to a commonly supported subset of SQL.

Replacement of DBA_Source in Postgres to find DB objects

How can I know table (table_1) is being used in which all UDF?
Below query gives me table's details:
SELECT * FROM information_schema.tables;
Below Query gives UDF details:
select * FROM pg_proc;
But how can I know that table1 is used in which all UDF?
A string search in the prosrc column of pg_proc is the only way if you want to find dependencies between functions and tables.
Of course that is not very satisfying, because it would be rather difficult to say if – say – an occurrence of table_1 is a reference to the table or a variable name. Also, you cannot find the source of C functions in the catalog.
To get a reliable answer, you would need insight into the language in which the function is written, and here is the core of the problem: PostgreSQL does not have any insight into the language! PostgreSQL's fabled extensibility allows you to define new languages for functions, and only the language handler knows how to interpret the string that is the function body. That also holds for PL/pgSQL which is shipped with PostgreSQL.
That is also the reason why there are no pg_depend entries for objects used in functions.

Does wrapping a query in SELECT protect you completely in Postgres

Given a client library that can only execute one statement in a batch, if you run
query.exec_sql("SELECT * FROM (" + sql + ")")
Are there any vectors where sql can run anything but a SELECT ?
Are there any other ways to temporarily de-elevate a connection so it can only perform SELECT?
Note: It looks like SET ROLE solves this problem, but the the issue I have is that I am unable to create a role upfront in an easy way.
While you can put data-modifying statements in queries by embedding INSERT/UPDATE/DELETE statements in CTEs, they're only allowed at the top level, so that's not an issue.
You can, however, invoke a function, which could contain just about anything. Even if you ran this in a read-only transaction, a function could potentially elevate it to read-write.
But the solution is simple: If you don't want to allow the caller to do something, don't give them permission to do it. Create a user with only the GRANTs they need, and you can execute sql as-is.
Without the ability to define permissions, the closest you're going to get is probably a read-only transaction and/or an explicit rollback after the query, but there will still be holes you can't plug (e.g. you can't roll back a setval() call).
If the sql string came from a third party then it can be used to SQL injection. I'm not sure if that is what you are asking because it is too basic for a 56k points user to ask. Sorry if that is not the case. The string could be:
some_table; insert into user_table (user_id, admin_privilege) values (1, true);

Is it possible to get explain plan with bind variables in DB2?

With Oracle, the syntax is:
explain plan for
select * from users WHERE user_name = :user_name AND user_dob = :user_dob
Is it possible to do the same in DB2? The statement below does not seem to work.
explain plan with snapshot for
select * from users WHERE user_name = :user_name AND user_dob = :user_dob
Thank you.
The answer may depend on your DB2 version and platform, which you chose not to share with us for some reason. This works fine on DB2 for LUW (v10.1, but I'm sure it would work with v9.7 and up):
$ db2 "explain plan with snapshot for select * from syscat.schemata where schemaname = :blah"
DB20000I The SQL command completed successfully.
You may want to try replacing named parameter markers with questions marks.
Apparently, the answer is in the IBM website, but it is not easy to make sense of.
http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=%2Fcom.ibm.db2.udb.admin.doc%2Fdoc%2Fr0000952.htm
FOR explainable-sql-statement
Specifies the SQL statement to be explained. This statement can be any
valid CALL, Compound SQL (Dynamic), DELETE, INSERT, MERGE, SELECT,
SELECT INTO, UPDATE, VALUES, or VALUES INTO SQL statement. If the
EXPLAIN statement is embedded in a program, the
explainable-sql-statement can contain references to host variables
(these variables must be defined in the program). Similarly, if
EXPLAIN is being dynamically prepared, the explainable-sql-statement
can contain parameter markers.
But it does not tell you what "parameter markers" are, so you have to go and search for it.

PostgreSQL: How do I export a function definition to SQL

I have a function (stored procedure) defined in a database that I would like to edit.
I think one way of doing this is to dump the function definition to a SQL file, edit the SQL file, then replace the definition in the database with the edited version.
Is it possible to do this (dump the definition to a SQL file)?
What I have been doing in the past is to use psql to connect to the database, run /df+ function, copy the output to a text file, massage the text so it looks like a function declaration, but this is time consuming and I'm wondering if there is a sleeker way of doing it.
I am using PostgreSQL 9.1 if it matters.
EDIT:
I accepted Mike Buland's answer because he provided the correct answer in his comment, which was to run \ef function in psql.
This is actually listed in a previous question:
SELECT proname, prosrc
FROM pg_catalog.pg_namespace n
JOIN pg_catalog.pg_proc p
ON pronamespace = n.oid
WHERE nspname = 'public';
List stored functions that reference a table in PostgreSQL
You should be able to use this on the command line or with a client to read the current text of the proc and do anything you'd like with it :)
I hope that helps
You would also need the function arguments:
SELECT p.proname
, pg_catalog.pg_get_function_arguments(p.oid) as params
, p.prosrc
FROM pg_catalog.pg_proc p
WHERE oid = 'myschema.myfunc'::regproc;
Or, to make it unambiguous for functions with parameters:
WHERE oid = 'myschema.myfunc(text)'::regprocedure;
Or you can use pgAdmin to do what you describe a lot more comfortably. It displays the complete SQL script to recreate objects and has an option to copy that to the the edit window automatically. Edit and execute.
I think you need to take a step back and see the root issue here. Which is you're not using version control to version your files (database objects). There are plenty of free ones, Git and Mercurial to name a few. So use psql or the query Mike provided to dump the structure out and put them in version control. Going forward check out from version control and make edits there. You should be deploying code from this version control system to the database server. It is also useful to reconcile that the code you have in version control matches the code in the database in a automated and on a regular basis. In theory though if a strict process is in place code that isn't checked into source control should never make it to the database and you don't ever have to wonder if source control matches what the database has. However I don't trust that people with admin access won't abuse their privilege so I put steps in place to check this. If someone is found to be abusing their privileges that can be dealt with in other ways.