Integrated unstructured database

Web.dev.app includes an integrated unstructured database (IUDB) which can be used to store any amount of unstructured data in a simple and efficient way. var db = dev.db.Database.create ("sample_db"); db.data.sample = { my_array: ["very", { deep: "stuff" }] }; db.attach(); db.commit();

Anything added to the database_instance.data object will become part of the database when attach() is called. It then gets saved to disk by commit(). Later, it can be retrieved from the database... var db = dev.db.Database.open ("sample_db"); console.log (db.data.sample);

In the debug console, sample.my_array appears as unloaded db object. The script engine knows it is a database object and will automatically load it from disk when required... var db = dev.db.Database.open ("sample_db"); console.log (db.data.sample.my_array[1].deep); // "stuff"

Database values are also easy to change... db.data.sample.my_array[1].deep = "other stuff"; db.commit();

If the new value is an object then it will also need to be attached.

Web.dev.app's built-in databases can currently store Number, String, Boolean, Object, Array, Set, Map, Date, RegExp, null and undefined. Each object is stored separately. Numbers, strings and booleans are stored with the object that owns them. Each object is only loaded when required by a script. Only objects that change are saved to disk during a commit. Objects that are no longer attached to the database_instance.data object or any of its deep properties will be automatically removed from the database. No circular or diamond references are permitted, although future versions may allow them.

A database can only be accessed by one thread at a time. A thread will lock a database when opening it or when lock() is called. It remains locked until the script finishes or unlock() is called. Competing threads wait for a database to be unlocked before locking it themselves. A database remains open in memory and ready to be locked again until the close() method is called or the app shuts down.

This database was designed for A.C.I.D. compliance. If there is a problem during the commit then either no changes are made, or the commit will be attempted again next time the database is opened. Future versions will support encryption. Database files have no size limit and future versions may allow spanning across multiple disks. ACID compliance has not been tested.

Methods of the dev.db.Database constructor

If no filename folder is given then the database will be stored in the app's private data folder.

dev.db.Database.close (filename)

dev.db.Database.create (filename)

dev.db.Database.delete (filename)

dev.db.Database.exists (filename)

dev.db.Database.open (filename)

Properties and methods of a Database instance

database_instance.data

database_instance.name

database_instance.version


database_instance.attach ([optional_object])

database_instance.clone (object)

database_instance.commit ()

database_instance.detach (object)

database_instance.lock ()

database_instance.restore (object)

database_instance.unlock ()

Example

The following database keeps a list of new users which can be accepted to become old users. Each new user is given an array of random tokens. As users are moved from the new list into the old list, their token array must be detached from new_users and re-attached to old_users. Their username is not an object and does not need attaching. <ul> <button onclick='AddNewUser()'>Add new user</button> <button onclick='AcceptNewUsers()'>Accept new users</button> </ul> <ul id='new_user_list'></ul> <ul id='old_user_list'></ul> <script> var db, DB = dev.db.Database; if (DB.exists ("userbase")) db = DB.open ("userbase"); else CreateDatabase(); ShowData(); function CreateDatabase (){ db = DB.create ("userbase"); db.data.users = { user_count: 0, new_users: new Map, old_users: new Map }; db.attach(); db.commit();} function AddNewUser (){ db.lock(); var name = "User " + ++db.data.users.user_count; db.data.users.new_users.set (name, RandomTokens()); db.attach (db.data.users.new_users); db.commit(); ShowData();} function AcceptNewUsers (){ db.lock(); db.data.users.new_users.forEach (function (tokens, user_id){ db.detach (tokens); db.data.users.old_users.set (user_id, tokens); db.attach (tokens);}); db.data.users.new_users.clear(); db.commit(); ShowData();} function ShowData (){ db.lock(); ShowUsers (db.data.users.new_users, new_user_list, 'New users'); ShowUsers (db.data.users.old_users, old_user_list, 'Old users');} function ShowUsers (map, ul, head){ var html = "<p><b>" + head + '</b></p>'; map.forEach (function (tokens, user_id){ html += "<li>" + user_id + ": " + tokens.join (', ');}); ul.innerHTML = html;} function MakeToken (){ return Math.floor (Math.random() * 1e8).toString(36);} function RandomTokens (){ return [MakeToken(), MakeToken(), MakeToken()];} </script>