Database¶
Unicon databases¶
Unicon supports a couple of different database types.
- DBM
- ODBC
These are optional dependencies during compiler build. DBM requires a DBM engine, GDBM for instance, and ODBC requires a Open Data Base Connection layer. A third option is using the native table datatype (or other aggregate data structure) to handle memory based database management
Tables¶
table data can be an easy way to handle ad-hoc database problems.
The IPL entries for xencode
and xdecode
can then be used
to add persistence.
#
# table-db, a small database in a table
#
link xcodes
procedure main()
db := table()
db["key"] := "valuable data"
db["alternate"] := ["more Unicon treasure", "in a list"]
dbf := open("table-db.dat", "w")
xencode(db, dbf)
close(dbf)
dbf := open("table-db.dat")
newdb := xdecode(dbf)
close(dbf)
write("newdb[\"key\"] is ", newdb["key"])
end
newdb["key"] is valuable data
Note
The xencode
and xdecode
procedures come in a couple of
different flavours; as link xcode
or link xcodes
. xcodes
makes handling record definitions a little easier, and
provides for file and procedure
structures that may not be present in the decoding program. Try and
use xcodes
for most developments.
DBM¶
When supported, open mode “d” (and mode “dr” for read-only) will
open DBM database resources. Once opened, the resource is treated as a
persistent table datatype. datum := dbm[s]
will retrieve
data for key s
, and dbm[s] := "some data"
will attempt to insert or
update the DBM information on disk. insert
, delete
and fetch
built-in functions can also be used. Update and insert are blocked for mode
“dr” read-only data stores.
#
# dbm, database sample
#
procedure main()
db := open("dbm.dat", "d")
db["key"] := "valuable data"
db["alternate"] := "more Unicon treasure"
close(db)
dbf := open("dbm.dat", "dr")
write(dbf["key"])
write(dbf["alternate"])
close(dbf)
end
valuable data
more Unicon treasure
The example above will create dbm.dat
, the user visible data file, and
also some internal files; dbm.dat.dir
and dbm.dat.pag
.
DBM information is converted to string form when written to
disk. Unlike memory tables, 1
and "1"
are the same key in DBM mode.
Use xencode
(and xdecode
) if you need to differentiate between string
and other datatypes for DBM keys and values.
ODBC¶
Unicon includes SQL features, when built with ODBC
support.
Documented in Unicon Technical Report, UTR1, http://unicon.org/utr/utr1/utr1.htm by Federico Balbi and Clint.
Requirements¶
- ODBC,
unixodbc
package (for instance) - SQLiteODBC,
libsqliteodbc
package (or other ODBC driver) - datasource definintion,
~/.odbc.ini
#
# odbc.icn, ODBC trial
#
link ximage
procedure main()
# mode 'o' open, ODBC SQL
db := open("unicon", "o", "", "") | stop("no odbc for \"unicon\"")
# Display some ODBC driver information
write("dbproduct:")
write(ximage(dbproduct(db)))
write("\ndbdriver:")
write(ximage(dbdriver(db)))
write("\ndblimits:")
write(ximage(dblimits(db)))
# create a sample table
sql(db, "drop table if exists contacts")
sql(db, "create table contacts (id integer primary key, name, phone)")
# insert some records, with and without transaction control
sql(db, "insert into contacts (name, phone) _
values ('brian', '613-555-1212')")
sql(db, "BEGIN; insert into contacts (name, phone) _
values ('jafar', '615-555-1213'); _
COMMIT")
sql(db, "insert into contacts (name, phone) _
values ('brian', '615-555-1214')")
sql(db, "BEGIN; insert into contacts (name, phone) _
values ('clint', '615-555-1215'); _
COMMIT")
sql(db, "insert into contacts (name, phone) _
values ('nico', '615-555-1216')")
# display ODBC view of table schema
write("\ndbtables:")
every write(ximage(dbtables(db)))
tables := dbtables(db)
write("\ndbcolumns.", tables[1].name, ":")
every write(ximage(dbcolumns(db, tables[1].name)))
# query a few phone numbers
write("\nPhone numbers for brian:")
sql(db, "select id, phone from contacts where name='brian'")
while rec := fetch(db) do write(rec.id, ": ", rec.phone)
write("\nPhone numbers for jafar:")
sql(db, "select id, phone from contacts where name='jafar'")
while rec := fetch(db) do write(rec.id, ": ", rec.phone)
# query with an intrinsic function
write("\nRecord count:")
sql(db, "select count(*) from contacts")
rec := fetch(db)
write(ximage(rec))
write(rec["count(*)"])
# query with an intrinsic function given alias
writes("\nRecord count (as counter): ")
sql(db, "select count(*) as counter from contacts")
rec := fetch(db)
write(rec.counter)
# close off the resource
close(db)
end
With a unicon
DSN (data source name) configuration of:
[unicon]
Description=Unicon ODBC sample
Driver=SQLite3
Database=/home/btiffin/lang/unicon/databases/unicon.db
Timeout=2000
Giving:
dbproduct:
R__1 := ()
R__1.name := "SQLite"
R__1.ver := "3.9.2"
dbdriver:
R__1 := ()
R__1.name := "sqlite3odbc.so"
R__1.ver := "0.9992"
R__1.odbcver := "03.00"
R__1.connections := 0
R__1.statements := ""
R__1.dsn := "unicon"
dblimits:
R__1 := ()
R__1.maxbinlitlen := 0
R__1.maxcharlitlen := 0
R__1.maxcolnamelen := 255
R__1.maxgroupbycols := 0
R__1.maxorderbycols := 0
R__1.maxindexcols := 0
R__1.maxselectcols := 0
R__1.maxtblcols := 0
R__1.maxcursnamelen := 255
R__1.maxindexsize := 0
R__1.maxownnamelen := 255
R__1.maxprocnamelen := 0
R__1.maxqualnamelen := 255
R__1.maxrowsize := 0
R__1.maxrowsizelong := "N"
R__1.maxstmtlen := 16384
R__1.maxtblnamelen := 255
R__1.maxselecttbls := 0
R__1.maxusernamelen := 16
dbtables:
L1 := list(1)
L1[1] := R__1 := ()
R__1.qualifier := ""
R__1.owner := ""
R__1.name := "contacts"
R__1.type := ""
R__1.remarks := ""
dbcolumns.contacts:
L6 := list(3)
L6[1] := R__1 := ()
R__1.catalog := ""
R__1.schema := ""
R__1.tablename := "contacts"
R__1.colname := "id"
R__1.datatype := 4
R__1.typename := "integer"
R__1.colsize := 9
R__1.buflen := 10
R__1.decdigits := 10
R__1.numprecradix := 0
R__1.nullable := 1
R__1.remarks := ""
L6[2] := R__2 := ()
R__2.catalog := ""
R__2.schema := ""
R__2.tablename := "contacts"
R__2.colname := "name"
R__2.datatype := 12
R__2.typename := ""
R__2.colsize := 0
R__2.buflen := 255
R__2.decdigits := 10
R__2.numprecradix := 0
R__2.nullable := 1
R__2.remarks := ""
L6[3] := R__3 := ()
R__3.catalog := ""
R__3.schema := ""
R__3.tablename := "contacts"
R__3.colname := "phone"
R__3.datatype := 12
R__3.typename := ""
R__3.colsize := 0
R__3.buflen := 255
R__3.decdigits := 10
R__3.numprecradix := 0
R__3.nullable := 1
R__3.remarks := ""
Phone numbers for brian:
1: 613-555-1212
3: 615-555-1214
Phone numbers for jafar:
2: 615-555-1213
Record count:
R__1 := ()
R__1.count(*) := 5
5
Record count (as counter): 5
That same code will work with MariaDB, PostgreSQL, Oracle, or any of the many other ODBC drivers that are available for most operating systems and database engines.
Index | Next: Networking | Previous: Graphics