::xo::db Object Relational Database Interface
The database abstraction layer of xotcl-core interfaces between the OpenACS object model used in the relational Database and XOTcl objects. The database abstraction layer works for PostgreSQL and Oracle in exact the same way.
The functionality of the database abstraction layer provides separate classes for operation on generic ACS objects and on objects stored in the OpenACS content repository. The generic lookup queries and instantiate methods are provided through the following classes
- ::xo::db::Class (for ordinary ACS Objects)
- ::xo::db::CrClass (for content repository objects)
Generic operations on ACS Object IDs:
- ::xo::db::Class get_object_type -id
- ::xo::db::Class get_instance_from_db -id
- ::xo::db::Class exists_in_db -id
- ::xo::db::Class delete -id
Generic operations on ACS Object Types:
- ::xo::db::Class get_table_name -object_type
- ::xo::db::Class object_type_exists_in_db -object_type
- ::xo::db::Class get_class_from_db -object_type
- ::xo::db::Class drop_type -object_type -drop_table -cascade_p
- ::xo::db::Class delete_all_acs_objects -object_type
Generic operations on items of the content repository:
- ::xo::db::CrClass get_object_type -item_id -revision_id
- ::xo::db::CrClass get_instance_from_db -item_id -revision_id
- ::xo::db::CrClass lookup -item_id -revision_id
- ::xo::db::CrClass delete -item_id
Methods on classes for ACS Object Types
- <classname> new_persistent_object -package_id -creation_user -creation_ip ...
- <classname> object_types -subtypes_first
- <classname> create_object_type
- <classname> drop_object_type -cascade
- <classname> instance_select_query ...
- <classname> get_instances_from_db ...
Methods on content repository classes
- <classname> new_persistent_object -package_id -creation_user -creation_ip ...
- <classname> create_object_type
- <classname> drop_object_type
- <classname> get_instance_from_db -item_id -revision_id
- <classname> instance_select_query ...
- <classname> get_instances_from_db ...
- <classname> folder_type_unregister_all -include_subtypes -folderid register|unregister
- <classname> folder_type_unregister_all -include_subtypes
Methods on instances of ordinary classes
- <object> save -package_id -modifying_user
- <object> save_new -package_id -creation_user -creation_ip
- <object> delete
Methods on instances of content repository classes
- <object> save -modifying_user -live_p
- <object> save_new -package_id -creation_user -creation_ip -live_p
- <object> set_live_revision -revision_id -publish_status
- <object> delete
The following links provide a detailed description of these classes in the version as they are installed on openacs.org: ::xo::db::Class and ::xo::db::CrClass
The xotcl-core Database Abstraction Layer by Examples
The remainder of this page provides a short tutorial into the basic functionality of the interface. A more detailed description can be found in the xotcl-core tutorial
############################################################ # # 1) Create new ACS Objects, destroy it in memory, # load it from the database, delete it in the database. # .. Create a plain new ACS object just for demo purposes. .. The ACS object is created with a new object id. >> set o [::xo::db::Object new_persistent_object] = ::7845 .. Show the contents of object ::7845 by serializing it: >> ::7845 serialize = ::xo::db::Object create ::7845 -noinit \ -set object_title {Object 7845} \ -set object_id 7845 .. In the next steps, we (a) get the object_id of the newly .. created ACS object, (b) destroy the XOTcl object (the ACS .. object is still in the database, (c) we recreate the .. XOTcl object from the database, and (d) delete it in the .. database. .. Step (a) >> set o_id [::7845 object_id] = 7845 # # Delete object from memory: <object> destroy # Check, if an XOTcl object exists: ::xotcl::Object isobject <obj> # >> ::xotcl::Object isobject ::7845 = 1 .. Step (b) >> ::7845 destroy >> ::xotcl::Object isobject ::7845 = 0 # # Load an object from the database: ::xo::db::Class get_instance_from_db -id <id> # .. Step (c) >> set o [::xo::db::Class get_instance_from_db -id 7845] = ::7845 >> ::xotcl::Object isobject ::7845 = 1 .. Now, we have recreated the same object as before: >> ::7845 serialize = ::xo::db::Object create ::7845 -noinit \ -set object_title {Object 7845} \ -set object_id 7845 # # Check, if an ACS object exists in the database: ::xo::db::Class exists_in_db -id <id> # Delete object from memory and database: <object> delete # >> ::xo::db::Class exists_in_db -id 7845 = 1 .. Step (d) >> ::7845 delete .. Now, we have deleted the ACS Object and the XOTcl object: >> ::xo::db::Class exists_in_db -id 7845 = 0 >> ::xotcl::Object isobject ::7845 = 0 ############################################################ # # 2) Create new ACS Object Types, ACS Attributes and # SQL Tables from XOTcl Classes with slot definitions. # .. We want to create a new ACS Object type and .. an XOTcl class named ::demo::Person. .. Does the ACS Object type ::demo::Person exist in the database? >> ::xo::db::Class object_type_exists_in_db -object_type ::demo::Person = 0 .. The ACS Object Type should not exist (statement should return 0) .. We create a new XOTcl Class '::demo::Person'. .. By defining this class, the database layer takes care .. of creating the ACS Object Type and the necessary table via SQL. .. The persistent attributes (stored in the database) are defined .. as slots of type ::xo::db::Attribute. >> ::xo::db::Class create ::demo::Person \ -superclass ::xo::db::Object \ -slots { ::xo::db::Attribute create name -column_name pname ::xo::db::Attribute create age -default 0 -datatype integer ::xo::db::Attribute create projects -default {} -multivalued true } = ::demo::Person .. If the ACS Object Type and the ACS Attributes would be .. already defined in the database, the class definition above .. would be a no-op operation. .. Now, the ACS Object Type exists in the database >> ::xo::db::Class object_type_exists_in_db -object_type ::demo::Person = 1 .. The XOTcl class definition created automatically the .. following table for storing instances: CREATE TABLE demo_person ( age integer DEFAULT '0' , pname text , projects text DEFAULT '' , person_id integer REFERENCES acs_objects(object_id) ON DELETE CASCADE CONSTRAINT demo_person_person_id_pk PRIMARY KEY ) .. SQL attribute slot names: >> ::demo::Person array names db_slot = name age projects person_id .. The XOTcl class definition created as well a 'save' and .. an 'insert' method: .. Created 'save' method: ::demo::Person instproc save {} { db_transaction { next my instvar object_id name age projects db_dml dbqd..update_demo_person {update demo_person set pname = :name,age = :age,projects = :projects where person_id = :object_id } } } .. Created 'insert' method: ::demo::Person instproc insert {} { set __table_name [[self class] table_name] set __id [[self class] id_column] my set $__id [my set object_id] my log "ID insert in $__table_name, id = $__id = [my set $__id]" next foreach {__slot_name __slot} [[self class] array get db_slot] { my instvar $__slot_name if {[info exists $__slot_name]} { lappend __vars $__slot_name lappend __atts [$__slot column_name] } } db_dml dbqd..insert_$__table_name "insert into $__table_name ([join $__atts ,]) values (:[join $__vars ,:])" } .. The 'insert' method is typically called via .. '<classname> new', which takes care about db_transaction (see below) # # Create a new instance of ::demo::Person with name 'Gustaf' # # The method 'new_persistent_object' of a database class (instance of ::xo::db::Class) # creates an ACS Object with a fresh id in the database and # creates as well an XOTcl object in memory >> set p [::demo::Person new_persistent_object -name Gustaf -age 105] = ::7846 ::7846 created .. check, if object ::7846 exists in memory >> ::xotcl::Object isobject ::7846 = 1 .. check, if object ::7846 exists in the database >> ::xo::db::Class exists_in_db -id 7846 = 1 .. Every persistent XOTcl object has an object_id. >> ::7846 exists object_id = 1 .. Show the contents of object ::7846 (using serialize) >> ::7846 serialize = ::demo::Person create ::7846 -noinit \ -set object_title {Person 7846} \ -set name Gustaf \ -set age 105 \ -set projects {} \ -set person_id 7846 \ -set object_id 7846 .. modify some attributes of the XOTcl object >> ::7846 incr age = 106 .. show modified contents of ::7846 ::demo::Person create ::7846 -noinit \ -set object_title {Person 7846} \ -set name Gustaf \ -set age 106 \ -set projects {} \ -set person_id 7846 \ -set object_id 7846 .. save the modified object data in the database >> ::7846 save >> set person_id [$p person_id] = 7846 .. deleting xotcl object ::7846 in memory >> $p destroy .. check, if object ::7846 exists in memory >> ::xotcl::Object isobject ::7846 = 0 .. check, if object ::7846 exists in the database >> ::xo::db::Class exists_in_db -id 7846 = 1 .. fetch person again from database: >> set p [::xo::db::Class get_instance_from_db -id 7846] = ::7846 .. check, if object ::7846 exists in memory >> ::xotcl::Object isobject ::7846 = 1 ::demo::Person create ::7846 -noinit \ -set object_title {Person 7846} \ -set name Gustaf \ -set age 106 \ -set projects {} \ -set object_id 7846 \ -set person_id 7846 .. The object ::7846 was fetched from the database using the .. automatically created query: SELECT demo_person.pname AS name,demo_person.age, demo_person.projects,demo_person.person_id, acs_objects.title AS object_title,acs_objects.object_id FROM demo_person,acs_objects WHERE person_id = 7846 and object_id = person_id .. In order to delete an object from the database, .. the method 'delete' can be used. 'delete' deletes the .. ACS object in the database as well the XOTcl object in memory. >> set p_id [::7846 object_id] = 7846 >> ::xo::db::Class exists_in_db -id 7846 = 1 >> ::7846 delete >> ::xo::db::Class exists_in_db -id 7846 = 0 .. Instead of using 'new_persistent_object' to create .. new acs_objects, one can use the method 'new' in .. combination with 'save_new'. While the method 'new' creates .. an XOTcl object in memory, the method 'save_new' can be used .. to create a new ACS object (with a new object_id) an to .. save this object persistently in the database. >> set p [::demo::Person new -name Gustaf -age 105] = ::xotcl::__#A >> ::xotcl::__#A exists object_id = 0 >> ::xotcl::__#A save_new = 7847 >> ::xotcl::__#A exists object_id = 1 .. Now, we create a subclass of ::demo::Person called ::demo::Employee .. which has a few more attributes. Again, we define an XOTcl class .. ::demo::Employee which creates the ACS Object Type, the ACS .. attributes and the table, if necessary. >> ::xo::db::Class create ::demo::Employee \ -superclass ::demo::Person \ -table_name demo_employee \ -id_column employee_id \ -slots { ::xo::db::Attribute create salary -datatype integer ::xo::db::Attribute create dept_nr -datatype integer -default "0" } = ::demo::Employee .. The XOTcl class definition created automatically the .. following table for storing instances: CREATE TABLE demo_employee ( dept_nr integer DEFAULT '0' , salary integer , employee_id integer REFERENCES demo_person(person_id) ON DELETE CASCADE CONSTRAINT demo_employee_employee_id_pk PRIMARY KEY ) .. Create a first new employee: >> set p1 [::demo::Employee new_persistent_object -name Neophytos -age 25] = ::7848 .. show contents of ::7848 ::demo::Employee create ::7848 -noinit \ -set employee_id 7848 \ -set object_title {Employee 7848} \ -set dept_nr 0 \ -set name Neophytos \ -set age 25 \ -set projects {} \ -set person_id 7848 \ -set object_id 7848 .. Create a second new employee: >> set p2 [::demo::Employee new_persistent_object -name Lore -age 35 -salary 100000] = ::7849 .. show contents of ::7849 ::demo::Employee create ::7849 -noinit \ -set employee_id 7849 \ -set object_title {Employee 7849} \ -set salary 100000 \ -set dept_nr 0 \ -set name Lore \ -set age 35 \ -set projects {} \ -set person_id 7849 \ -set object_id 7849 .. Create a third new employee: >> set p3 [::demo::Employee new_persistent_object -name Nora -age 7 -salary 100] = ::7850 .. show contents of ::7850 ::demo::Employee create ::7850 -noinit \ -set employee_id 7850 \ -set object_title {Employee 7850} \ -set salary 100 \ -set dept_nr 0 \ -set name Nora \ -set age 7 \ -set projects {} \ -set person_id 7850 \ -set object_id 7850 # # Delete object from memory: <object> destroy # >> ::xotcl::Object isobject ::7848 = 1 >> set p1_id [$p1 object_id] = 7848 >> ::xo::db::Class exists_in_db -id 7848 = 1 >> $p1 destroy >> ::xotcl::Object isobject ::7848 = 0 >> ::xo::db::Class exists_in_db -id 7848 = 1 # # Delete object from memory and database: <object> delete # >> ::xotcl::Object isobject ::7849 = 1 >> set p2_id [$p2 object_id] = 7849 >> ::xo::db::Class exists_in_db -id 7849 = 1 >> $p2 delete >> ::xotcl::Object isobject ::7849 = 0 >> ::xo::db::Class exists_in_db -id 7849 = 0 .. Fetch employee with id 7848 again from the database: >> set p [::xo::db::Class get_instance_from_db -id 7848] = ::7848 .. show contents of ::7848 ::demo::Employee create ::7848 -noinit \ -set object_title {Employee 7848} \ -set salary {} \ -set employee_id 7848 \ -set dept_nr 0 \ -set name Neophytos \ -set age 25 \ -set projects {} \ -set object_id 7848 \ -set person_id 7848 .. The object ::7848 was fetched from the database using the .. automatically created query: SELECT demo_employee.employee_id,demo_employee.salary, demo_employee.dept_nr, demo_person.pname AS name,demo_person.age, demo_person.projects,demo_person.person_id, acs_objects.title AS object_title,acs_objects.object_id FROM demo_employee,demo_person,acs_objects WHERE employee_id = 7848 and person_id = employee_id and object_id = employee_id >> ::7848 destroy .. Query the instances from the database .. Instances are queried by default based on the following, .. automatically generated SQL Query: >> ::demo::Employee instance_select_query = SELECT demo_employee.employee_id,demo_employee.salary, demo_employee.dept_nr, demo_person.pname AS name,demo_person.age, demo_person.projects, demo_person.person_id, acs_objects.title AS object_title,acs_objects.object_id FROM demo_employee,demo_person,acs_objects WHERE person_id = employee_id and object_id = employee_id .. Query the object using this query into a set of objects. >> set s [::demo::Employee get_instances_from_db] = ::xotcl::__#H .. The result is an OrderedComposite. Children can be accessed .. via the 'children' method: >> llength [$s children] = 2 .. serialize all children ::xotcl::Object create ::xotcl::__#I -noinit \ -set __parent ::xotcl::__#H \ -set object_title {Employee 7848} \ -set dept_nr 0 \ -set salary {} \ -set employee_id 7848 \ -set age 25 \ -set name Neophytos \ -set projects {} \ -set object_id 7848 \ -set person_id 7848 ::xotcl::Object create ::xotcl::__#J -noinit \ -set __parent ::xotcl::__#H \ -set object_title {Employee 7850} \ -set dept_nr 0 \ -set salary 100 \ -set employee_id 7850 \ -set age 7 \ -set name Nora \ -set projects {} \ -set object_id 7850 \ -set person_id 7850 .. The instance_select_query can be configured in many ways. .. Here we use the '-count true' option to return just the number .. of solutions: >> ::demo::Employee instance_select_query -count true = SELECT count(*) FROM demo_employee,demo_person,acs_objects WHERE person_id = employee_id and object_id = employee_id >> db_string cnt [::demo::Employee instance_select_query -count true] = 2 .. The same queries for ::demo::Person instead of ::demo::Employee. .. Note, that we get the person data of employees as well, since .. employees are as well persons (i.e. a specialization of person): >> ::demo::Person instance_select_query = SELECT demo_person.pname AS name,demo_person.age, demo_person.projects,demo_person.person_id, acs_objects.title AS object_title,acs_objects.object_id FROM demo_person,acs_objects WHERE object_id = person_id >> set s [::demo::Person get_instances_from_db] = ::xotcl::__#M >> llength [$s children] = 3 ::xotcl::Object create ::xotcl::__#N -noinit \ -set __parent ::xotcl::__#M \ -set object_title {Person 7847} \ -set age 105 \ -set name Gustaf \ -set projects {} \ -set object_id 7847 \ -set person_id 7847 ::xotcl::Object create ::xotcl::__#O -noinit \ -set __parent ::xotcl::__#M \ -set object_title {Employee 7848} \ -set age 25 \ -set name Neophytos \ -set projects {} \ -set object_id 7848 \ -set person_id 7848 ::xotcl::Object create ::xotcl::__#P -noinit \ -set __parent ::xotcl::__#M \ -set object_title {Employee 7850} \ -set age 7 \ -set name Nora \ -set projects {} \ -set object_id 7850 \ -set person_id 7850 TODO: explain more options for instance_select_query and get_instances_from_db ############################################################ # # 3) Create XOTcl classes from existing ACS Object Types # and ACS Attributes based on the definitions in the # database >> set c [::xo::db::Class get_class_from_db -object_type party] = ::xo::db::party .. XOTcl class ::xo::db::party created (superclass ::xo::db::Object) .. SQL attributes: >> ::xo::db::party array names db_slot = email party_id url >> set c [::xo::db::Class get_class_from_db -object_type person] = ::xo::db::person .. XOTcl class ::xo::db::person created (superclass ::xo::db::party) .. SQL attributes: >> ::xo::db::person array names db_slot = last_name first_names person_id >> set c [::xo::db::Class get_class_from_db -object_type user] = ::xo::db::user .. XOTcl class ::xo::db::user created (superclass ::xo::db::person) .. SQL attributes: >> ::xo::db::user array names db_slot = user_id >> set c [::xo::db::Class get_class_from_db -object_type group] = ::xo::db::group .. XOTcl class ::xo::db::group created (superclass ::xo::db::party) .. SQL attributes: >> ::xo::db::group array names db_slot = group_name group_id .. Create XOTcl object for user_id = 0 .. please log in >> set u [::xo::db::Class get_instance_from_db -id $myuser] = ::0 .. ::0 created, class ::xo::db::user .. class hierarchy for ::0 ::xo::db::user ::xo::db::person ::xo::db::party ::xo::db::Object ::xotcl::Object .. show contents of ::0 ::xo::db::user create ::0 -noinit \ -set object_title Unregistered Visitor \ -set party_id 0 \ -set email {} \ -set last_name Visitor \ -set object_id 0 \ -set url {} \ -set person_id 0 \ -set first_names Unregistered \ -set user_id 0 .. The object ::0 was fetched from the database using the .. automatically created query: SELECT users.user_id,persons.last_name,persons.first_names, persons.person_id,parties.email, parties.party_id,parties.url, acs_objects.title AS object_title,acs_objects.object_id FROM users,persons,parties,acs_objects WHERE user_id = 0 and person_id = user_id and party_id = user_id and object_id = user_id .. Now we modify the user. To be on the safe side, we .. a) save firstly the original URL of the current user, then .. b) we set it to a new value and save the user information .. to the database .. c) delete the user object in memory .. d) load it again from the database to see the modified data .. e) reset it to the original value and save it again to restore .. the original state .. Step a: >> set url [::0 url] .. Step b: >> ::0 url https://openacs.org/ = https://openacs.org/ >> ::0 save .. Step c: >> ::0 destroy .. Step d: >> set u [::xo::db::Class get_instance_from_db -id $myuser] = ::0 .. show contents of ::0 ::xo::db::user create ::0 -noinit \ -set object_title Unregistered Visitor \ -set party_id 0 \ -set email {} \ -set last_name Visitor \ -set object_id 0 \ -set url https://openacs.org" \ -set person_id 0 \ -set first_names Unregistered \ -set user_id 0 .. Step e: >> ::0 url $url >> ::0 save >> ::0 destroy >> set u [::xo::db::Class get_instance_from_db -id $myuser] = ::0 .. show contents of ::0 ::xo::db::user create ::0 -noinit \ -set object_title Unregistered Visitor \ -set party_id 0 \ -set email {} \ -set last_name Visitor \ -set object_id 0 \ -set url {} \ -set person_id 0 \ -set first_names Unregistered \ -set user_id 0 ############################################################ # # 4) Use the generic Content Repository interface (using # just cr_items and cr_revisions) # .. check, if cr_item with name 'testing' exists >> set item_id [::xo::db::CrClass lookup -name testing] = 7841 .. yes, it exists; delete it without instantiating >> ::xo::db::CrItem delete -item_id 7841 .. create item >> set i [::xo::db::CrItem new -name "testing" -title "Title of Hello World" -text "Hello World" ] = ::xotcl::__#a >> $i save_new = 7852 .. show contents of item ::xo::db::CrItem create ::xotcl::__#a -noinit \ -set creation_date {2007-09-03 23:28:26.727511+02} \ -set creation_user 0 \ -set object_id 7852 \ -set description {} \ -set text {Hello World} \ -set nls_language en_US \ -set mime_type text/plain \ -set name testing \ -set publish_status ready \ -set title {Title of Hello World} \ -set revision_id 7851 \ -set item_id 7852 \ -set last_modified {2007-09-03 23:28:26.727511+02} \ -set parent_id -100 .. update content >> ::xotcl::__#a append text {... more text.. more text.. more text.} = Hello World... more text.. more text.. more text. >> ::xotcl::__#a append title { - v2} = Title of Hello World - v2 .. show modified contents of item ::xo::db::CrItem create ::xotcl::__#a -noinit \ -set creation_date {2007-09-03 23:28:26.727511+02} \ -set creation_user 0 \ -set object_id 7852 \ -set description {} \ -set text {Hello World... more text.. more text.. more text.} \ -set nls_language en_US \ -set mime_type text/plain \ -set name testing \ -set publish_status ready \ -set title {Title of Hello World - v2} \ -set revision_id 7851 \ -set item_id 7852 \ -set last_modified {2007-09-03 23:28:26.727511+02} \ -set parent_id -100 >> ::xotcl::__#a save = 7852 .. method 'save' creates a new revision; see changed revision_id below ::xo::db::CrItem create ::xotcl::__#a -noinit \ -set creation_date {2007-09-03 23:28:26.727511+02} \ -set creation_user 0 \ -set object_id 7852 \ -set description {} \ -set text {Hello World... more text.. more text.. more text.} \ -set nls_language en_US \ -set mime_type text/plain \ -set name testing \ -set publish_status ready \ -set title {Title of Hello World - v2} \ -set revision_id 7853 \ -set item_id 7852 \ -set last_modified {2007-09-03 23:28:26.727511+02} \ -set parent_id -100 >> set item_id 7852 = 7852 >> ::xotcl::__#a destroy >> set i [::xo::db::CrClass get_instance_from_db -item_id 7852] = ::7852 ::xo::db::CrItem create ::7852 -noinit \ -set object_type content_revision \ -set creation_date {2007-09-03 23:28:26.727511+02} \ -set object_id 7853 \ -set creation_user 0 \ -set description {} \ -set text {Hello World... more text.. more text.. more text.} \ -set nls_language en_US \ -set package_id 492 \ -set name testing \ -set mime_type text/plain \ -set publish_status ready \ -set title {Title of Hello World - v2} \ -set item_id 7852 \ -set revision_id 7853 \ -set last_modified {2007-09-03 23:28:26.750059+02} \ -set parent_id -100 ############################################################ # # 5) Create new application classes by sub-typing the # Content Repository, adding additional attributes # .. We create a subclass of ::xo::db::CrItem called ::demo::Page .. which has a few more attributes. Actually, this class is very .. similar to ::xowiki::Page. Again, we define an XOTcl class .. ::demo::Page which creates the ACS Object Type, the ACS .. attributes and the table, if necessary. >> # content class very similar to ::xowiki::Page ::xo::db::CrClass create Page \ -superclass ::xo::db::CrItem \ -pretty_name "demo Page" \ -mime_type text/html \ -slots { if {[::xo::db::has_ltree]} { ::xo::db::CrAttribute create page_order \ -sqltype ltree -validator page_order \ -default "" } ::xo::db::CrAttribute create creator \ -column_name creator_string } = ::demo::Page .. The sql_attribute_names for content items contain .. the attributes of all supertypes: >> ::demo::Page array names db_slot = creator page_order page_id object_id description text object_title nls_language mime_type name title item_id revision_id >> ::demo::Page info slots = ::demo::Page::slot::creator ::demo::Page::slot::page_order ::demo::Page::slot::mime_type ::demo::Page::slot::page_id >> ::xo::slotobjects ::demo::Page = ::demo::Page::slot::creator ::demo::Page::slot::page_order ::demo::Page::slot::mime_type ::demo::Page::slot::page_id ::xo::db::CrItem::slot::package_id ::xo::db::CrItem::slot::nls_language ::xo::db::CrItem::slot::description ::xo::db::CrItem::slot::name ::xo::db::CrItem::slot::text ::xo::db::CrItem::slot::publish_status ::xo::db::CrItem::slot::parent_id ::xo::db::CrItem::slot::title ::xo::db::CrItem::slot::revision_id ::xo::db::CrItem::slot::item_id ::xo::db::Object::slot::object_title ::xo::db::Object::slot::object_id .. create page >> set i [Page new \ -name "page0" \ -title "Joke of the Month" \ -creator "GN" \ -text "Three cannibals meet in a NYC subway station..." ] = ::xotcl::__#j >> $i save_new = 7855 .. show contents of page object ::xotcl::__#j (including creator and page_order, .. when ltree is available) ::demo::Page create ::xotcl::__#j -noinit \ -set page_order {} \ -set creator GN \ -set page_id {} \ -set creation_date {2007-09-03 23:28:29.149591+02} \ -set object_id 7855 \ -set creation_user 0 \ -set description {} \ -set text {Three cannibals meet in a NYC subway station...} \ -set nls_language en_US \ -set mime_type text/html \ -set name page0 \ -set publish_status ready \ -set title {Joke of the Month} \ -set revision_id 7854 \ -set item_id 7855 \ -set last_modified {2007-09-03 23:28:29.149591+02} \ -set parent_id -100 >> set item_id [::xotcl::__#j item_id] = 7855 >> ::xotcl::__#j destroy >> ::demo::Page get_instance_from_db -item_id 7855 = ::7855 ::demo::Page create ::7855 -noinit \ -set page_order {} \ -set object_type ::demo::Page \ -set page_id 7854 \ -set creation_date {2007-09-03 23:28:29.149591+02} \ -set object_id 7854 \ -set creation_user 0 \ -set description {} \ -set text {Three cannibals meet in a NYC subway station...} \ -set nls_language en_US \ -set package_id 492 \ -set name page0 \ -set mime_type text/html \ -set title {Joke of the Month} \ -set publish_status ready \ -set revision_id 7854 \ -set item_id 7855 \ -set last_modified {2007-09-03 23:28:29.149591+02} \ -set parent_id -100 \ -set creator_string GN
in last 30 minutes
OpenACS.org
- HOME
- News
- OpenACS Projects
- Activity Graph
- Admin Package RFC
- Bugtracker Cleanup Project
- Collaboration Graph
- Community Metrics in OpenACS
- Debian/Ubuntu installer developing
- Documentation Project
- Documentation Project Discussion
- Documentation Project Plan (Approach 4)
- {done} Change Log from OpenACS 5.4.2 to OpenACS 5.4.3
- {done} OpenACS 5.3.x releases
- {done} Release Notes OpenACS 5.4.3
- Dynamic Object Types and Attributes
- Ecommerce G2
- E-Mail: Event Handling
- E-Mail: Incoming E-Mail
- E-Mail: Outgoing E-Mail
- Forums Project
- GETable resources, that should be POSTable resources
- Interface / CSS Coding Guidelines
- Logo
- .LRN
- Mentorship Program
- Migration from CVS to GIT
- Official Test Servers
- OpenACS 5.10.0 Change Summary
- OpenACS 5.10.1 Change Summary
- OpenACS 5.9 HTML validity fixes
- OpenACS/.LRN for Debian
- OpenACS Packaging for Debian and Ubuntu
- OpenACS Release Status
- OpenACS TODO List
- Package Object Types
- Package Testing Process
- Prerequisites and Procedures for Migrating to Subversion from CVS
- Site Nodes Proposal (Draft)
- Site Wide File Upload
- Site Wide Image Upload Widget
- (Sketch for) OpenACS Home
- Theme Manager
- Theming Project
- Translation server for OpenACS packages
- User interface mockups
- Website_Redesign
- XoWiki Design Ideas
- YUI Project
- Marketing
- Our Website
- Packages
- Available OpenACS Packages
- Core Packages
- ACS Admin
- ACS API Browser
- ACS Authentication
- ACS Automated Testing
- ACS Bootstrap Installer
- ACS Content Repository
- ACS Core Docs
- ACS Default Theme
- ACS Developer Support
- ACS Kernel
- ACS Lang
- ACS Mail Lite
- ACS Messaging
- ACS Reference Data
- ACS Service Contract
- ACS Subsite
- ACS Tcl
- ACS Templating
- ACS Translations
- Intermedia Driver
- Notifications
- Reference Data - Country
- Reference Data - Language
- Reference Data - Timezone
- Search
- Tsearch2 Driver
- Non-Core Packages
- ACS Date Time
- ACS Events
- ACS Interface
- ACS Object Management
- Address Book
- Ad Server
- Ajax Filestore UI
- Ajax Helper
- Ajax Photoalbum UI
- Anonymous Evaluation
- Assessment
- Attachments
- Attendance
- Attribute Management System
- Auth CAS
- Authentication Server
- Auth HTTP
- Authorize.net Gateway
- Beehive
- Bookmarks
- Bookshelf
- Boomerang Plugin
- B Responsive Theme
- Bug tracker
- Bulk mail
- Calendar
- Calendar Includelet
- Cards
- Categories
- Chat
- Chat Includelet
- Clickthrough
- Clipboard
- CMS
- CMS News Demo
- Connections
- Contacts
- Contacts Lite
- Content Includelet
- Cookie Consent Widget
- Cronjob
- Curriculum
- Curriculum Central
- Curriculum Tracker
- Datamanager
- dbm
- Diagram
- Directory
- Download
- Dynamic Object Type
- E-Commerce
- Ecommerce Serial Number Tracking
- Edit This Page
- EduWiki
- Email Handler
- Evaluation
- Expense
- Expense Tracking
- EZIC Gateway
- Facebook API
- FAQ
- Feed parser
- File Manager
- File storage
- File Storage Includelet
- Forums
- Forums Includelet
- GateKeeper
- General comments
- Glossar
- Glossary
- Image Magick
- IMS Enterprise
- Imsld
- Invoices
- Jabber
- Lab Report
- Lab Report Central
- LAMS Integration
- LAMS Integration Configuration
- Latest
- Layout Managed Subsite
- Layout Manager
- LDAP Authentication Driver
- Learning Content
- Logger
- LORS management Includelet
- Mail Tracking
- MMplayer
- Monitoring
- New portal
- News
- News aggregator
- News Includelet
- Notes
- OCT Election
- openacs-bootstrap3-theme
- Organization
- Outdated Library functions
- Package Builder
- Page
- Pages
- PAM Authentication Driver
- Payment Gateway
- Permissions Administrator
- Photo album
- Planner
- Poll
- Postal Address
- Post Card
- Press
- Profile provider
- Project Manager
- Q-Forms
- Quota
- Q-Wiki
- Ratings
- Recruiting
- Redirect
- Reference Data - Currency
- Reference Data - ITU Code
- Reference Data - UNSPSC code
- Reference Data - US County
- Reference Data - US State
- Reference Data - US Zipcode
- Related Items
- Richtext CKEditor 4
- Richtext CKEditor 5
- Richtext TinyMCE
- Richtext Xinha
- Robot Detection
- RSS support
- S5
- Sample Gateway
- Schema Browser
- Scholarship Fund
- Scorm Core
- Scorm Importer
- Scorm Player
- Scorm Simple LMS
- Selva theme
- Shipping Service Contract
- Simple Survey
- Simulation
- Site-wide Search
- Skin
- SOAP db
- SOAP Gateway
- Spreadsheet
- Static Pages
- Survey
- Survey Library
- Survey Reports
- T Account
- Tasks
- Tcl SOAP
- Telecom Information
- Trackback
- User preferences
- User profile
- Value-based Shipping
- Version Control
- Views
- WebDAV Support
- Weblogger
- Webmail System
- Wikipedia
- Wimpypoint slim
- Workflow
- XCMS User Interface
- XML RPC
- XO Learning Performance
- xolirc
- xooauth
- XOTcl Core
- XOTcl Request Monitor
- xowf plugin for Monaco code editor
- xowf (XoWiki Workflow)
- XoWiki
- XoWiki Includelet
- ecommerce-g2
- Accounts Desk
- Accounts Finance
- Accounts Payables
- Accounts Payroll
- Accounts Receivables
- Bulk Upload
- CL Custom Commerce
- Customer Service
- E-commerce 2
- Fabrication
- Field Service
- General Ledger
- Human Resources
- Inventory Control
- Manufacturing Design
- Online Catalog
- Production
- Reference Data - GIFI
- Ship-Track
- Vendors-Suppliers
- DotLrn
- Anon Eval Applet
- Anon Eval Portlet
- Application track
- Application track Applet
- Application track portlet
- Assessment Applet
- Assessment portlet
- Attendance Applet
- Beehive Applet
- Beehive Portlet
- Bulk mail Applet
- Bulk mail Portlet
- Calendar Applet
- Calendar portlet
- Cards applet
- Cards portlet
- Chat Applet
- Chat Portlet
- Contacts Applet
- Contacts Portlet
- Content Applet
- Content Portlet
- Courses
- Curriculum Applet
- Curriculum Portlet
- Datamanager Portlet
- dotLRN
- dotLRN Administration
- dotLRN applet
- dotLRN Bootstrap 3 Theme
- dotLRN Course Catalog
- dotLRN Datamanager Applet
- dotLRN - Ecommerce
- dotLRN portlet
- dotLRN Roadmap
- Edit-this-page Applet
- Edit-this-page Portlet
- EduWiki Applet
- EduWiki Portlet
- Evaluation applet
- Evaluation portlet
- Expense-tracking Applet
- FAQ Applet
- FAQ Portlet
- File Storage Applet
- File Storage Portlet
- Forums Applet
- Forums Portlet
- Glossar Applet
- Glossar Portlet
- Homework Applet
- IMS-LD Applet
- IMS LD Portlet
- Invoices Applet
- Invoices Portlet
- Jabber Applet
- Jabber Portlet
- LAMS Integration Applet
- LAMS Integration Portlet
- Latest Applet
- Latest Portlet
- Learning Content Applet
- Learning Content Portlet
- LORS central
- LORS - Learning Objects Repository Service
- LORS management
- LORS management Applet
- LORS management Portlet
- Messages Applet
- Messages Portlet
- MMplayer Applet
- MMplayer Portlet
- News Aggregator Applet
- News Aggregator Portlet
- News Applet
- News Portlet
- Photo Album Applet
- Photo Album Portlet
- Private-Message
- Project-manager Applet
- Project Manager Portlet
- Quota Applet
- Quota Portlet
- Random-photo Applet
- Random-photo Portlet
- Recruiting Applet
- Recruiting Portlet
- Research Applet
- Research Portlet
- Static Applet
- Static Portlet
- Survey Applet
- Survey Portlet
- Syllabus Applet
- Tasks Applet
- Tasks Portlet
- Theme Zen
- User Tracking
- User Tracking Applet
- User Tracking Portlet
- Weblogger Applet
- Weblogger Portlet
- Wikipedia Applet
- Wikipedia Portlet
- Wimpypoint Slim Applet
- Wimpypoint Slim Portlet
- XoWiki Applet
- XoWiki Portlet
- Contrib Packages
- Acknowledgement
- BCDS
- BCMS
- BCMS UI Base
- BCMS UI Wizard
- Classified Ads
- COP Base
- COP UI
- Events Management
- Form To Mail
- Irc Applet
- IRC Logger
- Mail Clickthrough
- mailing-lists
- PayFlowPro Gateway
- Personal Community
- Photobook
- Populate
- Research Papers
- Resource List
- Room Reservation
- Users Selection
- Vocabulary
- Deprecated Packages
- {deprecated} ACS Content
- {deprecated} ACS LDAP Authentication
- {deprecated} ACS Mail
- {deprecated} ACS Utility Services
- {deprecated} Bboard Portlet
- {deprecated} dotFOLIO
- {deprecated} dotFOLIO UI
- {deprecated} dotLRN BBoard Applet
- {deprecated} OpenFTS Driver
- {deprecated} Portal
- {deprecated} Sloan Bboard
- {deprecated} Spam System
- {deprecated} Webmail
- {deprecated} Wiki
- {deprecated} Workflow Service
- Community
- Getting admin-level help
- Getting help
- Goals / Ideas
- History of OpenACS
- Marketing Team
- Most Popular Pages
- OpenACS Translation server
- Events
- 2006 Fall Conference Interest in Attending
- 2006 Fall Conference Presentations
- 2006 Fall Conference Submissions and Program
- 2006 International Workshop on Community Based E-Learning Systems
- 2006 November 2nd (General Web Applications Focus - OpenACS)
- 2006 November 3rd and November 4th (Training and Hacking Days)
- 2006 OpenACS/.LRN Fall Conference
- 2006 Session 1: Towards full Accessibility in LMS
- 2007 Project Ideas for Google Summer of Code
- OpenACS conferences
- OCT
- F. A. Q.
- .LRN
- 2006 Fall Conference Submissions and Program
- Content development tools options
- Documentation and help pages for individual .LRN installations
- Educational Wiki (Eduwiki) Tool
- How to contribute code that passes accessibility tests
- Learning Content Tool
- .LRN
- .LRN Accessibility
- .LRN Core Team (DRAFT)
- .LRN Educational standards support
- .LRN Get Involved!
- .LRN Governance
- .LRN Installation
- .LRN Installation (up to .LRN 2.5.0)
- .LRN Leadership Team 2008
- .LRN Meetings
- .LRN Motions (DRAFT)
- Modelling Learners Preferences
- Plataforma Elearning
- SCORM support
- Simple Content Creator / Editor
- Time/Topics Planner for dotLRN Courses
- Consortium
- Releases
- .LRN 2.2 bugs
- .LRN 2.2 Release Management
- .LRN 2.2 to .LRN 2.3.0 Change Log
- .LRN 2.3.0 to .LRN 2.3.1 Change Log
- .LRN 2.3.1 Release Notes
- .LRN 2.3.1 to .LRN 2.4 Change Log
- .LRN 2.3 Release Management
- .LRN 2.4.0 to .LRN 2.4.1 Change Log
- .LRN 2.4.1 Release Notes
- .LRN 2.4 Release Management
- .LRN 2.4 Release Notes
- .LRN 2.5 Release Management
- Zen Project
- Coding Standards
- ADP Files
- Ajax and Accessibility
- Code Formatting
- Coding Standards - Index
- Commit Messages
- Emacs as an OpenACS IDE
- How to contribute code that passes accessibility tests
- Logging Conventions
- .LRN Zen Project: Standards
- Naming Conventions
- Security Guidelines
- SQL - XQL
- Tcl pages
- Tcl Procs
- template::head::*
- Vi as an OpenACS IDE
- WCAG 1.0 Checkpoints
- Web Forms
- Web Lists / Tables
- External Resources
- Cookbook
- Accessing LTI services from OpenACS
- Add extra headers
- Cookbook
- Creating adp box tags for consistent html/css
- Double Click Handling
- E-Mail: Event Handling
- E-Mail: Incoming E-Mail
- E-Mail: Outgoing E-Mail
- F. A. Q.
- Fresh install of OpenACS 5.10 on Oracle 19c
- Handling out of memory on "exec" calls
- Host Node Map
- How to configure a Network Place under Windows XP to access file-storage via WebDAV
- How to handle "connection already closed" errors
- How to manage/upgrade CKEditor versions
- How to tune cache sizes
- Interfacing with MS Teams and related services (Microsoft Graph)
- Managing Versions of External JavaScript Libraries
- Modifying the look of an installation
- NaviServer and OpenACS with Docker
- New Interface for Calling Database functions
- OpenACS Performance Tuning
- Passing values up from an include
- Permissions explored, a practical way exists
- Refactoring Recipes
- Running OpenACS behind a proxy
- Security: Content Security Policy (CSP)
- Security: Cross Site Request Forgery (CSRF)
- Server-sent events
- Setup with docker-s6
- SQL: How to log (slow) queries in the system log
- Streaming HTML
- Using OpenACS with External Identity Providers
- Using Pound as a reverse Proxy
- When to use URLencode
- XoWiki: How to save files directly in the wiki
- XoWiki: List of the available includelets
- Resources
- Accessibility
- Testing Pages
- category test
- Commit graph
- Commits
- Comparison of the CTRL Surveys Package vs. the OACS Assessment Package
- fullpage
- just playing around
- name with space
- OpenACS Object Types
- Pastebin for irc
- preview.png
- QUOTA
- Recently Changed Pages
- toc-test-page
- Wikipedia
- XoWiki Slides from the Vienna OpenACS conference
- Directory - Who's Who
- Documentation
- Collaboration Graph
- Documentation Credits
- Documentation History
- Documentation Introduction
- Documentation Process test-doc (Approach 3)
- Documentation Project Discussion
- Documentation Project Plan (Approach 4)
- for administrators
- for administrators - Table of Contents
- for beginning developers
- for developers
- for developers - Table of Contents
- for everyone
- for everyone - Table of Contents
- Most Popular Pages
- OpenACS Handbook
- Try Openacs
- WikiDoc Project Notice
- Package Documentation
- Aliases at CVS
- Available OpenACS Packages
- Packages available in the oacs-5-10 channel
- Packages available in the oacs-5-9 channel
- Documentation Non-Core Packages
- Marketing Documentation
- Tutorials
- Developer Tutorial - Req.
- for beginning developers
- Introduction to OpenACS
- Next Steps After Installation, Debian Specific
- OpenACS/dotLRN windows installer how to
- Theming in OpenACS
- Tutorials for Designers
- Tutorials for Users
- Tutorials for Administrators
- Tutorials for Programmers
- Add extra headers
- Automated Installs - Using install.xml
- Body Onload javascript event
- Emacs as an OpenACS IDE
- listbuilder tutorial
- OpenACS 5.1.4 / PG 7.3.6 => 5.2.3/8.0.7 Upgrade Path for acs-core
- OpenACS mode for Emacs
- Vi as an OpenACS IDE
- Webinar - Part 1 - Basics
- Webinar - Part 2 - Site Map Administration
- Webinar - Part 3 - Packages and ad_form
- Webinar - Part 4 - Survey
- Tutorials - The N00B Journey
- Core Documentation
- Subsystems Documentation
- Administrators - Req.
- AOLserver
- AOLserver administration
- Available OpenACS Packages
- Boost your application performance to serve large files!
- Conditional CREATE Index for Postgresql and Oracle
- Deployment feedback channel
- Developer - Requirements
- Developer Tutorial - Req.
- Emacs as an OpenACS IDE
- End-users - Requirements
- for administrators
- for administrators - Table of Contents
- for beginning developers
- for developers
- for developers - Table of Contents
- for everyone
- for everyone - Table of Contents
- Get the OpenACS Source Code
- Getting admin-level help
- hstore
- Install a *nix-based operating system (OS)
- Install AOLserver
- Install AOLserver 4.5
- Installation - Req.
- Installing OpenACS
- Installing OpenACS on Arch Linux
- Installing OpenACS on debian
- Installing OpenACS on FreeBSD
- Installing OpenACS on FreeBSD (quick)
- Installing OpenACS on FreeBSD with ports
- Installing OpenACS on Mac OS X
- Installing OpenACS on Redhat
- Installing OpenACS on RPM-based systems
- Installing OpenACS on Solaris
- Installing OpenACS on SuSE
- Installing OpenACS on win2k
- Installing OpenACS on Windows
- Install OpenACS distribution
- Install OpenACS on debian unstable / Ubuntu 7.10
- Install OpenACS on Linux
- Install OpenACS on Mac OS X 10.5 / 10.6 (Snow Leopard) Using Macports
- Install OpenACS - prereqs
- Install OpenACS with NaviServer from Scratch
- Install Oracle
- Install Postgresql
- Install Tcl
- Mail Transport Agents
- Monitoring Naviserver
- Nagios Monitoring
- NaviServer
- Next Steps After Installation, Debian Specific
- *nix operating system
- OpenACS compatibility matrix
- OpenACS Debian Install quicksheet
- OpenACS/dotLRN windows installer how to
- OpenACS/dotLRN Windows Installer Instructions
- OpenACS/.LRN for Debian
- OpenACS/.LRN for Ubuntu
- OpenACS Monitoring
- OpenACS Performance Tuning
- OpenACS Reference Platform
- OpenACS subsystem
- OpenACS system
- Oracle
- Oracle Notes
- Postgres 8.1.x to 9.1
- PostgreSQL
- PostgreSQL Administration
- PostgreSQL's Tsearch2
- Securing your system
- Source control
- Tcl
- Tcl Thread Library
- tDOM
- tDOM with OpenACS
- Testing with Selenium
- Testing with TCLWebtest
- Upgrade between PostgreSQL versions
- Upgrade from PostgreSQL 9.6 to 13.1
- Upgrade to OpenACS 5.10
- Upgrade to OpenACS 5.8
- Upgrade to OpenACS 5.9
- Vi as an OpenACS IDE
- ::xo::db Object Relational Database Interface
- XOTcl