Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/db-api.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/db-api.xml,v
diff -u -r1.2 -r1.3
--- openacs-4/packages/acs-core-docs/www/xml/developers-guide/db-api.xml 24 Dec 2001 19:31:42 -0000 1.2
+++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/db-api.xml 2 Feb 2002 03:47:32 -0000 1.3
@@ -10,10 +10,10 @@
Overview
- One of ACS's great strengths is that code written for it is very close to
- the database. It is very easy to interact with the database from anywhere
- within ACS. Our goal is to develop a coherent API for database access which
- makes this even easier.
+ One of OpenACS's great strengths is that code written for it is
+ very close to the database. It is very easy to interact with the
+ database from anywhere within OpenACS. Our goal is to develop a
+ coherent API for database access which makes this even easier.
@@ -22,7 +22,7 @@
The Old Way
- Here's a typical block of code from an ACS 3.x dynamic page:
+ Here's a typical block of code from an OpenACS 3.x dynamic page:
@@ -153,15 +153,18 @@
- The new command db_transaction makes the scope of a
- transaction clear. db_transaction takes the code block
- argument and automatically runs it in the context of a transaction.
+ The new command db_transaction
+ makes the scope of a transaction
+ clear. db_transaction takes the
+ code block argument and automatically runs it in the context of a
+ transaction.
- The new command db_foreach writes our old while loop for us.
+ The new command db_foreach writes
+ our old while loop for us.
@@ -188,7 +191,6 @@
Bind Variables
-
Bind variables are placeholders for literal values in an SQL query
being sent to the server. Take the example query above: in the old
way, data was generally passed to Oracle directly, via Tcl string
@@ -501,7 +503,7 @@
Therefore, the Database Access API provides a database-independent way to
represent null (instead of the Oracle-specific idiom of the
- empty string): db_null.
+ empty string): db_null.
Use it instead of the empty string whenever you want to set a column value
explicitly to null, e.g.:
@@ -584,17 +586,15 @@
-
db_abort_transaction
-
-db_abort_transaction
+db_abort_transaction
Aborts all levels of a transaction. That is if this is called within
@@ -608,17 +608,17 @@
-
+
db_null
-
+
-db_null
+db_null
@@ -633,16 +633,16 @@
-
+
db_foreach
-
+
-db_foreach statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
+db_foreach statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ] \
code_block [ if_no_rows if_no_rows_block ]
@@ -684,16 +684,16 @@
-
+
db_1row
-
+
-db_1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
+db_1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ]
@@ -719,16 +719,16 @@
-
+
db_0or1row
-
+
-db_0or1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
+db_0or1row statement-name sql [ -bind bind_set_id | -bind bind_value_list ] \
[ -column_array array_name | -column_set set_name ]
@@ -744,11 +744,11 @@
- db_nextval
+ db_nextval
-db_nextval sequence-name
+db_nextval sequence-name
@@ -764,17 +764,17 @@
-
+
db_register_pooled_sequence
-
+
-db_register_pooled_sequence sequence-name pool-size
+db_register_pooled_sequence sequence-name pool-size
Registers the sequence sequence-name to be pooled, with a pool
@@ -786,11 +786,11 @@
- db_string
+ db_string
-db_string statement-name sql [ -default default ] [ -bind bind_set_id | -bind bind_value_list ]
+db_string statement-name sql [ -default default ] [ -bind bind_set_id | -bind bind_value_list ]
Returns the first column of the result of SQL query
@@ -808,11 +808,11 @@
- db_list
+ db_list
-db_list statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+db_list statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
Returns a Tcl list of the values in the first column of the result of SQL
@@ -827,11 +827,11 @@
- db_list_of_lists
+ db_list_of_lists
-db_list_of_lists statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+db_list_of_lists statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
Returns a Tcl list, each element of which is a list of all column values
@@ -844,11 +844,11 @@
- db_dml
+ db_dml
-db_dml statement-name sql \
+db_dml statement-name sql \
[ -bind bind_set_id | -bind bind_value_list ] \
[ -blobs blob_list | -clobs clob_list |
-blob_files blob_file_list | -clob_files clob_file_list ]
@@ -892,18 +892,18 @@
- db_write_clob,
- db_write_blob,
- db_blob_get_file
+ db_write_clob,
+ db_write_blob,
+ db_blob_get_file
-db_write_clob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+db_write_clob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
-db_write_blob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+db_write_blob statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
-db_blob_get_file statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
+db_blob_get_file statement-name sql [ -bind bind_set_id | -bind bind_value_list ]
Analagous to ns_ora write_clob/write_blob/blob_get_file.
@@ -914,10 +914,10 @@
- db_release_unused_handles
+ db_release_unused_handles
- db_release_unused_handles
+ db_release_unused_handles
Releases any allocated, unused database handles.
@@ -926,11 +926,11 @@
- db_transaction
+ db_transaction
-db_transaction code_block [ on_error { code_block } ]
+db_transaction code_block [ on_error { code_block } ]
Executes code_block transactionally. Nested
@@ -981,12 +981,12 @@
- db_resultrows
+ db_resultrows
-db_resultrows
+db_resultrows
Returns the number of rows affected or returned by the previous
@@ -997,10 +997,10 @@
- db_with_handle
+ db_with_handle
-db_with_handle var code_block
+db_with_handle var code_block
@@ -1037,20 +1037,20 @@
-
+
db_nullify_empty_string
-
+
-db_nullify_empty_string string
+db_nullify_empty_string string
For true SQL purists, we provide the convenience function
- db_nullify_empty_string, which returns
+ db_nullify_empty_string, which returns
[db_null] if its string argument is the empty string
and can be used to encapsulate another Oracle quirk:
@@ -1088,134 +1088,7 @@
- Implementation Design (work in progress)
-
- The ideas here are preliminary, so please send feedback to michael@arsdigita.com. There may well
- be a much simpler, superior design that I (Michael) am just missing right
- now. If so, please let me know!
-
-
- The basic idea is to translate the logical
- statement-name into an actual SQL statement, written in
- the appropriate SQL dialect for the RDBMS that is in use. The
- sql argument is essentially a convenience that enables
- the SQL for the "default dialect" to be written inline. For 3.4, we
- will probably use configuration parameters to tell the Database Access API
- what the default dialect is and what dialect is actually in use:
-
-
-
-[ns/server/server_name/acs]
-...
-DefaultSQLDialect=oracle8
-SQLDialect=postgres7
-
-
-
-
- (An alternative approach would be to use the ACS Package Manager, i.e.,
- install a "pseudo-package" with no actual code to indicate what
- RDBMS is installed. Then, the Database Access API could query the APM to
- figure what SQL dialect to employ.)
-
-
- For instructing the Database Access API to translate a named statement in
- a specific SQL dialect, we may define a new API call:
-
-
-statement_location statement_name sql_dialect sql
-
-
-
-
- which would be called at server initialization time. The Database Access API
- will then know to use the SQL statement appropriate for the specified
- SQLDialect. (The name db_implement_statement is
- very tentative.)
-
- Issues:
-
-
-
-
- Is making the caller of db_implement_statement explicitly
- specify the statement location (e.g., "/bboard/q-and-a") too much
- of a pain? Can we make this more convenient somehow?
-
-
-
-
-
- In the case that the inline SQL is not in the specified
- SQLDialect, reading the rewritten SQL into memory for the life
- of the server may not be a good idea. The three basic approaches I can think
- of to implement the
- db_implement_statement API are:
-
-
-
-
- Cache the rewritten SQL for the appropriate SQL dialect in an
- nsv array
-
-
-
-
- Cache the rewritten SQL for the appropriate SQL dialect in a special
- database table that we keep pinned in memory
-
-
-
-
- Cache the rewritten SQL for the appropriate SQL dialect in a special
- file, maybe even a DBM file
-
-
-
-
-
-
- Given the above two issues, should we rethink the
- db_implement_statement API
- altogether?
-
-
-
- One possibility is a file-based approach, where the alternative SQL
- statements would live in conventionally named and located files, e.g.,
- /bboard/q-and-a.postgres7 would contain Postgres 7 versions of
- the SQL statements in /bboard/q-and-a.tcl.) A potential con of
- this approach is that the Database Access API would have to perform file I/O
- for every SQL statement that's been rewritten. This may be a non-issue; I
- don't actually know. (We could augment this approach with caching too,
- perhaps a fixed-size LRU cache.)
-
- Another similar approach would be just to have one massive, magic file for
- each SQL dialect that maps each statement identifier (location plus name) to
- the corresponding statement.
-
-
-
- Another larger problem is the fact that this design does not work for
- instances where we build a SQL statement based on control flow logic, e.g.,
- we sometimes join in an extra table based on the user input. This problem
- doesn't mean that the design as a whole is broken; it just means that
- this design alone does not get us all the way to full SQL abstraction.
-
-
-
- Version 2.1 of the ArsDigita Oracle
- Driver adds a set of ns_ora analogs for the following
- ns_db calls:
- 0or1row, 1row,
- select, and
- dml.
- (It also adds ns_ora
- array_dml.) Thus, the groundwork for implementing the above API for
- ACS/Oracle is already established.
-
-
($Id$)