>> % Connect to an SQLite database, turn on automated database schema building, >> % and turn on debugging to print all executed SQL statements. >> d=zdb('temp.sqlite', 'hot',true, 'dbg',true); SELECT name FROM sqlite_master WHERE type="table" AND name!="sqlite_sequence" UNION ALL SELECT name FROM sqlite_temp_master WHERE type="table" AND name!="sqlite_sequence" ORDER BY 1 PRAGMA journal_mode = MEMORY PRAGMA synchronous = OFF PRAGMA temp_store = 2 PRAGMA cache_size PRAGMA cache_size=20000 SELECT tbl_name,sql FROM sqlite_master WHERE type='table' AND sql LIKE "CREATE TABLE %" AND tbl_name='user' PRAGMA TABLE_INFO("user") SELECT tbl_name,sql FROM sqlite_master WHERE type='index' AND sql LIKE "CREATE %INDEX %" AND tbl_name='user'If you already have a pre-built database and you do not want ZozaniDB to not automatically change its schema, disable the hot option (or omit it; the default is off). Similarly, the default for the dbg option is off.
>> % Connect to an existing SQLite database, >> % turn off automated database schema building and turn off debugging. >> d=zdb('temp.sqlite');
>> d=zdb('mysql:host=localhost;dbname=somedatabase;user=myusername;pass=mypassword');ZozaniDB will automatically download the MySQL driver when it needs to. If this download fails or you want to manually load the driver, download the MySQL Java Connector. If you use the Windows installer, the Jar file will for example located at C:\Program Files (x86)\MySQL\MySQL Connector J\mysql-connector-java-5.1.34-bin.jar. If you use the platform independent file, unpack it and use its location below instead. In Matlab, run the following:
>> % Replace the path below if you saved the jar file to a different location. >> javaaddpath('C:\Program Files (x86)\MySQL\MySQL Connector J\mysql-connector-java-5.1.34-bin.jar');
>> % connect to the user table. >> % if you have d.hot=true, the table will be automatically created if it does not exist. >> t=d.table('user');
>> %You can drop previously created tables if you need to create them afresh. >> d.droptable('user'); DROP TABLE IF EXISTS "user" >> t=d.table('user'); CREATE TABLE IF NOT EXISTS "user"(id integer not null, PRIMARY KEY(id)) SELECT tbl_name,sql FROM sqlite_master WHERE type='table' AND sql LIKE "CREATE TABLE %" AND tbl_name='user' PRAGMA TABLE_INFO("user") SELECT tbl_name,sql FROM sqlite_master WHERE type='index' AND sql LIKE "CREATE %INDEX %" AND tbl_name='user' --- NOTICE: created table "user" >> % Or delete them all: >> d.dropalltables('force'); DROP TABLE IF EXISTS "user" >> %If the user already exists, you can use the shorthand dot operator to get the table. >> t=d.user; CREATE TABLE IF NOT EXISTS "user"(id integer not null, PRIMARY KEY(id)) SELECT tbl_name,sql FROM sqlite_master WHERE type='table' AND sql LIKE "CREATE TABLE %" AND tbl_name='user' PRAGMA TABLE_INFO("user") SELECT tbl_name,sql FROM sqlite_master WHERE type='index' AND sql LIKE "CREATE %INDEX %" AND tbl_name='user' --- NOTICE: created table "user"
>> t.insert(struct('name','ahmet')); BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 ALTER TABLE "user" RENAME TO "user_backup142" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase) DROP TABLE "user_backup142" COMMIT --- NOTICE: added field "user.name" INSERT INTO "user"("name") VALUES('ahmet') >> t.insert(struct('name',{'tom','jerry'})); INSERT INTO "user"("name") SELECT 'tom' AS "name" UNION ALL SELECT 'jerry'
>> %insert cell arrays. each row of cell arrays must have all fields of the >> %table. >> t.insert({100,'apple'}); INSERT INTO "user" VALUES(100,'apple')
By default, zdb will first try an insertion and if a uniqueness constraint violation happens, it will update that entry instead.
>> t.insert(struct('id',1,'name','jerry')); INSERT INTO "user"("id","name") VALUES(1,'jerry') --- ERROR:SQLITE:CONSTRAINT_PRIMARYKEY UNIQUE constraint failed: user.id --- stack: query.m:33, insert.m:84, func_runhtmlpublish.m:31 --- CAUSE: The sql statement was: INSERT INTO "user"("id","name") VALUES(1,'jerry') UPDATE "user" SET "name"='jerry' WHERE id=1
>> % To ignore all uniqueness constraint violation errors but just let us know when they happen: >> d.oninserterror='ignoreduplicates,echoduplicates'; >> t.insert({1,'orange'}); INSERT INTO "user" VALUES(1,'orange') --- ERROR:SQLITE:CONSTRAINT_PRIMARYKEY UNIQUE constraint failed: user.id --- stack: query.m:33, insert.m:84, func_runhtmlpublish.m:31 --- CAUSE: The sql statement was: INSERT INTO "user" VALUES(1,'orange')
>> % To ignore all insert errors (uniqueness constraints or any other errors), use: >> d.oninserterror='ignore,echo'; >> t.insert({1,'orange'}); INSERT INTO "user" VALUES(1,'orange') --- ERROR:SQLITE:CONSTRAINT_PRIMARYKEY UNIQUE constraint failed: user.id --- stack: query.m:33, insert.m:84, func_runhtmlpublish.m:31 --- CAUSE: The sql statement was: INSERT INTO "user" VALUES(1,'orange')
>> % To not ignore insert errors, use: >> d.oninserterror=''; >> t.insert({1,'orange'}); Error using sqlitemex UNIQUE constraint failed: user.id Error in zdb/query (line 33) ret{i}=sqlitemex(d.connect,sq); Error in dbtable/insert (line 86) else t.db.query(sql); end Error in func_runhtmlpublish (line 31) cmdout=evalc(cmd); Caused by: The sql statement was: INSERT INTO "user" VALUES(1,'orange')Instead of relying on the zdb.oninserterror property for all insertions, you can also call the insertorupdate() method of the dbtable object for individual insertion operations.
>> t.insertorupdate(struct('id',1,'name','orange')); INSERT INTO "user"("id","name") VALUES(1,'orange') UPDATE "user" SET "name"='orange' WHERE id=1
>> % get the entry with name='ahmet'. >> t.getby(struct('name','ahmet')) SELECT * FROM "user" WHERE name='ahmet' ans = 0x1 empty struct array with fields: id name >> % get name='ahmet' OR name='tom'. >> t.getby(struct('name',{{'ahmet','tom'}})) SELECT * FROM "user" WHERE name IN ('ahmet','tom') ans = struct with fields: id: 2 name: 'tom' >> % you can also provide full sql statements, but we recommend using >> % zdb.query() for this instead. >> t.getby('SELECT * FROM user WHERE name like "%met"') SELECT * FROM user WHERE name like "%met" ans = 0x1 empty struct array with fields: id name >> %use getall() to fetch the entire table. >> t.getall() SELECT * FROM "user" WHERE 1 ans = 4x1 struct array with fields: id name >> %use dumpall() to view the entire table in a fixed-width format. >> t.dumpall() SELECT * FROM "user" WHERE 1 id name === ====== 1 orange 2 tom 3 jerry 100 apple >> % getcolby() returns a single column. The result will be a numerical column >> % vector if the entries are numerical; otherwise it will be a cell array. >> % Here, we are getting the name column as a cell array. >> t.getcolby('(id<3)','name') SELECT "name" FROM "user" WHERE (id<3) ans = 2x1 cell array {'orange'} {'tom' } >> % getrowby() gets a single row. >> t.getrowby('(id=2)') SELECT * FROM "user" WHERE (id=2) LIMIT 0,1 ans = struct with fields: id: 2 name: 'tom' >> % getrowbyid(x) is a short hand for getrowby(struct('id',x)) >> t.getrowbyid(2) SELECT * FROM "user" WHERE id=2 LIMIT 0,1 ans = struct with fields: id: 2 name: 'tom' >> % getcol() gets a column from the entire table. Below, we get the names of all >> % entries in the user table. >> t.getcol('name') SELECT "name" FROM "user" WHERE 1 ans = 4x1 cell array {'orange'} {'tom' } {'jerry' } {'apple' } >> % getfirstrow() gets a the first row of the table. getfirstrow() is a quick >> % way of examining the available fields and data types of a table. >> t.getfirstrow() SELECT * FROM "user" WHERE 1 LIMIT 0,1 ans = struct with fields: id: 1 name: 'orange' >> % getnrows() gets the first n rows. >> t.getnrows(2) SELECT * FROM "user" WHERE 1 LIMIT 0,2 ans = 2x1 struct array with fields: id name >> % You can specify a starting position for getting n rows. The example below >> % will get 1 row (first argument) starting at position 2 (second argument). >> % Note that the first entry of the database is located at position 0. >> t.getnrows(1,2) SELECT * FROM "user" WHERE 1 LIMIT 2,1 ans = struct with fields: id: 3 name: 'jerry'
>> e=t.findrowbyid(2,'id') SELECT "id" FROM "user" WHERE id=2 LIMIT 0,1 e = dbentity: user 1 entries. id: 2 >> % Notice above that e.name is not in the entity, but it will be fetched when you >> % first access it. >> e.name SELECT "name" FROM "user" WHERE id=2 LIMIT 0,1 ans = 'tom' >> % You can change the dbentity objects just like you change a struct's values. >> e.name='adam'; >> % Note that your changes are not saved into the database right away. The changes >> % will be saved when the object is removed from memory, allowing you to make >> % more than one change to the object before the data is saved to the database. >> clear e UPDATE "user" SET "name"='adam' WHERE id=2 >> % You can also explicitly have the object update itself to the database by >> % calling its save() method. >> e=t.findrowbyid(2,'id'); SELECT "id" FROM "user" WHERE id=2 LIMIT 0,1 >> e.name='ahmet'; >> e.save; UPDATE "user" SET "name"='ahmet' WHERE id=2Below are additional examples (similar to the get*() functions above) that construct dbentity objects.
>> t.findby(struct('name',{{'ahmet','tom'}})) SELECT * FROM "user" WHERE name IN ('ahmet','tom') ans = dbentity: user 1 entries. id: 2 name: 'ahmet' >> t.findby('SELECT * FROM user WHERE name like "%met"') SELECT * FROM user WHERE name like "%met" ans = dbentity: user 1 entries. id: 2 name: 'ahmet' >> t.findall() SELECT * FROM "user" WHERE 1 ans = dbentity: user Fields: id,name 4 entries. >> t.findrowby('(id=2)') SELECT * FROM "user" WHERE (id=2) LIMIT 0,1 ans = dbentity: user 1 entries. id: 2 name: 'ahmet' >> t.findfirstrow() SELECT * FROM "user" WHERE 1 LIMIT 0,1 ans = dbentity: user 1 entries. id: 1 name: 'orange' >> t.findnrows(2) SELECT * FROM "user" WHERE 1 LIMIT 0,2 ans = dbentity: user Fields: id,name 2 entries. >> t.findnrows(1,2) SELECT * FROM "user" WHERE 1 LIMIT 2,1 ans = dbentity: user 1 entries. id: 3 name: 'jerry'
>> % change the datatype of the info field to yaml datatype. >> t.changefieldtypeifnot('info','yaml'); BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 ALTER TABLE "user" RENAME TO "user_backup951" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase, "info" text COLLATE nocase) INSERT INTO "user" SELECT "id","name",null FROM "user_backup951" DROP TABLE "user_backup951" COMMIT >> e=t.findrowbyid(2,'id') SELECT "id" FROM "user" WHERE id=2 LIMIT 0,1 e = dbentity: user 1 entries. id: 2 >> % Now you can set the value of the info field to complex data. >> e.info=struct('age',34,'height',5.10,'weight',175); >> % when the entity is saved, ZozaniDB will automatically convert the data into >> % a yaml string before storing it into the database. >> e.save UPDATE "user" SET "info"='age: 34 height: 5.1 weight: 175' WHERE id=2 >> % Conversely, ZozaniDB will restore the complex data when it creates the >> % dbentity from a query. >> t.findrowbyid(2,'id').info SELECT "id" FROM "user" WHERE id=2 LIMIT 0,1 SELECT "info" FROM "user" WHERE id=2 LIMIT 0,1 ans = struct with fields: age: 34 height: 5.1000 weight: 175 >> % Note that the decoding is only done when you use the find*() methods to created >> % object. The get*() methods will return the raw strings, without decoding them. >> info=t.getonebyid(2,'info') SELECT "info" FROM "user" WHERE id=2 LIMIT 0,1 info = 'age: 34 height: 5.1 weight: 175' >> whos('info') Name Size Bytes Class Attributes info 1x31 62 char
>> % drop a field >> t.dropfield('info'); BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 ALTER TABLE "user" RENAME TO "user_backup755" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase) INSERT INTO "user" SELECT "id","name" FROM "user_backup755" DROP TABLE "user_backup755" COMMIT >> % add a new field >> t.addfield('email','type','integer') BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 ALTER TABLE "user" RENAME TO "user_backup499" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase, "email" integer) INSERT INTO "user" SELECT "id","name",null FROM "user_backup499" DROP TABLE "user_backup499" COMMIT ans = dbtable: user dbfields: id, name, email >> t.addfield('age'); BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 ALTER TABLE "user" RENAME TO "user_backup256" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase, "email" integer, "age" integer) INSERT INTO "user" SELECT "id","name","email",null FROM "user_backup256" DROP TABLE "user_backup256" COMMIT >> % change the type or attributes of an existing field >> t.changefield('age','type','decimal'); BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 ALTER TABLE "user" RENAME TO "user_backup139" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase, "email" integer, "age" real) INSERT INTO "user" SELECT "id","name","email","age" FROM "user_backup139" DROP TABLE "user_backup139" COMMIT >> % changefieldtype(...) is a short hand for changefield('type',...) >> t.changefieldtype('email','string','length',32); BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 ALTER TABLE "user" RENAME TO "user_backup244" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase, "email" text(32) COLLATE nocase, "age" real) INSERT INTO "user" SELECT "id","name","email","age" FROM "user_backup244" DROP TABLE "user_backup244" COMMIT >> % you would usually need to set a uniqueness constraint, to prevent duplicate rows. >> t.adduniqueindexifnotexists('name,email'); CREATE UNIQUE INDEX "user_name_email_idx" ON "user"("name","email") >> % create an index on a field, to speed up queries that check values in this column. >> t.addindex('email') CREATE INDEX "user_email_idx" ON "user"("email") ans = dbtable: user dbfields: id, name, email, age >> % You can add/remove a field in the list of primary keys, to generate composite >> % primary keys. >> % An autoincrement key implies non-composite primary key, so you need to remove >> % autoincrement before you can generate a composite primary key. >> t.changefield('id','autoincrement',false); BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 DROP INDEX IF EXISTS "user_name_email_idx" DROP INDEX IF EXISTS "user_email_idx" ALTER TABLE "user" RENAME TO "user_backup586" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase, "email" text(32) COLLATE nocase, "age" real)\nCREATE INDEX IF NOT EXISTS "user_email_idx" ON "user"("email")\nCREATE UNIQUE INDEX IF NOT EXISTS "user_name_email_idx" ON "user"("name","email") INSERT INTO "user" SELECT "id","name","email","age" FROM "user_backup586" DROP TABLE "user_backup586" COMMIT >> t.addprimarykey('name'); %this will make (id,name) pair the new composite primary key. BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 DROP INDEX IF EXISTS "user_name_email_idx" DROP INDEX IF EXISTS "user_email_idx" ALTER TABLE "user" RENAME TO "user_backup758" CREATE TABLE "user"( "id" integer, "name" text(5) COLLATE nocase, "email" text(32) COLLATE nocase, "age" real, PRIMARY KEY("id","name"))\nCREATE INDEX IF NOT EXISTS "user_email_idx" ON "user"("email")\nCREATE UNIQUE INDEX IF NOT EXISTS "user_name_email_idx" ON "user"("name","email") INSERT INTO "user" SELECT "id","name","email","age" FROM "user_backup758" DROP TABLE "user_backup758" COMMIT >> % Change the primary key (existing values in this column should be unique). >> t.setprimarykey('id'); BEGIN TRANSACTION SELECT count(*) FROM "user" WHERE 1 LIMIT 0,1 DROP INDEX IF EXISTS "user_name_email_idx" DROP INDEX IF EXISTS "user_email_idx" ALTER TABLE "user" RENAME TO "user_backup531" CREATE TABLE "user"( "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" text(5) COLLATE nocase, "email" text(32) COLLATE nocase, "age" real)\nCREATE INDEX IF NOT EXISTS "user_email_idx" ON "user"("email")\nCREATE UNIQUE INDEX IF NOT EXISTS "user_name_email_idx" ON "user"("name","email") INSERT INTO "user" SELECT "id","name","email","age" FROM "user_backup531" DROP TABLE "user_backup531" COMMIT
>> % Results of the query are returned as structs. >> d.query('select * FROM user') select * FROM user ans = 4x1 struct array with fields: id name email age >> % You can use question marks to fill values into the sql statement; >> % ZozaniDB will escape the string and wrap them with proper quoting. >> % You can think about this functionality similar to Matlab's fprintf() >> % function, but instead of the % symbol, the entries are specified >> % with one of the ?, ??, ??? markers: >> % * ? is replaced with quoted value. >> % * ?? is replaced with quoted field. use this as placeholder for table and field names. >> % * ??? is replaced with the provided string, without any change. >> d.query('select * FROM ?? WHERE name=? AND ???', 'user', 'ahmet', 'id<3') select * FROM "user" WHERE name='ahmet' AND id<3 ans = struct with fields: id: 2 name: 'ahmet' email: [] age: [] >> % If you want to construct queries without executing them, use zdb.fillquery(). >> d.fillquery('select * FROM ?? WHERE name=? AND ???','user','ahmet','id<3') ans = 'select * FROM "user" WHERE name='ahmet' AND id<3' >> d.fillquery('select * FROM ?? WHERE name=? AND ???','user',5,'id<3') ans = 'select * FROM "user" WHERE name=5 AND id<3'
>> % d.whereclause() is useful for constructing the criteria for the selection >> % statements. The input to this method can be strings, structs, and cells. >> % Multiple values (given as cell array) for the same field are OR'ed, whereas >> % different fields are AND'ed. >> d.whereclause(struct('id',3)) WHERE id=3 >> d.whereclause(struct('id',{{3,5}})) WHERE id IN (3,5) >> d.whereclause(struct('id',{{3,5}},'name',{{'tom','jerry'}})) WHERE id IN (3,5) AND name IN ('tom','jerry') >> d.whereclause(struct('id',3,'name',{{'tom','jerry'}},'lastname','sacan')) WHERE id=3 AND name IN ('tom','jerry') AND lastname='sacan' >> d.whereclause({'id=3','age=32',struct('name','ahmet')}) WHERE id=3 AND age=32 AND name='ahmet' >> d.whereclause({'id=3','age=32',struct('name','ahmet','lastname','sacan')}) WHERE id=3 AND age=32 AND (name='ahmet' AND lastname='sacan') >> % If you want to provide your own criteria in a struct, mixed with other fields >> % and values, use 'X___1','X___2',etc. as fieldnames for your criteria. >> d.whereclause(struct('name','ahmet','X___1','lastname LIKE "saca%"')) WHERE name='ahmet' AND lastname LIKE "saca%" >> % The second argument to whereclause() specifies whether we prepend the >> % string with 'WHERE'. >> d.whereclause(struct('id',3),false) id=3 >> d.whereclause(struct('id',{{3,5}},'name',{{'tom','jerry'}}) ,false) id IN (3,5) AND name IN ('tom','jerry')
>> % insert and update clauses can be constructed similarly. >> d.insertclause(struct('id',3,'name','ahmet','lastname','sacan')) VALUES (3,'ahmet','sacan') >> d.insertclause({3,'ahmet','sacan'}) VALUES (3,'ahmet','sacan') >> d.updateclause(struct('id',3,'name','ahmet','lastname','sacan')) SET "id"=3,"name"='ahmet',"lastname"='sacan'
Associations become useful for navigating across different tables using the dbentity object properties. If you want to use entity relationships, you need to turn on withrel property when connecting to the database. For existing databases, ZozaniDB automatically determines entity-relationships across multiple tables by analyzing the field names, datatypes, primary keys, and uniqueness constraints. withrel=1 turns on only direct relationships; if you want to also have ZozaniDB detect transitive relationships, use withrel=2. ZozaniDB uses shortest-path in the relationship graph to set transitive relationships.
You can create associations between tables using zdb.addmanytoone/addmanytomany/addonetoone methods. You need to provide the names of the tables being associated. The fieldnames will be automatically determined with an '_id' postfix, e.g., "tablex_id". Keep zdb.hot=true so that the fields and join tables can be automatically created in the database.
In the example below, we link users and cars.
>> d=zdb('temp.sqlite','hot',true,'dbg',false, 'withrel',1); >> % Create the tables and link them with manytomany relationship. >> d.table('user'); >> d.table('car'); --- NOTICE: created table "car" >> d.addmanytomany('user','car'); >> % Let's fill in some example data. >> d.table('user').insertorupdate(struct('id',{50,60,70},'name',{'agent50','agent60','agent70'})); >> d.table('car').insertorupdate(struct('id',{5,10,15,20},'name',{'bmw','mercedes','honda','toyota'})); --- NOTICE: added field "car.name" >> d.table('user_car').insertorupdate(struct('user_id',50,'car_id',{5 10})); >> d.table('user_car').insertorupdate(struct('user_id',60,'car_id',{10 20})); >> d.table('user_car').insertorupdate(struct('user_id',70,'car_id',{5 15})); >> % Now, a user dbentity object will be able to get its respective car(s). >> % Let's create a dbentity object for agent50. >> e=d.table('user').findby(struct('name','agent50')) e = dbentity: user Associations: car: manyToMany:car 1 entries. id: 50 name: 'agent50' email: [] age: [] >> % Let's get the car(s) for this user. Notice that ZozaniDB constructs an SQL >> % join query to link the tables. The result is again a dbentity object, now >> % representing the cars. >> f=e.car f = dbentity: car Associations: user: manyToMany:user Fields: id,name 2 entries. >> % Use the dump method to view the data. >> f.dump id name == ======== 5 bmw 10 mercedes >> % or get an individual field. >> f.name ans = 1x2 cell array {'bmw'} {'mercedes'} >> % We can repeat the same exercise starting from a car and getting all the users >> % associated with that car. >> d.table('car').findby(struct('name','bmw')).user.dump id name email age == ======= ===== === 50 agent50 70 agent70
Behaviors are setup during zdb.expandmodels(), which is executed when you connect to a database. These behaviors register themselves into onbeforeinsert, onafterinsert, e.g., table events. Note that any behavior you attache to the tables would be lost when the database model is regenerated from the database system. If you want behaviors to persist, zdb.modelpatchfile is a good place to specify them.
In the example below, we attach a timestamping behavior, such that whenever a new entry is inserted or an existing entry is updated, we automatically set the timestamps for that entry.
>> t=d.user; >> % Add the timestampeable_demo class. ZozaniDB will look for a class with the >> % name 'db[behaviorname]' >> t.addbehavior('timestampable_demo'); >> % Inserting a new table will automaticall call timestampable_demo.onbeforeinsert() >> % method, which will add the current time to the entry being inserted. >> t.insert(struct('id',55,'name','apple')); --- NOTICE: added field "user.created" --- NOTICE: added field "user.modified" >> t.getrowby(struct('id',55)) ans = struct with fields: id: 55 name: 'apple' email: [] age: [] created: '18-12-21 12:59:45' modified: '18-12-21 12:59:45' >> t.update(struct('id',55,'name','orange')); >> t.getrowby(struct('id',55)) ans = struct with fields: id: 55 name: 'orange' email: [] age: [] created: '18-12-21 12:59:45' modified: '18-12-21 12:59:45'
>> % Connect to the database as follows when you need to perform many inserts. >> d=zdb('temp.sqlite','hot',true,'fastmode',true,'dbg',false); >> % If you already have the table schema setup, you may want to set d.hot=false. >> % Also set d.dbg=false if you don't want to see the debugging messages.
In the example below, we load a tab file into a new table.
>> % Let's use Table 12 available at: https://elifesciences.org/articles/35471/figures >> % We use maxlines=10 for demonstration purposes. Don't specify maxlines if you want >> % to load the entire file. >> % We use reset=1, so that the table (if already present) is emptied before we load it. >> d.loadtabfile('goenrichment','https://elifesciences.org/download/aHR0cHM6Ly9jZG4uZWxpZmVzY2llbmNlcy5vcmcvYXJ0aWNsZXMvMzU0NzEvZWxpZmUtMzU0NzEtZGF0YTEyLXYyLnhsc3g=/elife-35471-data12-v2.xlsx?_hash=o1Ew%2BslRkaIhjvGAPrVHbAcYlBlcmJQSgocT6EdOxVU%3D','maxlines',10,'reset',true); --- NOTICE: added field "goenrichment.annotated" --- NOTICE: added field "goenrichment.significant" --- NOTICE: added field "goenrichment.expected" >> d.goenrichment.dumpall id goid term pvalue annotated significant expected == ========== =========================================================== ======= ========= =========== ======== 1 GO:0006357 regulation of transcription from RNA polymerase II promoter 3.7e-09 457 19 3.99 2 GO:0006355 regulation of transcription, DNA-templated 7.8e-09 719 23 6.27 3 GO:1903506 regulation of nucleic acid-templated transcription 8e-09 720 23 6.28 4 GO:2001141 regulation of RNA biosynthetic process 8e-09 720 23 6.28 5 GO:0051252 regulation of RNA metabolic process 1.3e-08 737 23 6.43 6 GO:0006351 transcription, DNA-templated 3.6e-08 778 23 6.79 7 GO:0006366 transcription from RNA polymerase II promoter 3.6e-08 524 19 4.57 8 GO:0097659 nucleic acid-templated transcription 3.7e-08 779 23 6.8 9 GO:0032774 RNA biosynthetic process 4e-08 783 23 6.83
>> % If you don't want to load all the columns, use selectfields to specify a subset. >> d.loadtabfile('goenrichment2','https://elifesciences.org/download/aHR0cHM6Ly9jZG4uZWxpZmVzY2llbmNlcy5vcmcvYXJ0aWNsZXMvMzU0NzEvZWxpZmUtMzU0NzEtZGF0YTEyLXYyLnhsc3g=/elife-35471-data12-v2.xlsx?_hash=o1Ew%2BslRkaIhjvGAPrVHbAcYlBlcmJQSgocT6EdOxVU%3D','maxlines',10,'reset',true, 'selectfields',{'GO.ID','Term','pValue'}); --- NOTICE: created table "goenrichment2" --- NOTICE: added field "goenrichment2.goid" --- NOTICE: added field "goenrichment2.term" --- NOTICE: added field "goenrichment2.pvalue" >> d.goenrichment2.dumpall id goid term pvalue == ========== =========================================================== ======= 1 GO:0006357 regulation of transcription from RNA polymerase II promoter 3.7e-09 2 GO:0006355 regulation of transcription, DNA-templated 7.8e-09 3 GO:1903506 regulation of nucleic acid-templated transcription 8e-09 4 GO:2001141 regulation of RNA biosynthetic process 8e-09 5 GO:0051252 regulation of RNA metabolic process 1.3e-08 6 GO:0006351 transcription, DNA-templated 3.6e-08 7 GO:0006366 transcription from RNA polymerase II promoter 3.6e-08 8 GO:0097659 nucleic acid-templated transcription 3.7e-08 9 GO:0032774 RNA biosynthetic process 4e-08