FAST PostgreSQL wrote:
> We are trying to develop the updateable cursors functionality into 
> Postgresql. I have given below details of the design and also issues we are 
> facing.  Looking forward to the advice on how to proceed with these issues.
> 
> Rgds,
> Arul Shaji

Would this be something that you would hope to submit for 8.3?

Joshua D. Drake


> 
> 
> 
> 
>  
> 1. Introduction
> --------------
> This is a combined proposal and design document for adding updatable 
> (insensitive) cursor capability to the PostgreSQL database. 
> There have already been a couple of previous proposals since 2003 for 
> implementing this feature so there appears to be community interest in doing 
> so. This will enable the following constructs to be processed:
> 
> 
> UPDATE <table_name> SET value_list WHERE CURRENT OF <cursor_name>
> DELETE FROM <table_name> WHERE CURRENT OF <cursor_name>
> 
> This has the effect of users being able to update or delete specific rows of 
> a table, as defined by the row currently fetched into the cursor.
> 
> 
> 2. Overall Conceptual Design
> -----------------------------
> The design is considered from the viewpoint of progression of a command 
> through the various stages of processing, from changes to the file ‘gram.y’ 
> to implement the actual grammar changes, through to changes in the Executor 
> portion of the database architecture.
> 
> 2.1 Changes to the Grammar
> ------------------------------
> The following changes will be done to the PostgreSQL grammar:
> 
> UPDATE statement has the option ‘WHERE CURRENT OF <cursor_name>’ added
> DELETE statement has the option ‘WHERE CURRENT OF <cursor_name>’ added
> 
> The cursor_name data is held in the UpdateStmt and DeleteStmt structures and 
> contains just the name of the cursor.
> 
> The pl/pgsql grammar changes in the same manner.
> 
> The word CURRENT will be added to the ScanKeywords array in keywords.c.
> 
> 
> 2.2 Changes to Affected Data Structures
> ------------------------------------------
> The following data structures are affected by this change: 
> 
> Portal structure, QueryDesc structure, the UpdateStmt and DeleteStmt 
> structures
> 
> The Portal will contain a list of structures of relation ids and tuple ids 
> relating to the tuple held in the QueryDesc structure. There will be one 
> entry in the relation and tuple id list for each entry in the relation-list 
> of the statement below: 
> 
> DECLARE <cursor_name> [WITH HOLD] SELECT FOR UPDATE OF <relation-list> 
> 
> The QueryDesc structure will contain the relation id and the tuple id 
> relating to the tuple obtained via the FETCH command so that it can be 
> propagated back to the Portal for storage in the list described above.
> 
> The UpdateStmt and DeleteStmt structures have the cursor name added so that 
> the information is available for use in obtaining the portal structure 
> related to the cursor previously opened via the DECLARE CURSOR request.
> 
> 
> 2.3 Changes to the SQL Parser
> ------------------------------------
> At present, although the FOR UPDATE clause of the DECLARE CURSOR command has 
> been present in the grammar, it causes an error message later in the 
> processing since cursors are currently not updatable. This now needs to 
> change. The ‘FOR UPDATE’ clause has to be valid, but not the ‘FOR SHARE’ 
> clause. 
> 
> The relation names that follow the ‘FOR UPDATE’ clause will be added to the 
> rtable in the Query structure and identified by means of the rowMarks array. 
> In the case of an updatable cursor the FOR SHARE option is not allowed 
> therefore all entries in the rtable that are identified by the rowMarks array 
> must relate to tables that are FOR UPDATE.
> 
> In the UPDATE or DELETE statements the ‘WHERE CURRENT OF <cursor_name>’ 
> clause results in the cursor name being placed in the UpdateStmt or 
> DeleteStmt structure. During the processing of the functions - 
> transformDeleteStmt() and transformUpdateStmt() - the cursor name is used to 
> obtain a pointer to the related Portal structure and the tuple affected by 
> the current UPDATE or DELETE statement is extracted from the Portal, where it 
> has been placed as the result of a previous FETCH request. At this point all 
> the information for the UPDATE or DELETE statement is available so the 
> statements can be transformed into standard UPDATE or DELETE statements and 
> sent for re-write/planning/execution as usual.
> 
> 2.4 Changes to the Optimizer
> ------------------------------
> There is a need to add a TidScan node to planning UPDATE / DELETE statements 
> where the statements are ‘UPDATE / DELETE at position’. This is to enable the 
> tuple ids of the tuples in the tables relating to the query to be obtained. 
> There will need to be a new mechanism to achieve this, as at present, a Tid 
> scan is done only if there is a standard WHERE condition on update or delete 
> statements to provide Tid qualifier data.
> 
> 
> 2.5 Changes to the Executor
> -------------------------------
> There are various options that have been considered for this part of the 
> enhancement. These are described in the sections below.
> 
> We would like to hear opinions on which option is the best way to go or if 
> none of these is acceptable, any alternate ideas ?
> 
> Option 1  MVCC Via Continuous Searching of Database
> 
> The Executor is to be changed in the following ways:
> 1)    When the FETCH statement is executed the id of the resulting tuple is 
> extracted and passed back to the Portal structure to be saved to indicate the 
> cursor is currently positioned on a tuple.
> 2)    When the UPDATE or DELETE request is executed the tuple id previously 
> FETCHed is held in the QueryDesc structure so that it can be compared with 
> the tuple ids returned from the TidScan node processed prior to the actual 
> UPDATE / DELETE node in the plan. This enables a decision to be made as to 
> whether the tuple held in the cursor is visible to the UPDATE / DELETE 
> request according to the rules of concurrency. The result is that, at the 
> cost of repeatedly searching the database at each UPDATE / DELETE command, 
> the hash table is no longer required.
> This approach has the advantage that there is no hash table held in memory or 
> on disk so it will not be memory intensive but will be processing intensive. 
> 
> This is a good ‘one-off’ solution to the problem and, taken in isolation is 
> probably the best approach. However, if one considers the method(s) used in 
> other areas of PostgreSQL, it is probably not the best solution. This option 
> will probably not be used further.
> 
> Option 2  MVCC via New Snapshot
> 
> The executor can be changed by adding a new kind of snapshot that is 
> specifically used for identifying if a given tuple, retrieved from the 
> database during an update or delete statement should be visible during the 
> current transaction.
> 
> This approach requires a new kind of snapshot (this idea was used by Gavin 
> for a previous updatable cursor patch but objections were raised.)
> 
> Option 3  MVCC Via Hash Table in Memory
>  
> The executor can be changed by saving into a hash table and comparing each 
> tuple in the cursor with that set to check if the tuple should be visible.
> This approach has the advantage that it will be quick. It has the 
> disadvantage that, since the hash table will contain all the tuples of the 
> table being checked that it may use all local memory for a large table.
> 
> Option 4  MVCC Via Hash Table on Disk
>  
> When the UPDATE or DELETE request is executed the first time the Tid scan 
> database retrieval will be done first. At this time the tuple id of each row 
> in the table to be updated by the request will be available in the executor. 
> These tuple ids need to be stored in a hash table that is stored to disk, as, 
> if the table is large there could be a huge number of tuple ids. This data is 
> then available for comparison with the individual tuple to be updated or 
> deleted to check if it should be processed. The hash table will exist for the 
> duration of the transaction, from BEGIN to END (or ABORT). 
> 
> The hash table is then used to identify if the tuple should be visible during 
> the current transaction. If the tuple should be visible then the update or 
> delete proceeds as usual.
> 
> This approach has the advantage that it will use little memory but will be 
> relatively slow as the data has to be accessed from disk. 
> 
> Option 5 Store Tuple Id in Snapshot.
> 
> The Snapshot structure can be changed to include the tuple id. This enables 
> the current state of the tuple to be identified with respect to the current 
> transaction.
> The tuple id, as identified in the cursor at the point where the 
> DELETE/UPDATE statement is being processed, can use the snapshot to identify 
> if the tuple should be visible in the context of the current transaction.
> 
> 
> 2.6 Changes to the Catalog 
> ----------------------------
> The Catalog needs to reflect changes introduced by the updatable cursor 
> implementation. A boolean attribute ‘is_for_update’ is to be added to the 
> pg_cursors implementation. It will define that the cursor is for update 
> (value is FALSE) or for share (value is TRUE, the default value).
>  
> 
> 3 Design Assumptions
> ----------------------------
> The following design assumptions are made:
> 
> As PostgreSQL8.2 does not support the SENSITIVE cursor option the tuples 
> contained in a cursor can never be updated so these tuples will always appear 
> in their ‘original’ form as at the start of the transaction. This is in 
> breach of the SQL2003 Standard as described in 5WD-02-Foundation-2003-09.pdf, 
> p 810. The standard requires the updatable cursor to be declared as sensitive.
> 
> With respect to nested transactions – In PostgreSQL nested transactions are 
> implemented by defining ‘save points’ via the keyword SAVEPOINT. A ‘ROLLBACK 
> TO SAVEPOINT’ rolls back the database contents to the last savepoint in this 
> transaction or the begin statement, whichever is closer.
> 
> It is assumed that the FETCH statement is used to return only a single row 
> into the cursor with each command when the cursor is updatable.
> 
> According to the SQL2003 Standard Update and Delete statements may contain 
> only a single base table.
> 
> The DECLARE CURSOR statement is supposed to use column level locking, but 
> PostgreSQL supports only row level locking. The result of this is that the 
> column list that the standard requires ‘DECLARE <cursor_name> SELECT … FOR 
> UPDATE OF column-list’ becomes a relation (table) list.
> 
> This is an email from Fujitsu Australia Software Technology Pty Ltd, ABN 27 
> 003 693 481. It is confidential to the ordinary user of the email address to 
> which it was addressed and may contain copyright and/or legally privileged 
> information. No one else may read, print, store, copy or forward all or any 
> of it or its attachments. If you receive this email in error, please return 
> to sender. Thank you.
> 
> If you do not wish to receive commercial email messages from Fujitsu 
> Australia Software Technology Pty Ltd, please email [EMAIL PROTECTED]
> 
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
>        choose an index scan if your joining column's datatypes do not
>        match
> 


-- 

      === The PostgreSQL Company: Command Prompt, Inc. ===
Sales/Support: +1.503.667.4564 || 24x7/Emergency: +1.800.492.2240
Providing the most comprehensive  PostgreSQL solutions since 1997
             http://www.commandprompt.com/

Donate to the PostgreSQL Project: http://www.postgresql.org/about/donate
PostgreSQL Replication: http://www.commandprompt.com/products/


---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to