I like making the lives of my future self and collaborators easier by using COMMENT ON to add comments on database objects. People can then see them when they're exploring the schema with \d+ and \df+ and so on.
However, some objects can accept comments, but psql won't display them where I would expect developers to typically go to learn about an object. For example, I can do COMMENT ON POLICY ... to add comments to an RLS policy, but they don't show up on \d+ or \dp+ for the table, which are the commands I'd normally use to inspect RLS policies.
What comments can I use and reasonably expect psql to show in an easily-accessible place?
COMMENT ON COLUMN is visible in \d+ for the relation.
COMMENT ON FUNCTION is visible in \df+ for the function. Since functions are stored as text, you can also include code comments in functions, and they will be visible to someone reading the function too.
COMMENT ON SCHEMA is visible in \dn+
COMMENT ON ROLE is visible in \dg+
COMMENT ON TYPE is visible in \dT (unlike the other examples, you don't need the +)
COMMENT ON TABLE or VIEW or MATERIALIZED VIEW etc. are visible in the listing of objects you get when you run \d+ with no arguments. They don't seem to be in \d+ for the object itself.
COMMENT ON CONSTRAINT is visible in \dd for the constraint name, although there's ~no other reason to look at \dd, so I don't think this is worth much.
As mentioned in the question, COMMENT ON POLICY doesn't appear to be visible anywhere (or maybe it's in \dd, but if so I don't know how to find it).
There's obviously many more of these, but these are the notes I've made so far. Feel free to edit in more.
Related
The docs recommend setting pg_temp as the last entry in search_path.
Why not leave it out of the list altogether? Would this accomplish the same?
The explanation is right in the documentation you reference:
Particularly important in this regard is the temporary-table schema, which is searched first by default, and is normally writable by anyone.
So if you don't put pg_temp on the search_path explicitly, it gets implicitly put first on the path. Than means that any temporary table (or view) that a user created manually before calling the SECURITY DEFINER function will be taken if the function uses that table name without an explicit schema qualification. So you could make the function read or write your table instead of the one it meant to use.
It is clear why that is a security problem, right?
This QA entry shows how to get OID code from catalog header.
It might be the simplest way to get OID numbers. Anyway the header file itself is explicitly separated from client-side header, so it seems it implies not to be used on client side.
Is it safe to use these server-side constants on client side? It's predictable that it will make some legacy issue. Older version of server may lack specific OID code. So I ask excluding this case. I mean, can I assume *once define OID code for fundamental types to be same eternally on future versions*?
Update
I meant only for fundamental types. Such as TEXTOID, INT8OID or TIMESTAMPOID. No custom, composite, user-defined or any other non-fundamental stuffs.
Currently, this is the best I could find. I would go with hardcoding OIDs.
Cited from Merlin Moncure's mention from the mailing list entry.
built in type oids are defined in pg_type.h: cat
src/include/catalog/pg_type.h | grep OID | grep define
built in type oids don't change. you can pretty much copy/pasto the
output of above into an app...just watch out for some types that may
not be in older versions.
user defined type oids (tables, views, composite types, enums, and
domains) have an oid generated when it is created. since that oid can
change via ddl so you should look it up by name at appropriate times.
Is it safe to use these server-side constants on client side? (...) I mean, can I assume once define OID code to be same eternally on future versions?
I honestly doubt it's not safe. The oids will likely be different depending on the Postgres version that was initially installed when new types etc are introduced. Older installs that get upgraded may or may not have the same oids as the same on fresh installs.
For illustration purposes, picture yourself creating an admin user with ID 1 in an app when it gets installed, and hard-coding everything in C by defining ADMIN_USER as that ID. Your customers then add new users, etc. In a subsequent release, you add a quasi-admin user with ID 2 and proceed tohard-code everything around that too. Customers upgrade... and, well, it blows up in your face because on their end, the quasi-admin user can have any ID...
When you use hard-coded oids in Postgres, the same kind of thing may happen. In one version, the built-in types are created in a certain order; in the next, they may be created in another because e.g. Postgres adds a shiny new enum or int4range type. And this doesn't begin to touch the topic of what may potentially occur during upgrades. (Admittedly, dumping and reloading data should yield sane things here, but I wouldn't take the chance myself.)
In PostgreSQL, how can I prevent anyone (including superusers) from dropping some specific table?
EDIT: Whoa, did we have some misunderstanding here. Let's say there is a big, shared QA database. Sometimes people run destructive things like hibernate-generated schema on it by mistake, and I'm looking for ways to prevent such mistakes.
anyone (including superusers) from dropping some specific table?
Trust your peers.
You can do that by writing some C code that attaches to ProcessUtility_hook. If you have never done that sort of thing, it won't be exactly trivial, but it's possible.
Another option might be looking into sepgsql, but I don't have any experience with that.
A superuser is precisely that. If you don't want them to be able to drop things, don't make them a superuser.
There's no need to let users run as superusers pretty much ever. Certainly not automated tools like schema migrations.
Your applications should connect as users with the minimum required user rights. They should not own the tables that they operate on, so they can't make schema changes to them or drop them.
When you want to make schema changes, run the application with a user that does have ownership of the tables of interest, but is not a superuser. The table owner can drop and modify tables, but only the tables it owns.
If you really, truly need to do something beyond the standard permissions model you will need to write a ProcessUtility_hook. See this related answer for a few details on that. Even then a superuser might be able to get around it by loading an extension that skips your hook, you'll just slow them down a bit.
Don't run an application as a superuser in production. Ever.
See the PostgreSQL documentation on permissions for more guidance on using the permissions model.
I don't think you can do that. You could perhaps have super super users who are going to manage the dropping of everything first. OR have backups constantly, so the higher member of the hierarchy will always have the possibility of retrieving the table.
I don't know what the real original intention of this question is... but a lot of people seem to have hypothetical answers like trusting your peers or using least permissions models appropriately. Personally, this misses the point altogether and instead answers with something everyone probably knew already, which isn't particularly helpful.
So let me attempt a question + answer of my own: How do you put in safety locks to prevent yourself or others from accidentally doing something you shouldn't? If you think that this "should never happen" then I think your imagination is too narrow. Or perhaps you are more perfect than me (and possibly a lot of other people).
For the rest of us, here is a solution that works for me. It is just a little lock that is put wherever you want it to - using event triggers. Obviously, this would be implemented by a super-user of some sort. But the point of it is that it has no bearing on permissions because it is error-based not permission based.
Obviously, you shouldn't implement this sort of thing if production behavior is dependent on it. It only makes sense to use in situations where it makes sense to use. Don't use it to replace what should be solved using permissions and don't use it to undermine your team. Use common sense - individual results may vary.
CREATE SCHEMA testst;
CREATE OR REPLACE FUNCTION manual_override_required() RETURNS event_trigger AS
$$
DECLARE
obj record;
BEGIN
FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
LOOP
RAISE INFO 'object_oid: %, object_type: %', obj.objid, obj.object_type;
RAISE info '%', obj.object_name;
IF obj.object_type = 'schema' and obj.object_name = 'testst' THEN
RAISE EXCEPTION 'You have attempted to DROP something which has been hyper-locked and requires manual override to proceed.';
END IF;
END LOOP;
END
$$
LANGUAGE plpgsql
;
DROP EVENT TRIGGER IF EXISTS lock_schema;
CREATE EVENT TRIGGER lock_schema
ON sql_drop
EXECUTE FUNCTION manual_override_required();
DROP SCHEMA testst;
-- produces error: "ERROR: You have attempted to DROP something which has been admin-locked and requires manual override to proceed."
-- To override the admin-lock (you have the permission to do this, it just requires two turns of a key and positive confirmation):
ALTER EVENT TRIGGER lock_schema DISABLE;
DROP SCHEMA testst;
-- now it works!
An example of how I use this is in automation workflows. I have to switch between dev and prod environments a dozen times a day and I can (i.e. have) easily lost track of which is which despite the giant flags and banners I've put up to remind myself. Dropping certain schemas should be a rare and special event in Prod (thus the benefit of a active-confirmation approach) whereas in dev I rebuild them all the time. If I maintain the same permission structures in Dev as in Prod (which I do) then I wouldn't be able to solve this.
I recently found myself using some rather lengthy names for the tables and views involved in a development piece, which got me wondering whether it's possible to create client/database/server level aliases for objects.
Say for example I have a view named dbo.vAlphaBetaGammaDelta . Is there a way (with or without Intellisense) to create a reference to it named dbo.vABGD ?
If not, would there be any downfalls to creating a view of a view or single table aside from maintenance necessary if/when the table schema changes?
I should note that these aliases/views would not be intended for use in other objects, but for alleviation and prevention of carpal tunnel during day-to-day troubleshooting and delving xD
SQL Server allows for the creation of synonyms. That seems to be what you are looking for: http://msdn.microsoft.com/en-us/library/ms177544.aspx
However, as #MitchWheat mentioned. this seems to be going in the wrong direction. There are a few quite good SSMS plugins available that provide auto completion of long object names (e.g. SQL Prompt). Incidentally those products have trouble with synonyms...
There are many cases where you would like to have synonyms.
Let me state just one for start:
You have a well defined hypothetical name of a table: GlobalStatisticalRecord. Hundreds of lines of code and objects (keys, indexes, etc.) in SQL and elsewhere are referring to this table name.
After 5 years of usage, the abbreviation GSR was accustomed not only among the technical people, but also among the business users. So, to stress again, GSR is now even more recognizable than GlobalStatisticalRecord. However, for the new people that come into the technical team, it is good to keep the name GlobalStatisticalRecord as a table name, since it nicely describes what is the table all about. Now, when writing a quick adhoc query - and that may not be from your tool of choice with all the Intellisense features you are accustom to - then these aliases are really saving your time (and "life" at 2am in the morning when you are frantically trying to diagnose a production problem).
Please, if you never faced a case when you would need this, just don't assume that there is none.
I stressed the adhoc adjective, since I agree that in permanent queries (stored procedures, etc.), for the reasons you pointed out, it is advisable to use the full table names.
I'm currently doing some maintenance on an application and I've come across a big issue regarding the qualified name in tsql. I wondering if someone could clear my confusion up for me.
From my understanding you want to use USE [DatabaseName] to declare which database you are using. I notice if u "rename" the databse it automatically updates these references in your code.
However, the developer who originally wrote this code used the USE [DatabaseName]. Then in later statements he wrote: SELECT * FROM [DatabaseName].[dbo].[Table]. Well this obviously breaks if I change the Database's name. From what i've read you want to qualify names only to the owner such as: [dbo].[TableName] so it knows where to look which increases performance.
Is there a reason he included the Database name in each statement?
From what i've read you want to qualify names only to the owner such as: [dbo].[TableName] so it knows where to look which increases performance.
Not that I'm aware of, rather it looks like someone is lazy.
I always use the three name format (unless accessing a linked server instance, then it's four).
The benefit is that the correct table from the correct database & schema will be used without concern for an errant USE [appropriate database] statement. As long as the object exists, and the permissions are valid based on the need, you can recreate a stored procedure, function, view, etc in other databases without needing to address the USE [appropriate database] statement each time.
But I'm working with data spread over numerous databases on the same instance. I wouldn't have necessarily designed it that way, but it wouldn't change that I use three (or four) part qualified name format.