postgresql pendant of SqlDependency / notify on query result changes - sql

I have a postgresql database and I want to send E-Mail notifications if the results of specific queries have changed.
For SQL-Server there is a C# class called SqlDependency which allows me to do this in a very easy way. I'ts possible to say: "Hey notify me if SELECT * FROM a WHERE d changes".
But I couldn't find any solution for postgresql. I've often seen NOTIFY, but as far as I understand it, it's not as powerful as this SQL-Server mechanism, because I have to build lot of triggers.
My additional problem is, that the queries can potentially be very complex :/
So: Has postgresql any mechanism for this scenario?

I recently also went into that problem,
I'm currently evaluating the listen/notify functionality of psql.
It seems the suiting thing, but you have to implement your db-observer your self.
How to fire NOTIFICATION event in front end when table data gets changed

Related

Fire SQL Trigger only when a particular user update the row

There is a trigger in postgres that gets called whenever a particular table is updated.
It is used to send updates to another API.
Is there a way one can control the firing of this trigger?
Sometimes when I update the table I don't want the trigger to be fired. How do I do this?
Is there a silence trigger sql syntax?
If not
Can I fire triggers when a row is updated by PG user X and when PG user Y updates the table no trigger should be fired?
In recent Postgres versions, there is a when clause that you can use to conditionally fire the trigger. You could use it like:
... when (old.* is distinct from new.*) ...
I'm not 100% this one will work (can't test atm):
... when (current_user = 'foo') ...
(If not, try placing it in an if block in your plpgsql.)
http://www.postgresql.org/docs/current/static/sql-createtrigger.html
(There also is the [before|after] update of [col_name] syntax, but I tend to find it less useful because it'll fire even if the column's value remains the same.)
Adding this extra note, seeing that #CraigRinger's answer highlights what you're up to...
Trying to set up master-master replication between Salesforce and Postgres using conditional triggers is, I think, a pipe dream. Just forget it... There's going to be a lot more to it than that: you'll need to lock data as appropriate on both ends (which won't necessarily be feasible in a reasonable way), manage the resulting deadlocks (which might not automatically get detected), and deal with conflicting data.
Your odds of successfully pulling this off with a tiny team is about about zero -- especially if your Postgres skills are at the level where investing time in reading the manual would answer your own questions. You can safely bet that someone much more competent at Salesforce or some major SQL shop (e.g. like the one Craig works for) considered the same, and either miserably failed or ruled it out.
Moreover, I'd stress that implementing efficient, synchronous, multi-master replication is not a solved problem. You read that right: not solved. Just a few years ago, doing it at all wasn't well solved enough to make it in the Postgres core. So you've no prior art that works well to base your work on and iterate upon.
This seems to be the same problem as this post a few minutes ago, approaching it from a different direction.
If so, while you can indeed do as Denis suggests, don't attempt to reinvent this wheel. Use an established tool like Slony-I or Bucardo if you are attempting two-way (multi-master) replication. You also need to understand the major limitations involved in multi-master when dealing with conflicting updates.
In general, there are a few ways to control trigger firing:
Let the trigger fire, then put logic in the PL/PgSQL trigger body to cause it to take no action if a certain condition is met. This is often the only option when the rules are complex.
As Denis points out, use a trigger WHEN clause to conditionally fire the trigger
Use session_replication_role to control the firing of all triggers
Directly enable/disable triggers.
In particular, if your application shares a single SQL-level user ID for all database access and does its own user management above the SQL level, and you want to control trigger firing on a per-user basis, the only way to do it will be with in-trigger logic. You might find this prior answer about getting user IDs within triggers useful:
Passing user id to PostgreSQL triggers

How to make VB.NET application work as Multi-user?

I am developing a VB.Net application. That application might be working on a LAN. MS Access as a back end will be used. I have developed many single user applications, but don't know of multi user , LAN, manage DB etc. How do I make the program as Multi user on LAN. Data will be accessed at the same time. How to manage such things.
Please give me some help and Guidance.
Thanks
Your VB application does not care how many people run it.
Your database, with MS Access, has some serious issues with multiple users. Get away from it if you can. SQL Server has a free version called SQL Express. If you only plan on 2 people, you might be OK with Access for a while but be prepared to support it more.
That was all the easy stuff, now you have to think about how you are going to handle multiple users trying to access and update the same data (concurrency).
Imagine this, you are a user looking at employee record 1 and so is someone else. You change the birthday and save. The the other user changes thier suppervisor and saves. How do you know something changed? What do you do if something changed? These are questions I cannot answer for you, you must decide based on your situation.
There are 2 main types of concurrency, optimistic and pessimistic. See this link for a great explaination and discussion on them: optimistic-vs-pessimistic-locking
You can look at this on a table-by-table basis.
If a table is never updated, you dont have to worry about concurrency
If a table is rarely updated, like a table of states, you can decide if it is worth the extra effort to add concurrency.
Everything else, pretty much should have some type of concurrency.
Now, the million dollar question, how?
You will find as many ways to handle concurrency as you will find colors in the rainbow. Here are some of the ones I like:
Simple number that you increment with each save. Small and easy.
DateTime stamp - As long as you dont expect to ever have 2 people save the same record during the same second, this is easy. (I personally dont like it by it's self)
User Name - Pretty simple gives a little bit of an audit by knowing who last inserted/edited the record but doesn't handle an issue I have seen to often. Imagine the same senerio as above but you had 2 instances of record 1. Now you change the data again, maybe supervisor, and when you save, you overwrite the changes from your first save with those of the second save.
Guid - VB can create a guid, SQL Server can create a guid and so can Access. It is nice an unique and most important, you can create it on the client so you dont have to requery the database after you save the record to get a refreshed record.
Combination of these. I like 2 and 3 myself. Gives a mini audit and is unique to the user.
If you use a DataAdapter, by default, MS will assume concurrency checking means to compare EVERY field to make sure it did not change. This works, but is completely un-scaleable and should not be done.
All of this depends on the size of your application and how you see it being used. Definately do some more research before you settle on a decision.
There are a number of solutions here.
If I may suggest a drastic alternative, have you considered pairing the client running on the user's computer with a server component (through a web service)? A simpler alternative would be for the client to talk directly to a SQL Server (or other database) instance through the network?*
*I'm not a fan of having client side apps talk directly to the database. It will mean maintenance headaches in the future, but I
included it to give you options
.
I found this random example via Google so YMMV.

How to elegantly poll/pull information from a database?

I am currently beginning a new personal project. I have a database that keeps track of users as they log in to my webpage. It shows when they log on and log off. It uses SQL Server 2008.
What I would like to do is, whenever a user logs in, a scrolling bar along the top of my webpage alerts me to this. I have created a dashboard to keep track of a lot of my website statistics and this is something I think would be really cool. Useless, ultimately - but it would produce a "heheh" from me every so often, so why not ?
Now, I have never attempted to build something like this (which is the reason I am building it!) so I am torn between a few different design approaches. It seems like I could poll the database server repeatedly using http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldependency.aspx, just writing a query to find the set of currently logged in users and display any additions to that pool. If this is the right path to go down, then I would appreciate some more in-depth commentary on how this could be used.
From a high level perspective it seems like, rather than repeatedly polling the database, it would be more efficient to have the DB push the message out to my web server when there is a change. Would this be possible? If so, how ?
For the sake of argument, and to give this discussion a bit more specificity, let's assume our SQL Server tables are structured as follows (but feel free to make any improvements or changes as you see fit!):
Users {
ID Primary Key
Username(Varchar 100)
Password
}
LogInOrOutLogs {
SessionID Primary Key
UserID (Foreign Key)
TimeLoggedIn (DateTime)
TimeLoggedOut (DateTime)
CurrentlyLoggedIn(Bool)
}
Open to all technologies, all database structures, all design ideas. Go crazy! Only requirements : You have a DB of users which updates as they log in and out. Display the information on a web server as meaningfully, elegantly and simply as you can.
Thanks a lot, looking forward to reading peoples solutions for this problem.
Do you have look at Hibernate ? This is an elegante object layer over SQL database.
Then you can push triggers on your database to push the event. When you have a event to your data you send it to your web application via long query (it is an ajax query with very very very long timeout, the query is re-send after a event is receive).
A crazy design should also use a two way messaging system, one for message incoming into the DB one for other outputing from DB.
If you really like crazy thing you could thing of cache using a DB4O database (a cache for your SQL Server) embedded into a servicemix - redhatfuse. There easy way with servicemix because of the predeployed broker(activemq) and fuse with it's nice fabric system.

Log user activity - which is better

I am using Action Filter Attributes for loging user activity on certain action which has SQL database interaction. Similarly I can log the activity in the SQL tables using triggers on tables during each activity on the tables. I would like to know which of the above two methods is a best practice ( perfomance wise )
I think that the actionfilter is certainly the cleanest and best practice appraoch since it is in the application layer. Part of the benefit of being there is its managed code and if something breaks you can easily locate the problem. There is also the benefit that all your code is in one spot too.
Database triggers are a big no no in many companies since they have a habit of causing infinite loop well an unknowing programmer creates some logic that steps on the trigger over and over again causing the database to fail. Some companies do allow triggers but very well documented and very lightly used. Hope this helps.
Performance of logging depends greatly on the system architecture. If you have 3 load balanced web servers hitting one main database, triggers would have to handle all the load while Action Filters would split the load in three. In that scenario, Action Filters would be better.
In terms of best practices, I wouldn't use either of those approaches. I would set up Transactional Replication to another SQL server. This approach would run without impacting performance at all. The transaction log is already being generated and replication would just spin up a separate process that's reading that log.

NHibernate query interception

Is there any way to get the query text - i.e. plain SQL - of an NHibernate query from a DetachedCriteria object (or any NHibernate object, I just want to be pointed in the right direction) BEFORE it is sent to my server? If so, can I prevent it from executing?
I don't know if there is an easy way of doing this. There might be a listener you can use to display the sql and then abort the execution. I've never used one for this purpose.
If you simply want to debug your queries and don't want to hit your database then write some tests using an in-memory database. In my opinion this is a much better strategy.
You can observe the queries that are being generated by tailing your log files or using NHProf.