window.manualConvertUnicodeToUTF8 = function (s)\n{\n var re=/[^\su0000-\su007F]/g ;\n return( s.replace( re, function( $0 ) { return( "&#" +\n$0.charCodeAt(0).toString() + ";" ) ; }));\n\n}
[[Introduction]]
\nfunction onClickToolbarCloseOthers(e) {\nif (!e) var e = window.event;\noldVal = config.options.chkAnimate;\nconfig.options.chkAnimate = false;\ncloseAllTiddlers();\nif(this.parentNode.id) {\nvar title = this.parentNode.id.substr(7);\ndisplayTiddler(e.target,title,0);\n}\nconfig.options.chkAnimate = oldVal;\n}\n\nfunction addCloseOthersButton(ignored, args) {\nvar theToolbar = document.getElementById("toolbar" + args[0]);\nif(theToolbar) {\nif(!args[1]) {\ncreateTiddlyButton(theToolbar, "close others", "close others", onClickToolbarCloseOthers);\ninsertSpacer(theToolbar);\n}\n}\n\nreturn args;\n}\n\nAspects.addAfter(this, "createTiddlerToolbar", addCloseOthersButton);
//Thanks to Roman Porotnikov\n//http:www.jroller.com/page/deep/20030701\n\n//NB this systemConfig needs to be evaluated before other ones \n//that use the Aspects so the name starts with "."\n//since they're loaded alphabetically\n//should really put it into the main source code, but\n//wanted to keep everything upgrade-proof\n\nAspects = new Object();\n\nAspects.addBefore = function(obj, fname, before) {\nvar oldFunc = obj[fname];\nobj[fname] = function() {\nreturn oldFunc.apply(this, before(arguments, oldFunc, this));\n};\n};\n\nAspects.addAfter = function(obj, fname, after) {\nvar oldFunc = obj[fname];\nobj[fname] = function() {\nreturn after(oldFunc.apply(this, arguments), arguments, oldFunc, this);\n};\n};\n\nAspects.addAround = function(obj, fname, around) {\nvar oldFunc = obj[fname];\nobj[fname] = function() {\nreturn around(arguments, oldFunc, this);\n};\n};
///////////////////////////////////////////////////////////////\n// Requires http://www.digitaldimsum.co.uk/#_.FunctionDecorator\n///////////////////////////////////////////////////////////////\nconfig.options.txtBackupDir = "backup";\nconfig.shadowTiddlers.AdvancedOptions += "\sn\sn Backup Subdirectory: <<option txtBackupDir>>\sn ";\n\nfunction alterBackupDir(args) {\n var path = args[0];\n var re = new RegExp("\s.[0-9]+\s.html");\n if (re.test(path)) {\n var backSlash = true;\n var dirPathPos = path.lastIndexOf("\s\s");\n if (dirPathPos == -1) {\n dirPathPos = path.lastIndexOf("/");\n backSlash = false;\n }\n var backupPath = path.substr(0,dirPathPos) + (backSlash ? "\s\s" : "/");\n backupPath += config.options.txtBackupDir + path.substr(dirPathPos, path.length - dirPathPos);\n \n args[0] = backupPath;\n }\n return args;\n}\n\nAspects.addBefore(this,"saveFile",alterBackupDir);\n
See [[TiddlyWiki.com|http://www.tiddlywiki.com]] for descriptions, examples, and tutorials on TiddlyWiki.\n\nIf you want to create your own TiddlyWiki page, you can start by saving a copy of [[this file|http://avweb.etxb.ericsson.se/~etxuwig/empty_tiddlywiki.html]].\n
RDBMS
A relational database layer on top of Mnesia
'Rdbms' is mainly a mnesia activity module for Mnesia that adds support for constraint checking.\n\nMnesia is a robust distributed DBMS, but it performs very little validation on the actual data. Basically, the only things that it does validate (apart from ensuring ACID properties, which is no small thing) is that the record tag and number of attributes are correct. There is no support for verifying the type of data, or indeed to check relations between different tables.\n\n'Rdbms' does this, in a way that is almost totally transparent to the Mnesia user. It supports definition and validation of type, bounds, access rights, and relational constraints.
This document describes the 'rdbms' add-on to Mnesia. I've decided to arrange it as a TiddlyWiki in order to attempt a [[User Guide]], [[Reference Manual]], [[design log]], and [[tutorials]] in one single document. We'll se how it goes.\n\nA good starting point is [[What is rdbms?]]\n
in ''rdbms_index''. For example, read-only file system tables would be difficult to index. If one were to allow "partially complete" indexes, one could allow ''update_on_read'' indexes. Basically, one would [[rebuild_index]] once, and then refresh a portion of the index every time an object is read. This will not guarantee that the index is up to date, but should keep it mostly accurate, as long as updates are reasonably rare.\n
In [[module rdbms_index_load]], there is code for creating an index table on the fly. We should perhaps have a function, ''rebuild_indexes'', that does the same thing on demand for existing indexes.
This module is a callback for the mnesia_schema:do_restore/1 function, which is used by [[module rdbms_index]] in order to (re-)build an index at runtime. The reason for doing it this way, is that normal writes are not allowed within a schema transaction (which, for various reasons, is probably a good thing.)
[[Data model]]\n\nThe following API functions exist in rdbms:\n- [[module rdbms]]\n- [[module rdbms_index]]\n- [[module rdbms_props]]\n- [[module rdbms_mailmerge]]\n- [[module rdbms_wsearch]]
''Rdbms'' metadata can be specified while creating tables, using the following functions in [[module rdbms]]:\n<<<\nrdbms:create_table(Name, Options) % where Options = [{K,V}], rdbms metadata given as {rdbms, Properties}\nrdbms:do_create_table(Name, Options) \n<<<\n\nand for existing tables using the following functions in [[module rdbms_props]]:\n\n<<<\nset_property(Tab, Key, Value)\ndo_set_property(Tab, Key, Value)\nset_global_type(Class, Name, Value)\ndo_set_global_type(Class, Name, Value)\n<<<\n\nThe following types of table metadata can be specified:\n- [[references]]\n- [[acl]]\n- [[verify]]\n- [[{typedef, Name}]]\n- [[{attr, Attr, Prop}]]\n
This defines an attribute property for the given table (or a global attribute property).\n\nFor a table property, ''Attr'' must refer to an existing attribute in the table, or to a "compound_attribute" (see below).\n\nThe following properties can be specified for table attributes:\n\n- ''type'' - see [[attribute types]]\n- ''required'' - ''true | false''\n- ''key_type'' - ''primary | secondary | none''\n- ''default'' - ''{'value', term()} | {'auto', {M, F}}'')
- [[rebuild_indexes]], [[update_on_read]]\n- [[optimize type checks]]\n- [[rdbms_rofs]]
There is some code in [[module rdbms_props]] that normalizes type definitions. Part of the purpose is to expand all typedefs, but another reason is to try to simplify the type expressions. Obviously, e.g. {list, {'or', [..., any]}} can be simplified to {list, any}, which means that the list elements do not 't have to be inspected. This code lacks sophistication (to say the least), and could be made much better.\n\nBTW, should {list, any} be read as "a non-empty list", or "any list, including nil"? I think I prefer the former, since we have no other good expression for non-empty list.
<<<\n''type'' = builtinType | complexType | altType\n''logicalType'' = {logicalOp, [type]} | {'not', type} | 'true' | 'false'\n''logicalOp'' = 'and' | 'or' | 'andalso' | 'orelse'\n''comType'' = {compOp, value}\n''compOp'' = '==' | '=/=' | '>' | '<' | '=<' | '>='\n''builtinType'' = 'atom' | 'string' | 'binary' | 'number' | 'integer' | 'float' | 'oid' | 'any' |\n 'list' | 'nil' | 'tuple' | 'function' | 'pid' | 'port' | 'reference'\n''complexType'' = tupleType | listType | enumType\n''tupleType'' = {'tuple', [type]}\n''listType'' = {'list', type}\n''enumType'' = {'enum', [value]}\n<<<\n\nSpecifically, ''{'and', []}'' and ''{'or',[]}'' are the same as ''no_type'', and \n- '''nil''' means the empty list\n- ''{'list', 'false'}'' is the same as '''nil'''\n- ''{'list', 'any'} and ''{'list', 'undefined'}'' both mean a non-empty list
The following types are supported by ''rdbms'':\n\n- ''undefined'' - specifically matches the value 'undefined'\n- ''no_type'' - is an internal representation for "no type has been defined". It cannot be set.\n- ''any'' - means specifically that any value is allowed.\n- ''oid'' - built-in type for use as globally unique identifier. See [[oid]]\n- Simple builtin types (''atom, string, binary, number, integer, float, oid, any, pid, port, reference, list, nil, tuple, function, boolean'')\n- The distinct types 'true' and 'false'\n- [[global type]] (''{type, typeRef}'', see TypeDefs)\n- [[complex type]] (tuples or lists)\n
This user guide covers the following topics\n- [[activating rdbms]]\n- [[specifying types]]\n- [[referential integrity]]\n- [[parameterized indexes]]\n- [[fragmented tables]]