yet another attempt to deal with ffmpeg seeks, fred name/color change
[goodguy/history.git] / cinelerra-5.1 / db / doc
1 Notice:
2   Fields and Table names are remapped to:
3     first char Upper case, the rest are lower case
4
5 The code generator (x.C) processes limited schema information and
6   creates code which operates a base class Db as schema describes.
7
8   x.C reads from stdin, and has 1 optional parameter (theDb class name)
9     comments are whitespace, form /*comment*/ or -- comment... <cr>
10     ./a.out < schema.txt <class_name=defaults to theDb>
11       this produces a source file s.C containing all
12       * table definitions in the form of: <Tbl>
13           constructed as:  Entity Tbl(db);
14       * default locators in the form of <tbl>
15           constructed as:  TblLoc tbl(Tbl);
16           <Tbl> = table name, first char capitalized.
17           <tbl> = table name, all lower case
18       * ikey_<Key_name> and rkey_<Key_name> class definitions
19       * key cmpr functions for ikey_<Key_name> and rkey_<Key_name>
20       * EntityObj functions: Allocate, Construct, Destruct, Deallocate;
21       * theDb class definition, with base class Db with
22           constructor and functions create, open, and close
23
24   x.C allowed input data as follow:
25     items in [] are optional
26
27 ** CREATE TABLE table;
28 * table = <table_name> ( <member> [, <member> ...] )
29 * member = <field_name> <dtype> [<xtype> ...]
30 * dtqual = ( [0-9...] ) | [UNSIGNED | SIGNED | ZEROFILL]
31 * dtype0 = BIT | TINYINT | SMALLINT | MEDIUMINT | INT | INTEGER | BIGINT |
32            REAL | DOUBLE | FLOAT | DECIMAL
33 * dtype1 = DATE | TIME | TIMESTAMP | YEAR |
34            CHAR | VARCHAR [BINARY] | BINARY | VARBINARY | BLOB | MEDIUMBLOB |
35            LONGBLOB | TINYTEXT | TEXT | MEDIUMTEXT | LONGTEXT | BOOL | BOOLEAN |
36            ENUM ( <enum_value> [, <enum_value> ...] )
37 * dtype = <dtype0> [<dtqual>] | <dtype1>
38 * xrefer = <table_name> ( <key_field> [, <key_field> ...] )
39    ON [DELETE | UPDATE] [RESTRICT | CASCADE | SET NULL | NO ACTION]
40 * def_int = [+|-][0-9...]
41 * def_dbl = <def_int>[.[0-9...]]
42 * def_str = '[notany(') | \any() ...]' | "[notany(") | \any() ...]"
43 * def_value = <def_str> | <def_int> | <def_dbl> | NULL
44 * xtype = [NOT] NULL | DEFAULT <def_value> | AUTO_INCREMENT |
45           UNIQUE [PRIMARY] [KEY] | PRIMARY [UNIQUE] [KEY] |
46           REFERENCES xrefer
47
48 ** CREATE online modifier INDEX index;
49 * index = <index_name> ON <table_name> ( <key_field> [, <key_field> ...] );
50 * online = [ONLINE | OFFLINE]
51 * modifier = [UNIQUE | FULLTEXT | SPATIAL]
52
53
54 note:  C++ type      Schema field type
55   unsigned char:     BOOLEAN, BIT, BINARY
56   [unsigned] char:   CHAR, TINYINT
57   [unsigned] short:  ENUM, SMALLINT
58   [unsigned] int:    DECIMAL, MEDIUMINT, INT, INTEGER
59   [unsigned] long:   BIGINT
60   double:            REAL, DOUBLE
61   float:             FLOAT
62   char[n]:           DATE[8], TIME[6], YEAR[4] TIMESTAMP[14], DATETIME[14]
63   char[]:            VARCHAR, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT
64   unsigned char[]:   VARBINARY, TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB
65   not implemented:   SET
66
67 examples:
68
69 CREATE TABLE user_newtalk (
70   user_id int NOT NULL default 0,
71   user_ip varbinary(40) NOT NULL default '',
72   user_last_timestamp varbinary(14) NULL default NULL
73 ) ;
74 CREATE INDEX un_user_id ON user_newtalk (user_id);
75 CREATE INDEX un_user_ip ON user_newtalk (user_ip);
76
77 CREATE TABLE text (
78   old_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
79   old_text mediumblob NOT NULL,
80   old_flags tinyblob NOT NULL
81 )  MAX_ROWS=10000000 AVG_ROW_LENGTH=10240;  (MAX_ROWS,AVG_ROW_LENGTH are ignored)
82
83
84
85 To initialize/open a db instance:
86
87 #include <cstdio>
88 #include "db.h"
89 #include "s.C"
90
91 theDb db;
92
93 int main(int ac, char **av)
94 {
95   if( db.create(dfn) ) {
96     fprintf(stderr,"create_db failed\n");
97     exit(1);
98   }
99   if( db.open(dfn) ) {
100     fprintf(stderr,"open failed\n");
101     exit(1);
102   }
103   return 0;
104 }
105
106
107 Normally, almost everything is done with Key classes and locators.
108 There is a default locator for every entity (lower case tbl) in theDb.
109   defined similar to:   Entity Tbl(db);  TblLoc tbl(Tbl);
110
111 Locators provide access to the record member fields:
112   Access is provided by the .member() function.
113   value = tbl.Field();  // read access
114   tbl.Field(value);     // write access
115   tbl.size_Field();     // size(value)
116   tbl._Field();         // addr(value)
117   tbl.Field(value,sz);  // write access to varObj/blob field
118   tbl.set_wr();         // mark dirty
119
120
121
122 To create database records:
123
124 void insert()
125 {
126   db.tbl.Allocate();      // allocates a Tbl record assigned to tbl locator
127   db.tbl.Field1(value1); // assignes values to new Tbl record fields
128   db.tbl.Field2(value2); // ...
129   db.tbl.Construct();     // runs theDb record constructor
130 }
131
132 the record constructor is normally generated by x.C and typically:
133   if_err( insertProhibit() );  // run consistancy checks
134   if_err( construct() );       // load id and reference
135   int id = this->id();
136   { rkey_Tbl_Key1 rkey(*this); // add all keys associated to new id
137     if_err( entity->index("Tbl_Key1")->Insert(rkey,&id) ); }
138   if_err( insertCascade() );   // run insert cascade functions
139   return 0;
140
141
142 To access database records:
143   The TblLoc::ikey_Field key classes use immediate data for key values
144   The TblLoc::rkey_Field key classes use the current record for key values
145
146 The Db::Key class provides:
147   int Find();                 // immedate ikey_ only
148   int Locate(int op=keyGE);   // immedate ikey_ and relative rkey_
149   int First();                // relative rkey_ only
150   int Last();                 // relative rkey_ only
151   int Next();                 // relative rkey_ only
152   int First(pgRef &pos);      // relative rkey_ only
153   int Next(pgRef &pos);       // relative rkey_ only
154
155 To Locate/Find a table record (= EntityObj), use:
156
157   theDb db;  db.open("/path/the.db");
158   int ret = TblLoc::ikey_Key1(db.tbl, key).Find();
159   if( ret != 0 ) printf(" not found, ret = %d\n",ret);
160   printf(" the record data is now %d\n", ++db.tbl.Data());
161   db.commit();
162   db.close();
163
164 ** NOTE: <key field parameters> will be automatically constructed from
165    basic types, but for varObj types they should be explicity constructed
166    as in:
167      int ret = TblLoc::ikey_Key1(db.tbl, TblObj::t_Key1Field1(key, ksz)).Find();
168
169 Locate may be called with op=keyLT,keyLE,keyEQ,keyGE,keyGT
170   the index will be positioned to the appropriate boundry
171   keyEQ is mapped to keyLE when used with Locate
172
173 First/Next have a default cursor position associated to the index.
174 First/Next may return/use a cursor position locator which may be
175   used if multiple simultainious cursor positions are needed.
176
177 To iterate use Locate/First to set the cursor at a table record
178   then use Next to iterate until need records are exhausted.
179
180   theDb db;  db.open("/path/the.db");
181   TblLoc::rkey_KeyField1 key1(db.tbl);
182   if( !(ret=key1.First()) ) do {
183     printf(" the record data is now %d\n", ++db.tbl.Data());
184   } while( !(ret=key1.Next()) );
185   db.commit();
186   db.close();
187
188
189
190 To delete database records:
191
192   theDb db;  db.open("/path/the.db");
193   while( !db.tbl.Last() ) {
194     db.tbl.Destruct();    // run theDb record destructor
195     db.tbl.Deallocate();  // release db storage assigned to db.tbl
196   }
197
198 the record destructor is normally generated by x.C and typically:
199   if_err( deleteProhibit() );   // run consistency checks
200   { rkey_Tbl_Key1 rkey(*this);  // remove all keys associated to id
201     if_err( entity->index("Tbl_Key1")->Delete(rkey) ); }
202   if_err( destruct() );         // delete id and reference
203   if_err( deleteCascade() );    // run delete cascade functions
204   return 0;
205
206
207 There are also "media" keys, which are bit field key records which
208 are organized by total "weight" = unsigned sum of bit fields.  The
209 weight is recursively subdefined in left/right subfields, so that
210 all of the key record is encoded.  This usually requires a little
211 over 3 times as much storage.  This kind of key can index audio/video
212 data (and others, biometric, dna, images...).  The key data can be:
213 built, recovered, and compared for both magnitude and error as sum
214 of squared/linear error.  The work on this not complete at this time.
215 to insert (8 bit fields):
216   int ksz = Db::mediaKey::byte_size(sz, 8);
217   uint8_t *key = db.Tbl._key1(ksz);
218   Db::mediaKey::build(key, dat, 8, sz);
219
220 to access (8 bit fields):
221   int ksz = Db::mediaKey::byte_size(len, 8);
222   uint8_t key[ksz];
223   Db::mediaKey::build(key,dat,8,len);
224   PrefixLoc::ikey_Prefix_key_data ikey(db.prefix, key);
225   if( (ret=ikey.Find()) != 0 ) {
226
227
228
229
230
231 Example:
232
233 Makefile:
234
235 CPPFLAGS := -Wall -ggdb $(CFLAGS)
236 LDFLAGS := 
237
238 all:    prog
239
240 clean:
241         rm -f *.o xsch prog
242
243 prog:   prog.o db.o
244         g++ -o $@ $(LDFLAGS) $+
245
246 s.C:    x.o sch.txt
247         g++ -o xsch x.o
248         ./xsch < sch.txt
249
250 db.o:   db.C db.h
251 prog.o: prog.C prog.h s.C db.h
252 x.o:    x.C
253
254
255 sch.txt:
256
257 CREATE TABLE a_tbl (
258   a_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
259   a_name varchar(255) binary NOT NULL default '',
260   a_data int
261 );
262 CREATE UNIQUE INDEX a_names ON a_tbl (a_name);
263 CREATE UNIQUE INDEX a_datum ON a_tbl (a_data);
264
265
266 prog.C:
267
268 #include <cstdio>
269 #include <stdlib.h>
270 #include <unistd.h>
271 #include <fcntl.h>
272
273 #include "db.h"
274 #include "s.C"
275
276 theDb db;
277
278 void chk(int ret, const char *msg)
279 {
280   fprintf(stderr,"fail %s = %d\n",msg,ret);
281   exit(1);
282 }
283
284 void insert(const char *nm, int dat)
285 {
286   chk( db.a_tbl.Allocate(),  "Allocate");
287   chk( db.a_tbl.A_name(nm),  "A_name(nm)");
288   chk( db.a_tbl.A_data(dat,  "A_data(dat)");
289   chk( db.a_tbl.Construct(), "Construct");
290 }
291
292 int main(int ac, char **av)
293 {
294   const char *dfn = ac > 1 ? av[1] : "the.db";
295   chk( db.create(dfn), "db.create");
296   chk( db.open(dfn), "db.open");
297
298   // insert some data
299   insert("a borrower", 321);
300   insert("nor lendor", 232);
301   insert("be", 123);
302
303   chk( db.commit(), "commit()");
304   chk( db.close(),  "close()");
305   chk( db.open(dfn, "db.reopen");
306
307   // lookup at datum using immedate key
308   int dat = 232;
309   A_tblLoc::ikey_A_datum ky(db.a_tbl,dat);
310   chk( ky.Find(), "ky.Find()");
311   printf("Found %d name %s\n",dat,db.a_tbl.A_name());
312
313   // look at datum using relative key
314   int ret = 0;
315   A_tblLoc::rkey_A_datum rky(db.a_tbl);
316   if( !(ret=rky.First()) ) do {
317     printf("Data %d name %s\n",db.a_tbl.A_data(),db.a_tbl.A_name());
318   } while( !(ret=rky.Next()) );
319   if( ret == Db::errNotFound ) ret = 0;
320   chk( ret, "datam");
321
322   // get cursor position using immediate key
323   A_tblLoc::ikey_A_names iky(db.a_tbl,"b");
324   if( !(ret=iky.Locate()) ) {
325     // switch to relative key
326     A_tblLoc::rkey_A_names rky(db.a_tbl);
327     do {
328       printf("Name %s data %d\n",db.a_tbl.A_name(),db.a_tbl.A_data());
329     } while( !(ret=rky.Next()) );
330   }
331   if( ret == Db::errNotFound ) ret = 0;
332   chk( ret, "names");
333   chk( db.commit(1), "commit(1)");
334   db.close();
335   return 0;
336 }
337
338
339 Traveling db:
340 only one process allowed write access, no readers allowed
341   all allowed read lock while not write locked
342 to access database, typically:
343 int resetDb(int rw)
344 {
345   int result = 0;
346   if( access("/path/t.db", F_OK) ) db->create("/path/t.db");
347   if( !result ) result = openDb(rw);
348   return result;
349 }
350 int openDb(int rw) { return db->access("/path/tdb.db", SHM_KEY, rw); }
351 void closeDb() { detachDb();  db->close(); }
352 void commitDb() { db->commit(); } // detaches
353 void undoDb() { db->undo(); } // detaches
354 int attachDb(int rw) { return db->attach(rw); }
355 int detachDb() { return db->detach(); }
356
357 typical session:
358 openDb();  detachDb();  ...
359 //typical read access
360 attachDb(); do_read(); detachDb(); ...
361 //typical write access
362 attachDb(1); do_write(); commitDb(); ...
363 closeDb();
364