1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
|
<HTML><HEAD>
<TITLE>MetaKit for Python</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF"><A NAME="top"></A>
<A HREF="http://www.python.org/"><IMG SRC="python.gif" WIDTH="87" HEIGHT="24" BORDER=0 align=left></A>
<A HREF="http://www.equi4.com/"><IMG SRC="e4s.gif" vspace=3 WIDTH="97" HEIGHT="35" BORDER=0 align=right></A>
<CENTER>
<H2>MetaKit for Python</H2>
<I>The structured database which fits in the palm of your hand</I>
<P>
[ <A HREF="#Terminology">Terminology</A>
| <A HREF="#inst">Installation</A>
| <A HREF="#start">Getting started</A>
| <A HREF="#ref">Mk4py Reference</A> ]
</CENTER>
<P>
<B>Buzzwords</B> - <A HREF=".">MetaKit</A> is an embeddable database which runs on Unix, Windows, Macintosh, and other platforms. It lets you build applications which store their data efficiently, in a portable way, and which will not need a complex runtime installation. In terms of the data model, MetaKit takes the middle ground between RDBMS, OODBMS, and flat-file databases - yet it is quite different from each of them.
<P>
<B>Technology</B> - Everything is stored variable-sized yet with efficient positional row access. Changing an existing datafile structure is as simple as re-opening it with that new structure. All changes are transacted. You can mix and match software written in C++, Python, and Tcl. Things can't get much more flexible...
<P>
<B>Python</B> - The extension for <A HREF="http://www.python.org/">Python</A> is called "Mk4py". It provides a lower-level API for the Metakit C++ core extension than an earlier version of this interface, and uses <A HREF="http://starship.python.net/crew/gmcm/scxx.html">SCXX</A> by Gordon McMillan as C++ glue interface.
<P>
<B>Mk4py 2.4.3</B> - is a final/production release. The <A HREF=".">homepage</A> points to a download area with pre-compiled shared libraries for Unix, Windows, and Macintosh. The MetaKit source distribution includes this documentation, the Mk4py C++ source code, a "MkMemoIO.py" class which provides efficient and fail-safe I/O (therefore also pickling) using MetaKit memo fields, and a few more goodies.
<P>
<B>Changes since 2.01</B> - the MK core has changed substantially:
<UL>
<li>New commit-aside and commit-extend modes (see storage objects below)
<li>Performance improvements, mostly due to a much more scalable file format
<li>The "M" (memo) datatype is gone, use "B" instead, it now handles huge items
<li>Internal changes to take advantage of the hash/ordered/blocked viewers
<li>Mk4py members storage, view, and property are now lower-case
<li>Added Mk4py.version (currently the string "2.4.3")
<li>Added "metakit.py" as new main wrapper, use as "import metakit"
</UL>
<P>
<B>License and support</B> - MetaKit 2 and up are distributed under the liberal
X/MIT-style open source license. Commercial support is available through an Enterprise License. See the <A HREF="license.html">license</A> page for details.
<P>
<B>Credits</B> - Are due to Gordon McMillan for not stopping at the original Mk4py and coming up with a more Pythonic interface, and to Christian Tismer for pushing Mk4py way beyond its design goals. Also to GvR and the Python community for taking scripting to such fascinating heights...
<P>
<P>
<B>Updates</B> - The latest version of this document is at
<a href="http://www.equi4.com/metakit/python.html">http://www.equi4.com/metakit/python.html</a>
<A name="Terminology"><HR size=1></A><H2>Terminology</H2>
There are several ways to say the same thing, depending on where you're
coming from. For example, the terms <I>table</I>, <I>list</I>, <I>collection</I>,
<I>array</I>, <I>sequence</I>, and <I>vector</I> all
denote a more or less similar concept.
To help avoid confusion, MetaKit uses a simple
(but hopefully precise) terminology.
<P>
The terms adopted by MetaKit can be summarized as follows:
<P>
<UL>
<LI>A <B>view</B> is an indexable collection of <B>rows</B>
(a <I>table</I> of <I>records</I>, an <I>array</I> of <I>elements</I>).
<LI>An <B>index</B> is a position in a <I>view</I>, used to specify a <I>row</I>
(the first row is at index zero).
<LI>Each view has an ordered
set of <B>properties</B>, used to refer to the data values of each row.
<LI>In MetaKit, each (<I>view</I>, <I>index</I>, <I>property</I>) combination denotes
a single data value.
<LI>A different way to describe this combination would be:
(<I>matrix</I>, <I>row-index</I>, <I>column-id</I>).
<LI>Data values can be strings, numeric, untyped data,
or a nested view, called a <B>subview</B>.
</UL>
<P>
A few more comments about the semantics of MetaKit:
<P>
<UL>
<LI>Views are <I>homogenous</I>: each row in a view contains the same type of
information.
<LI>This also implies that all subviews within the same view always
have the same structure.
<LI>Rows are either part of a view on file, or <I>temporary</I> (gone
when no longer referenced).
</UL>
<P>
<A NAME="inst"><HR size=1></A><H2>Installation</H2>
<OL>
<LI>Download the latest version from <A HREF="http://www.equi4.com/pub/download.html">http://www.equi4.com/pub/download.html</A>
<LI>On Unix, rename the appropriate compiled extension to "Mk4py.so" (on Win/Mac, use the corresponding file)
<LI>Place the Mk4py extension as well as the "metakit.py" wrapper somewhere on Python's module search path, <br> such as in the site-packages directory (or just leave it in ".")
<LI>Do a small test, by running "demo.py". If all is well, you should get some self-explanatory output
</OL>
<P>
<A NAME="start"><HR size=1></A><H2>Getting started</H2>
Create a database:
<BLOCKQUOTE><PRE>import metakit
db = metakit.storage("datafile.mk",1)</PRE></BLOCKQUOTE>
Create a view (this is the MetaKit term for "table"):
<BLOCKQUOTE><PRE>vw = db.getas("people[first:S,last:S,shoesize:I]")</PRE></BLOCKQUOTE>
Add two rows (this is the MetaKit term for "record"):
<BLOCKQUOTE><PRE>vw.append(first='John',last='Lennon',shoesize=44)
vw.append(first='Flash',last='Gordon',shoesize=42)</PRE></BLOCKQUOTE>
Commit the changes to file:
<BLOCKQUOTE><PRE>db.commit()</PRE></BLOCKQUOTE>
Show a list of all people:
<BLOCKQUOTE><PRE>for r in vw: print r.first, r.last, r.shoesize</PRE></BLOCKQUOTE>
Show a list of all people, sorted by last name:
<BLOCKQUOTE><PRE>for r in vw.sort(vw.last): print r.first, r.last, r.shoesize</PRE></BLOCKQUOTE>
Show a list of all people with first name 'John':
<BLOCKQUOTE><PRE>for r in vw.select(first='John'): print r.first, r.last, r.shoesize</PRE></BLOCKQUOTE>
<P>
<A NAME="ref"><HR size=1></A>
<!--BEGIN-->
<A NAME="0"></A><H2>Mk4py Reference</H2>
<OL>
<LI><A HREF="#1">Module functions</A>
<LI><A HREF="#2">Storage objects</A>
<LI><A HREF="#3">View objects</A>
<LI><A HREF="#4">Derived views</A>
<LI><A HREF="#5">View operations</A>
<LI><A HREF="#6">Mapping views</A>
<LI><A HREF="#7">Rowref objects</A>
<LI><A HREF="#8">Property objects</A>
</OL>
<HR SIZE=1>
<H3><A NAME="1"></A><A HREF="#0">1.</A> Module functions</H3>These functions live at the module level. You can use them
as described below after executing the following preamble:<BR><PRE><FONT COLOR="#000099"> import metakit
print metakit.version</FONT></PRE><P><B><FONT SIZE=-1>SYNOPSYS</FONT></B><BLOCKQUOTE><DL><DT><FONT COLOR="#990000"><I>db</I> = <I>metakit</I>.<B>storage</B>()</font><DD>Create an in-memory database (can't use commit/rollback)<DT><FONT COLOR="#990000"><I>db</I> = <I>metakit</I>.<B>storage</B>(<I>file</I>)</font><DD>Use a specified file object to build the storage on<DT><FONT COLOR="#990000"><I>db</I> = <I>metakit</I>.<B>storage</B>(<I>name</I>, <I>mode</I>)</font><DD>Open file, create if absent and rwflag is non-zero.
Open read-only if mode is 0, r/w if mode is 1 (cannot be shared),
or as commit-extend if mode is 2
(in mode 1 and 2, the file will be created if needed).<DT><FONT COLOR="#990000"><I>vw</I> = <I>metakit</I>.<B>view</B>()</font><DD>Create a standalone view; not in any storage object<DT><FONT COLOR="#990000"><I>pr</I> = <I>metakit</I>.<B>property</B>(<I>type</I>, <I>name</I>)</font><DD>Create a property (a column, when associated to a view)<DT><FONT COLOR="#990000"><I>vw</I> = <I>metakit</I>.<B>wrap</B>(<I>sequence</I>, <I>proplist</I>, <I>byPos</I>=0)</font><DD>Wraps a Python sequence as a view</DL></BLOCKQUOTE><B><FONT SIZE=-1>ADDITIONAL DETAILS</FONT></B><BLOCKQUOTE><DL><FONT COLOR="#990000"><B>storage</B></FONT> - When given a single argument, the file object must be a real
stdio file, not a class implementing the file r/w protocol.
When the storage object is destroyed (such as with
'db = None'), the associated datafile will be closed.
Be sure to keep a reference to it around as long as you use it.
<BR><BR><FONT COLOR="#990000"><B>wrap</B></FONT> - This call can be used to wrap any Python sequence, it assumes
that each item is either a dictionary or an object with attribute
names corresponding to the property names. Alternately, if
byPos is nonzero, each item can be a list or tuple - they will
then be accessed by position instead.
Views created in this way can be used in
joins and any other view operations.
<BR><BR></DL></BLOCKQUOTE>
<H3><A NAME="2"></A><A HREF="#0">2.</A> Storage objects</H3><B><FONT SIZE=-1>SYNOPSYS</FONT></B><BLOCKQUOTE><DL><DT><FONT COLOR="#990000"><I>vw</I> = <I>storage</I>.<B>getas</B>(<I>description</I>)</font><DD>Locate, define, or re-define a view stored in a storage object<DT><FONT COLOR="#990000"><I>vw</I> = <I>storage</I>.<B>view</B>(<I>viewname</I>)</font><DD>The normal way to retrieve an existing view<DT><FONT COLOR="#990000"><I>storage</I>.<B>rollback</B>(<I>full</I>=0)</font><DD>Revert data and structure as was last committed to disk.
In commit-aside mode, a "full" rollback reverts to the
state of the original file and forgets about the aside file.<DT><FONT COLOR="#990000"><I>storage</I>.<B>commit</B>(<I>full</I>=0)</font><DD>Permanently commit data and structure changes to disk
In commit-aside mode, a "full" commit save the latest
state in the original file and clears the aside datafile.<DT><FONT COLOR="#990000"><I>ds</I> = <I>storage</I>.<B>description</B>(<I>viewname</I>='')</font><DD>The description string is described under getas<DT><FONT COLOR="#990000"><I>vw</I> = <I>storage</I>.<B>contents</B>()</font><DD>Returns the View which holds the meta data for the Storage.<DT><FONT COLOR="#990000"><I>storage</I>.<B>autocommit</B>()</font><DD>Commit changes automatically when the storage object goes away<DT><FONT COLOR="#990000"><I>storage</I>.<B>load</B>(<I>fileobj</I>)</font><DD>Replace storage contents with data from file (or any other object
supporting read)<DT><FONT COLOR="#990000"><I>storage</I>.<B>save</B>(<I>fileobj</I>)</font><DD>Serialize storage contents to file (or any other object
supporting write)</DL></BLOCKQUOTE><B><FONT SIZE=-1>ADDITIONAL DETAILS</FONT></B><BLOCKQUOTE><DL><FONT COLOR="#990000"><B>description</B></FONT> - A description of the entire storage is retured if no viewname
is specified, otherwise just the specified top-level view.
<BR><BR><FONT COLOR="#990000"><B>getas</B></FONT> - Side-effects: the structure of the view is changed.<BR>Notes: Normally used to create a new View, or alter the
structure of an existing one.
<BR>A description string looks like:<BR><PRE><FONT COLOR="#000099"> "people[name:S,addr:S,city:S,state:S,zip:S]"</FONT></PRE>That is "<viewname>[<propertyname>:<propertytype>...]"<BR>Where the property type is one of:<BR>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0>
<TR><TD WIDTH=40></TD><TD>I</TD><TD WIDTH=20></TD><TD>adaptive integer (becomes Python int)</TD></TR>
<TR><TD WIDTH=40></TD><TD>L</TD><TD WIDTH=20></TD><TD>64-bit integer (becomes Python long)</TD></TR>
<TR><TD WIDTH=40></TD><TD>F</TD><TD WIDTH=20></TD><TD>C float (becomes Python float)</TD></TR>
<TR><TD WIDTH=40></TD><TD>D</TD><TD WIDTH=20></TD><TD>C double (is a Python float)</TD></TR>
<TR><TD WIDTH=40></TD><TD>S</TD><TD WIDTH=20></TD><TD>C null terminated string (becomes Python string)</TD></TR>
<TR><TD WIDTH=40></TD><TD>B</TD><TD WIDTH=20></TD><TD>C array of bytes (becomes Python string)</TD></TR>
</TABLE>Careful: do not include white space in the decription string.<BR><BR></DL></BLOCKQUOTE>
<H3><A NAME="3"></A><A HREF="#0">3.</A> View objects</H3>View implements sequence (list) methods, including slicing,
concatentation etc. They behave as a sequence of "rows",
which in turn have "properties".
Indexing (getitem) returns a reference to a row, not a copy.
<BR><PRE><FONT COLOR="#000099"> r = view[0]
r.name = 'Julius Caesar'
view[0].name # will yield 'Julius Caesar'</FONT></PRE>A slice returns a modifiable view which is tied to the underlying
view. As special case, however, you can create a fresh empty view
with the same structure as another view with:
<BR><PRE><FONT COLOR="#000099"> v2 = v[0:0]</FONT></PRE>Setting a slice changes the view:<BR><PRE><FONT COLOR="#000099"> v[:] = [] # empties the view</FONT></PRE>View supports getattr, which returns a Property
(eg view.shoesize can be used to refer to the shoesize column).
Views can be obtained from Storage objects:
view = db.view('inventory') or from other views
(see select, sort, flatten, join, project...) or empty,
columnless views can be created: vw = metakit.view()
<BR><P><B><FONT SIZE=-1>SYNOPSYS</FONT></B><BLOCKQUOTE><DL><DT><FONT COLOR="#990000"><I>view</I>.<B>insert</B>(<I>index</I>, <I>obj</I>)</font><DD>Coerce object to a Row and insert at index in View<DT><FONT COLOR="#990000"><I>ix</I> = <I>view</I>.<B>append</B>(<I>obj</I>)</font><DD>Object is coerced to Row and added to end of View<DT><FONT COLOR="#990000"><I>view</I>.<B>delete</B>(<I>index</I>)</font><DD>Row at index removed from View<DT><FONT COLOR="#990000"><I>lp</I> = <I>view</I>.<B>structure</B>()</font><DD>Return a list of property objects<DT><FONT COLOR="#990000"><I>cn</I> = <I>view</I>.<B>addproperty</B>(<I>fileobj</I>)</font><DD>Define a new property, return its column position<DT><FONT COLOR="#990000"><I>str</I> = <I>view</I>.<B>access</B>(<I>byteprop</I>, <I>rownum</I>, <I>offset</I>, <I>length</I>=0)</font><DD>Get (partial) byte property contents<DT><FONT COLOR="#990000"><I>view</I>.<B>modify</B>(<I>byteprop</I>, <I>rownum</I>, <I>string</I>, <I>offset</I>, <I>diff</I>=0)</font><DD>Store (partial) byte property contents.
A non-zero value of diff removes (<0) or inserts (>0) bytes.<DT><FONT COLOR="#990000">n = <I>view</I>.<B>itemsize</B>(<I>prop</I>, <I>rownum</I>=0)</font><DD>Return size of item (rownum only needed for S/B types).
With integer fields, a result of -1/-2/-4 means 1/2/4 bits
per value, respectively.<DT><FONT COLOR="#990000"><I>view</I>.<B>map</B>(<I>func</I>, <I>subset</I>=<I>None</I>)</font><DD>Apply func to each row of view, or (if subset specified)
to each row in view that is lso in subset.
Func must have the signature "func(row)", and may mutate row.
Subset must be a subset of view: e.g.
"customers.map(func, customers.select(...))".<DT><FONT COLOR="#990000"><I>rview</I> = <I>view</I>.<B>filter</B>(<I>func</I>)</font><DD>Return a view containing the indices of those rows
satisfying func. Func must have signature "func(row)"
and must return a false value to omit the row.<DT><FONT COLOR="#990000"><I>obj</I> = <I>view</I>.<B>reduce</B>(<I>func</I>, <I>start</I>=0)</font><DD>Return the result of applying func(row, lastresult) to
each row in view.<DT><FONT COLOR="#990000"><I>view</I>.<B>remove</B>(<I>indices</I>)</font><DD>Remove all rows whose indices are in subset from view.
Not the same as minus, because unique is not required,
and view is not reordered.<DT><FONT COLOR="#990000"><I>rview</I> = <I>view</I>.<B>indices</B>(<I>subset</I>)</font><DD>Returns a view containing the indices in view of the rows in
subset.<DT><FONT COLOR="#990000"><I>rview</I> = <I>view</I>.<B>copy</B>()</font><DD>Returns a copy of the view.</DL></BLOCKQUOTE><B><FONT SIZE=-1>ADDITIONAL DETAILS</FONT></B><BLOCKQUOTE><DL><FONT COLOR="#990000"><B>addproperty</B></FONT> - This adds properties which do not persist when committed. To
make them persist, you should use storage.getas(...) when
defining (or restructuring) the view.
<BR><BR><FONT COLOR="#990000"><B>append</B></FONT> - Also support keyword args (colname=value...).<BR><BR><FONT COLOR="#990000"><B>insert</B></FONT> - coercion to a Row is driven by the View's columns, and works for:<BR><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD WIDTH=40></TD><TD>dictionaries</TD><TD WIDTH=20></TD><TD>(column name -> key)</TD></TR><TR><TD WIDTH=40></TD><TD>instances</TD><TD WIDTH=20></TD><TD>(column name -> attribute name)</TD></TR><TR><TD WIDTH=40></TD><TD>lists</TD><TD WIDTH=20></TD><TD>(column number -> list index) - watch out!</TD></TR></TABLE><BR></DL></BLOCKQUOTE>
<H3><A NAME="4"></A><A HREF="#0">4.</A> Derived views</H3><B><FONT SIZE=-1>SYNOPSYS</FONT></B><BLOCKQUOTE><DL><DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>select</B>(<I>criteria</I>...)</font><DD>Return a view which has fields matching the given criteria<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>select</B>(<I>low</I>, <I>high</I>)</font><DD>Return a view with rows in the specified range (inclusive)<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>sort</B>()</font><DD>Sort view in "native" order, i.e. the definition order of its keys<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>sort</B>(<I>property</I>...)</font><DD>Sort view in the specified order<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>sortrev</B>((<I>propall</I>...), (<I>proprev</I>...))</font><DD>Sort view in specified order, with optionally some properties in reverse<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>project</B>(<I>property</I>...)</font><DD>Returns a derived view with only the named columns</DL></BLOCKQUOTE><B><FONT SIZE=-1>ADDITIONAL DETAILS</FONT></B><BLOCKQUOTE><DL><FONT COLOR="#990000"><B>select</B></FONT> - Example selections, returning the corresponding subsets:<BR><PRE><FONT COLOR="#000099"> result = inventory.select(shoesize=44)
result = inventory.select({'shoesize':40},{'shoesize':43})
result = inventory.select({},{'shoesize':43})</FONT></PRE>The derived view is "connected" to the base view.
Modifications of rows in the
derived view are reflected in the base view
<BR><BR><FONT COLOR="#990000"><B>sort</B></FONT> - Example, returning the sorted permutation:<BR><PRE><FONT COLOR="#000099"> result = inventory.sort(inventory.shoesize)</FONT></PRE>See notes for select concerning changes to the sorted view<BR><BR></DL></BLOCKQUOTE>
<H3><A NAME="5"></A><A HREF="#0">5.</A> View operations</H3><B><FONT SIZE=-1>SYNOPSYS</FONT></B><BLOCKQUOTE>
<DL>
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>flatten</B>(<I>subprop</I>, <I>outer</I>=0)</font>
<DD>Produces one 'flat' view from a nested view
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>join</B>(<I>view</I>, <I>property</I>...,<I>outer</I>=0)</font>
<DD>Both views must have a property (column) of that name and type
<DT><FONT COLOR="#990000"><I>ix</I> = <I>view</I>.<B>find</B>(<I>criteria</I>..., <I>start</I>=0)</font>
<DD>Returns the index of the found row, or -1
<DT><FONT COLOR="#990000"><I>ix</I> = <I>view</I>.<B>search</B>(<I>criteria</I>...)</font>
<DD>Binary search (native view order), returns match or insertion point
<DT><FONT COLOR="#990000"><I>ix, cnt</I> = <I>view</I>.<B>locate</B>(<I>criteria</I>...)</font>
<DD>Binary search, returns position and count as tuple (count can be zero)
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>unique</B>()</font>
<DD>Returns a new view without duplicate rows (a set)
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>union</B>(<I>view2</I>)</font>
<DD>Returns a new view which is the set union of view and view2
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>intersect</B>(<I>view2</I>)</font>
<DD>Returns a new view which is the set intersection of view and view2
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>different</B>(<I>view2</I>)</font>
<DD>Returns a new view which is the set XOR of view and view2
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>minus</B>(<I>view2</I>)</font>
<DD>Returns a new view which is (in set terms) view - view.intersect(view2)
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>remapwith</B>(<I>view2</I>)</font>
<DD>Remap rows according to the first (int) property in view2
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>pair</B>(<I>view2</I>)</font>
<DD>Concatenate rows pairwise, side by side
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>rename</B>('<I>oldname</I>', '<I>newname</I>')</font>
<DD>Returns a derived view with one property renamed
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>product</B>(<I>view</I>)</font>
<DD>Returns the cartesian product of both views
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>groupby</B>(<I>property</I>..., '<I>subname</I>')</font>
<DD>Groups on specified properties, with subviews to hold groups
<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>counts</B>(<I>property</I>..., '<I>name</I>')</font>
<DD>Groups on specified properties, replacing rest with a count field
</DL></BLOCKQUOTE>
<B><FONT SIZE=-1>ADDITIONAL DETAILS</FONT></B><BLOCKQUOTE>
<DL><FONT COLOR="#990000"><B>find</B></FONT> - view[view.find(firstname='Joe')] is the same as
view.select(firstname='Joe')[0] but much faster
Subsequent finds use the "start" keyword:
view.find(firstname='Joe', start=3)
<BR><BR></DL></BLOCKQUOTE>
<H3><A NAME="6"></A><A HREF="#0">6.</A> Mapping views</H3><B><FONT SIZE=-1>SYNOPSYS</FONT></B><BLOCKQUOTE><DL><DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>hash</B>(<I>mapview</I>, <I>numkeys</I>=1)</font><DD>Construct a hash mapping based on the first N fields.<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>blocked</B>(<I>blockview</I>)</font><DD>Construct a "blocked" view, which acts as if all segments together
form a single large view.<DT><FONT COLOR="#990000"><I>vw</I> = <I>view</I>.<B>ordered</B>(<I>numkeys</I>=1)</font><DD>Define a view which assumes and maintains sort order,
based on the first N fields. When layered on top of a blocked
view, this implements a 2-level btree.</DL></BLOCKQUOTE><B><FONT SIZE=-1>ADDITIONAL DETAILS</FONT></B><BLOCKQUOTE><DL><FONT COLOR="#990000"><B>blocked</B></FONT> - This view acts like a large flat view, even though the actual
rows are stored in blocks, which are rebalanced automatically to
maintain a good trade-off between block size and number of blocks.
<BR>The underlying view must be defined with a single view property,
with the structure of the subview being as needed.
<BR><BR><FONT COLOR="#990000"><B>hash</B></FONT> - This view creates and manages a special hash map view, to implement
a fast find on the key. The key is defined to consist of the
first numKeys_ properties of the underlying view.
<BR>The mapview must be empty the first time this hash view is used,
so that MetaKit can fill it based on whatever rows are already
present in the underlying view. After that, neither the underlying
view nor the map view may be modified other than through this
hash mapping layer. The defined structure of the map view must be
"_H:I,_R:I".
<BR>This view is modifiable. Insertions and changes to key field
properties can cause rows to be repositioned to maintain hash
uniqueness. Careful: when a row is changed in such a way that its
key is the same as in another row, that other row will be deleted
from the view.
<BR><BR><FONT COLOR="#990000"><B>ordered</B></FONT> - This is an identity view, which has as only use to inform MetaKit
that the underlying view can be considered to be sorted on its
first numKeys properties. The effect is that view.find() will
try to use binary search when the search includes key properties
(results will be identical to unordered views, the find will
just be more efficient).
<BR>This view is modifiable. Insertions and changes to key field
properties can cause rows to be repositioned to maintain the sort
order. Careful: when a row is changed in such a way that its key
is the same as in another row, that other row will be deleted from
the view.
<BR>This view can be combined with view.blocked(), to create a 2-level
btree structure.
<BR><BR></DL></BLOCKQUOTE>
<H3><A NAME="7"></A><A HREF="#0">7.</A> Rowref objects</H3>RowRef allows setting and getting of attributes (columns)<BR>RowRef encapsulates a (view, ndx) tuple.<BR>Normally obtained from a view: rowref = view[33]<BR>
<H3><A NAME="8"></A><A HREF="#0">8.</A> Property objects</H3>Property has attributes name, id and type.
Example: p = metakit.property('I', 'shoesize')
<BR>Note that a property is used to describe a column, but it is NOT the
same as a column. That is, in a given storage, the property
Property('I', 'shoesize') will be unique, (that is, no matter how many
instances you create, they will all have the same property.id). But that
one property can describe any number of columns, each one in a different
view. This is how joins are done, and why "view.sort(view.firstname)"
is the same as "view.sort(metakit.property('S','firstname'))".
<BR>
<!--END-->
<P>
<HR size=1>
© 2000 Jean-Claude Wippler <<A HREF="mailto:jcw@equi4.com">jcw@equi4.com</A>>
</BODY>
</HTML>
|