File: SQLiteDB.k

package info (click to toggle)
kaya 0.4.2-4
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 4,448 kB
  • ctags: 1,694
  • sloc: cpp: 9,536; haskell: 7,461; sh: 3,013; yacc: 910; makefile: 816; perl: 90
file content (152 lines) | stat: -rw-r--r-- 4,944 bytes parent folder | download | duplicates (4)
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
/** -*-C-*-ish
    SQLite interface library for Kaya
    Copyright (C) 2006 Edwin Brady

    This file is distributed under the terms of the GNU Lesser General
    Public Licence. See COPYING for licence.
*/
"<summary>SQLite database interface module</summary>
<prose>This module allows querying of <link url='http://www.sqlite.org'>SQLite</link> database files, using the standard <moduleref>DB</moduleref> API.</prose>"
module SQLiteDB;

import Builtins;

// SQLite API suitable for use with the DB module.

// sqlite3_bind_*

import Prelude;
import public DB;

%include "sqlite_inter.h";
%imported "sqlite_inter";
%link "sqlite3";

"<summary>An SQLite database connection</summary>
<prose>This data type holds information about a database connection.
The type <code>SQLiteDB</code> is a type synonym for <code>DB::DBHandle&lt;SQLiteConnection></code></prose>
<related><moduleref>DB</moduleref></related>"
abstract data SQLiteConnection = SQLiteCon(Ptr cdata);

type SQLiteDB = DBHandle<SQLiteConnection>;

"<argument>The String contains the error message</argument>
<summary>Database error</summary>
<prose>This Exception is thrown if an error occurs while opening or querying a database file.</prose>"
Exception SQLiteError(String msg);

"<summary>Tried to read too many rows</summary>
<prose>This Exception is thrown if you try to read more rows from an incremental database query than actually exist.</prose>"
Exception TooManyRows();

foreign "sqlite_inter.o" {
    Ptr do_sqlite_connect(String info) = sqlite_connect;
    Bool sqlite_ok(Ptr con) = sqlite_ok;
    String sqlite_getError(Ptr con) = sqlite_getError;
    Void sqlite_close(Ptr con) = sqlite_close;
    Ptr sqlite_exec(Ptr con, String query) = sqlite_exec;
    Ptr sqlite_incexec(Ptr con, String query) = sqlite_incexec;
    [DBValue] sqlite_getrow(Ptr vm, Ptr res) = sqlite_getrow;
    Void sqlite_discard(Ptr res) = sqlite_discard;

    Ptr sqlite_execp(Ptr con, [Maybe<String>] params) = sqlite_execp;
    Ptr do_sqliprepare(Ptr vm, Ptr con, String query) = sqlite_prepare;

    [[DBValue]] sql_getrestable(Ptr pr) = sql_getrestable;
    [String] sql_getcolnames(Ptr pr) = sql_getcolnames;
    Int sql_numrows(Ptr pr) = sql_numrows;
    Int sql_numcols(Ptr pr) = sql_numcols;
    Int sql_resrc(Ptr pr) = sql_resrc;
}

"<argument name='fname'>The filename of the database</argument>
<summary>Open a database file.</summary>
<prose>Use this function to open the database file (creating it if it does not exist). You can then use the functions from <moduleref>DB</moduleref> to query the database.</prose>
<example>db = SQLiteDB::connect(\"site.db\");
res = exec(db,\"SELECT * FROM pagedata WHERE page_id = 10\");</example>
<related><moduleref>DB</moduleref></related>"
public SQLiteDB connect(String fname)
{
    sqlc = do_sqlite_connect(fname);
    con = SQLiteCon(sqlc);
    if (sqlite_ok(sqlc)==false) {
	throw(SQLiteError(sqlite_getError(sqlc)));
    }
    return DBh(con,
	       sqli_exec, sqli_incexec, 
	       sqli_prepare, sqli_execp, defaultIncExecPrepared,
	       sqli_getrow, sqli_discard, sqli_close);
}

"Execute a query on the given connection."
DBResult sqli_exec(SQLiteConnection con, String query)
{
    rc = sqlite_exec(con.cdata, query);
    if (sql_resrc(rc)==0) {
	dbvs = sql_getrestable(rc);
	rows = sql_numrows(rc);
	cols = sql_numcols(rc);
	colnames = sql_getcolnames(rc);
	return DBRes(dbvs, rows, cols, colnames, rc);
    }
    else {
	throw(SQLiteError(sqlite_getError(con.cdata)));
    }
}

DBIncResult<SQLiteConnection> sqli_incexec(SQLiteConnection con, String query, SQLiteDB dbc)
{
    rc = sqlite_incexec(con.cdata, query);
    if (sql_resrc(rc)==0) {
	rows = sql_numrows(rc);
	cols = sql_numcols(rc);
	colnames = sql_getcolnames(rc);
	return DBIncRes(dbc, rows, cols, colnames, rc);
    }
    else {
	throw(SQLiteError(sqlite_getError(con.cdata)));
    }
}

[DBValue] sqli_getrow(DBIncResult<SQLiteConnection> res) {
    try {
	return sqlite_getrow(getVM(),res.resptr);
    } catch(InternalError(e)) {
	if (e==0) {
	    throw(TooManyRows());
	} else throw(InternalError(e));
    }
}

Void sqli_discard(DBIncResult<SQLiteConnection> res) {
  sqlite_discard(res.resptr);
}


"Close a connection to the database."
Void sqli_close(SQLiteConnection con)
{
    sqlite_close(con.cdata);
}

DBStatement<SQLiteConnection> sqli_prepare(SQLiteDB con, String query) {
  try {
    return DBStatement(con,do_sqliprepare(getVM,con.handle.cdata,query));
  } catch(InternalError(e)) {
    throw(SQLiteError(sqlite_getError(con.handle.cdata)));
  }
}

DBResult sqli_execp(DBStatement<SQLiteConnection> prep, [Maybe<String>] params) {
    rc = sqlite_execp(prep.statement, params);
    if (sql_resrc(rc)==0) {
	dbvs = sql_getrestable(rc);
	rows = sql_numrows(rc);
	cols = sql_numcols(rc);
	colnames = sql_getcolnames(rc);
	return DBRes(dbvs, rows, cols, colnames, rc);
    }
    else {
	throw(SQLiteError(sqlite_getError(prep.con.handle.cdata)));
    }
}