(Postgis) Permission based on Geometry - gis

Is it possible to grant permissions to users valid only for a certain geometry on PostGIS?
For example I have a database of many tables for whole USA and I want to limit a user to view and update a specific state. Is there a way -without adding state column- to achieve this? If not which setup (ie. middleware) do you suggest?

You can use Row Level Security:
ALTER TABLE mygeoms ENABLE ROW LEVEL SECURITY;
ALTER TABLE mygeoms FORCE ROW LEVEL SECURITY;
CREATE POLICY only_in_area ON mygeoms
FOR ALL TO some_role
USING (to_contains(GEOMETRY 'SRID=4326;POLYGON((...)), geom_col);
Then some_role can only be able to see and modify rows that satisfy the condition.
A GiST index on the geometry column can speed up processing.

Related

What is MySQL View for?

MySQL Documentation explains how to create a view. However it doesn't explain why should I make a MySQL View in the first place.
Thus, my question is, what is MySQL View? What is it for? At what circumstances should I make or not make one?
Quoting the documentation
The view definition is “frozen” at creation time and is not affected by subsequent changes to the definitions of the underlying tables.
I don't see how creating a view would be beneficial, so please, enlighten me.
View the data without storing the data into the object.
Restrict the view of a table i.e. can hide some of columns in the tables.
Join two or more tables and show it as one object to user.
Restrict the access of a table so that nobody can insert the rows into the table.
Where I work, we use the views as big painful querys that we need many times, we decided to create views for them instead of doing a manual query and when we need to access the information
SELECT * FROM view WHERE (anything)

Database Architecture for logging

This is something that has bothered me for a long time and i still have been unable to find an answer.
I have a huge system with alot of different features. What is common for this system is of course that my users can
create, update, read & delete
different parts of my system.
For simple reasons lets say i have an application that has the following features:
Document administration
Video administration
User administration
Salery administration
(Please do note i took these at random just to prove a point that all of these would have their own separate tables and does not necessarily be connected).
Now i wish to create some sort of logging system. So that when ever someone either create,update or delete an entity it will be recorded.
Now as far as i can see i can do this two ways.
1.
Create a logging table for each of the 4 features that is in my system. However with this method i am required to create a logging table for each new feature i add to the system. i would also have to combine data from X number of tables if i wish to create a log which potentially could be a huge task!
2.
i could create something like the following:
However once again i would have to add a col for each new feature i will add.
So my question is what is the best way for creating logging database architecture
Or is there an easier way?
Instead of one target_xx for each feature, you could do it this way:
target_id | target_type
1 video
4 document
5 user
2 user
or even better. A table with target types and insert only the respective id's on target_type
Something like this:
if you want to capture for each table creation and update date, i would just use the default and the update event from mysql. You can define the fields like this for a table:
ALTER TABLE table
ADD COLUMN CreateDate Datetime DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN LastModifiedDate Datetime ON UPDATE CURRENT_TIMESTAMP;
You can add these 2 fields in all tables. If you want to use one central table for logging (which might be more difficult to manage, because you always need to create joins, maybe also worse performance), then I would work with triggers.

Redshift Usage - 1 row by 400 columns per user or (20-400) rows by 4 columns per user

We are building an analytics engine which has to store attribute preference score for each user. We are expecting 400 attributes and they may change(at what frequency is not known as yet). We are planning to store this in Redshift.
My qs is:
Should we store as 1 row per user with 400 cols(1 column for each attribute)
or should we go for a table structure like
(uid, attribute id, attribute value, preference score) which will be (20-400)rows by 3 columns
Which kind of storage would lead to a better performance in Redshift.
Should be really consider NoSQL for this?
Note:
1. This is a backend for real time application with increasing number of users.
2. For processing, the above table has to be read with entire information of all attibutes for one user i.e indirectly create a 1*400 matrix at runtime.
Please help me which desgin would be ideal for such a use case. Thank you
You can go for tables like given in this example and then use bitwise functions
http://docs.aws.amazon.com/redshift/latest/dg/r_bitwise_examples.html
Bitwise functions are here
For your problem, I would suggest a two table design. Its more pain in the beginning but will help in future.
First table would be a key value kind of first table, which would store all the base data and would be kind of future proof, where you can add/remove more attributes, but this table will continue working.
And a N(400 in your case) column 2nd table. This second table you can build using the first table. For the second table, you can start with a bare minimum set of columns .. lets say only 50 out of those 400. So that querying this table would be really fast. And the structure of this table can be refreshed periodically to match with the current reporting requirements. Also you will always have the base table in case you need to backfill any data.

How can I allow users sql access to a table limited to certain rows?

I'm building an stock exchange simulation game. I have a table called 'Market_data' and in the game players simulate being in particular dates and are allowed to use SQL queries to retrieve the historical data and plan their course of action. My difficulty is that I need to limit the rows they can access based on the current date they are playing on so they cant see rows with a date greater than the current date.
Eg: An user is running the game and is currently in the year 2010, if he does a simple select like "SELECT * FROM market_data" I don't want him to see rows with Date > 'x-x-2010'
The only soution that I know of is to parse the user's SQL and add WHERE clauses to remove newer dates but it seems time consuming and prone to errors and I wasn't sure whether there were better alternatives. Any ideas on how to do this right will be thanked.
Solution is SQL Views, Views are used for several different reasons:
*1.*To hide data complexity. Instead of forcing your users to learn the T-SQL JOIN syntax you might wish to provide a view that runs a commonly requested SQL statement.
*2.*To protect the data. If you have a table containing sensitive data in certain columns, you might wish to hide those columns from certain groups of users. For instance, customer names, addresses and their social security numbers might all be stored in the same table; however, for lower level employees like shipping clerks, you can create a view that only displays customer name and address. You can grant permissions to a view without allowing users to query the underlying tables. There are a couple of ways you might want to secure your data:
a.Create a view to allow reading of only certain columns from a table. A common example of this would be the salary column in the employee table. You might not want all personnel to be able to read manager's or each other's salary. This is referred to as partitioning a table vertically and is accomplished by specifying only the appropriate columns in the CREATE VIEW statement.
b.Create a view to allow reading only certain rows from a table. For instance, you might have a view for department managers. This way, each manager can provide raises only to the employees of his or her department. This is referred to as horizontal partitioning and is accomplished by providing a WHERE clause in the SELECT statement that creates a view.
*3.*Enforcing some simple business rules. For example, if you wish to generate a list of customers that need to receive the fall catalog, you can create a view of customers that have previously bought your shirts during the fall.
*4.*Data exports with BCP. If you are using BCP to export your SQL Server data into text files, you can format the data through views since BCP's formatting ability is quite limited.
*5.*Customizing data. If you wish to display some computed values or column names formatted differently than the base table columns, you can do so by creating views.
reference taken from http://sqlserverpedia.com.
1)You can use mysql proxy http://dev.mysql.com/downloads/mysql-proxy/ with custom rules restricting access.
2)You can use stored procedures/functions
3)You can use views
The basic way would be :
-> Prevent that user (or group) from accessing the base table.
-> Define a view on top of that table that shows only the rows these users are supposed to see.
-> Give those users SELECT permission on the view.
-> And you can also use SQL Encryption,Decryption and Hashing concept.
Encryption & Decryption examples can be found here:
http://msdn.microsoft.com/en-us/library/ms179331.aspx
Hashing example can be found here:
http://msdn.microsoft.com/en-us/library/ms174415.aspx

What's the best way to save trivial user states (e.g. dismissed welcome msg) in database?

Should I use (create) a column for every new state? Or one field with a bunch of comma separated states (alternatively a json obj)? Any suggestions welcome.
UPDATE
First let me day thanks for the answers. I just want to clear up, what options I see:
Put a column for every state in the user row (initial plan) / Can get messy with lots of states (in the future)
Put one column with json/xml data in the user row / Easy to maintain (no db change required), but doesn't feel right
Have a dedicated states table (thx lhiles)/ Sounds cool, how would this table look like?
I'm looking for pros/cons of the different implementations. Again: Thanks!
Create a column for each state. This is proper data normalization.
With a column for each state you can retrieve as few or as many states as needed for the current operation.
All of the states returned will be contained in a single row with each column named. This makes referencing each state value very easy.
It allows you to easily add constraints to each state as needed. (State X can only contain '1' or '2'.)
It allows you to easily query states across users. (How many users have set a state value to 'X'?)
My preferred method is to create a dedicated table for user settings. Each state/setting corresponds to a column within that table. As your project grows additional columns can be added without cluttering your apps core data.
Another route, if you feel that there will be too many settings to devote 1 setting per column, would be to store the settings as XML (or json as you mentioned) data within SQL. This would allow you to derive any type of state format you wanted, however, it puts more work on the programmer to parse, validate, and persist those settings.
You can save state using an ENUM if the states are mutually exclusive; e.g. person is male or female.
Or using a SET if states can co-exist; e.g. person is a member of (AA and CA and SOsA*)
A sample table using both:
CREATE TABLE test.table1(
test_enum ENUM('male', 'female') DEFAULT 'male',
test_set SET('AA', 'CA', 'SOsA') DEFAULT NULL
)
ENGINE = INNODB;
If you're using an ENUM I personally would recommend you set an explicit default value other than null, because most of the time a choice must be made.
Link: http://dev.mysql.com/doc/refman/5.1/en/constraint-enum.html
* (stackoverflow sufferers anonymous)
I really wouldn't do this with a column per setting, as most of the other people are suggesting. I'd do a setting per row because this doesn't require schema changes (including upgrade scripts) every time you add a setting.
Better yet, write some reflection code to run on app startup that'll look at the entries on an enum and automatically create a record in the database (with some default value that you specify in a custom attribute on each enum value).
I recently did something like I'm indicating above. Now to add a new setting, I add an entry to an enum and that's it. New settings take about 10 seconds.
I may put my code up on CodeProject, it has has made development easy.