Overview of the PersistentTable package
Calling Sequence
Description
List of PersistentTable Package Commands
Caveats
Thread Safety
Examples
Compatibility
PersistentTable:-command(arguments)
command(arguments)
The PersistentTable package provides a connection object that behaves somewhat like a table, except it is (by default) backed by a file containing an SQLite table. As a consequence, any information stored in the table persists when Maple is shut down or restarted. Furthermore, there is some extra functionality for searching through the stored information.
The interface is deliberately kept simple; it does not come close to giving access to all of SQLite's functionality. If you need more functionality, you can use the package Database:-SQLite. However, the PersistentTable package is easier to use for programmers who have experience with Maple, but not much experience with SQL. Conversely, if you don't need persistent storage or the extra searching functionality provided by this package, you are probably better off using a plain table.
The commands in the PersistentTable package are:
Close
Count
Get
GetAll
GetKeys
Has
MaybeGet
Open
RawCommand
Set
A PersistentTable object has a fixed number of columns with associated types, say k. The first column, or the first n columns for some positive integer n <= k, are taken to make up the primary key of the object. This means that when viewed as a key/value store, the object's keys are all expression sequences of n Maple expressions, and the values are expression sequences of n - k Maple expressions.
Storing values in columns with data type anything converts them to the so-called "dot m" format, as generated by the %m specifier for the sprintf command and as described in the Format,m help page. Retrieving them translates them back to Maple. If your value will not survive such a process (for example, if it involves locals from modules), use of persistent tables will lead to unexpected results.
If float columns are used, be aware that the float operations done inside SQLite, and conversion to SQLite and back, do not necessarily comply with the rules with respect to precision that hold in Maple. Similarly, any constraints involving equality of expressions involving floating-point computation should be viewed with suspicion.
Internally, if there are multiple connection objects for the same file at one time in a single Maple session (presumably, though not necessarily, with a different prefix), and the file is specified in the same way for all invocations of Open (in particular, the string is the same after being run through FileTools:-AbsolutePath), only a single connection object is created through SQLite:-Open. It is required that either all of these connections are read-only, or none of them are. (Connections to different files can, of course, have different read-only status.) Referring to the same file through different paths is not advised. SQLite enforces certain restrictions as to opening the same file in different concurrent Maple sessions; this is, therefore, also not advised.
This is the only thread safety issue - persistent tables are thread safe as of Maple 2021 otherwise.
For more information on thread safety, see index/threadsafe.
with⁡PersistentTable:
Generate three file names that we can overwrite.
path1≔FileTools:-JoinPath⁡FileTools:-TemporaryDirectory⁡,foo.mks
path1≔/tmp/mpldoc2/foo.mks
path2≔FileTools:-JoinPath⁡FileTools:-TemporaryDirectory⁡,bar.mks
path2≔/tmp/mpldoc2/bar.mks
path3≔FileTools:-JoinPath⁡FileTools:-TemporaryDirectory⁡,baz.mks
path3≔/tmp/mpldoc2/baz.mks
Make sure these files do not currently exist.
FileTools:-Remove⁡op⁡select⁡FileTools:-Exists,path1,path2,path3
Create the first persistent table: entries are indexed by two integers and the value is an arbitrary Maple expression.
store1≔Open⁡path1,style=k1::integer,k2::integer,v::anything,primarykey=2
store1≔<< 3-column persistent table at /tmp/mpldoc2/foo.mks >>
The expression that is the value can be, for example, a list.
Set⁡store1,3,5,2,4,6,1,3
One can access this value using the Get command or indexing.
Get⁡store1,3,5
2,4,6,1,3
store13,5
The Has and Count commands give us information about the existence of entries.
Has⁡store1,3,5
true
Has⁡store1,4,5
false
Count⁡store1,k1=3
1
Count⁡store1,k1=4
0
Set⁡store1,3,5,2,4
2,4
store13,6≔x,y
2
We can use the RawCommand command to manage transactions.
RawCommand⁡store1,BEGIN TRANSACTION
store13,2≔6
3
RawCommand⁡store1,ROLLBACK TRANSACTION
The Get command generates an error if you try to access an entry that does not exist. Indexing is the same. The MaybeGet command instead returns a default value that you specify.
MaybeGet⁡store1,3,6,FAIL
x,y
MaybeGet⁡store1,3,3,FAIL
FAIL
store2≔Open⁡path2,style=k1::integer,k2::integer,v::anything,b::boolean,primarykey=2
store2≔<< 4-column persistent table at /tmp/mpldoc2/bar.mks >>
Get⁡store2,3,5
Error, (in PersistentTable:-Get) bad index into PersistentTable
store21,4
Error, bad index into PersistentTable
The GetAll command returns all rows satisfying some criterion. The GetKeys command returns information from the same rows, but returns only the primary key columns.
store21,4≔sqrt⁡5,true
store21,4≔5,true
GetAll⁡store2,b=true
1,4,5,true
GetKeys⁡store2,b=true
1,4
Close⁡store1;Close⁡store2
You can't open two connections to the same file with different readonly settings, even if they have different prefixes:
store3≔Open⁡path3,style=k::anything,v::anything
store3≔<< 2-column persistent table at /tmp/mpldoc2/baz.mks >>
store4≔Open⁡path3,prefix=duck,style=k1::integer,k2::integer,v1::anything,v2::integer,v3::anything,primarykey=2,index⁡v2,readonly=true
Error, (in PersistentTable:-Open) tried to connect to /tmp/mpldoc2/baz.mks, which is already open with a different read-only status
store4≔Open⁡path3,prefix=duck,style=k1::integer,k2::integer,v1::anything,v2::integer,v3::anything,primarykey=2,index⁡v2
store4≔<< 5-column persistent table at /tmp/mpldoc2/baz.mks with prefix duck_ >>
store5≔Open⁡path3,prefix=drijfsijs,style=k1::integer,v1::float,v2::float
store5≔<< 3-column persistent table at /tmp/mpldoc2/baz.mks with prefix drijfsijs_ >>
store31+x≔y
store33,4≔y
Has⁡store3,1
Has⁡store3,1+x
Has⁡store4,3,4
store43,4≔duck,2,bill
store42,4≔goose,3,egg
store31+x
y
store43,4
duck,2,bill
store42,4
goose,3,egg
GetAll⁡store4,v2=3
2,4,goose,3,egg
GetAll⁡store4,v2=4
∅
Because the key and value are arbitrary Maple expressions, you cannot use inequalities when calling GetAll on store3: the comparison needs to be carried out inside the database engine, and it does not understand Maple expressions.
GetAll⁡store3,k<5
Error, (in PersistentTable:-GetAll) invalid condition (k < 5): column k is of type anything, so it does not support inequalities
However, store4 supports arbitrary polynomial conditions involving its integer columns:
GetAll⁡store4,k13<k2+v222
Set⁡store5,3,2.1,3.5
Set⁡store5,7,Float⁡∞,7.4
GetAll⁡store5
3,2.10000000000000009,3.50000000000000000,7,Float⁡∞,7.40000000000000036
GetAll⁡store5,k1<v1
7,Float⁡∞,7.40000000000000036
Close⁡store3;Close⁡store4;Close⁡store5
restart
The files should still be present.
store1≔Open⁡path1
store2≔Open⁡path2,readonly
5,true
store21,4≔6
Error, attempt to write a readonly database
store3≔Open⁡path3
store4≔Open⁡path3,prefix=duck
Close⁡store3;Close⁡store4
FileTools:-Remove⁡path1,path2,path3
The PersistentTable package was introduced in Maple 2021.
For more information on Maple 2021 changes, see Updates in Maple 2021.
See Also
Database:-SQLite
table
Download Help Document