Ocaml Sqlite3 Tutorial II
The code blow are modifed from http://www.mega-nerd.com/erikd/Blog/CodeHacking/Ocaml/snip_sqlite.html
I split the orginal problem into parts and fix the bugs in search_iterator
Create Table
#!/usr/bin/env ocaml
#use "topfind"
#require "sqlite3"
#require "unix"
open Sqlite3
open Printf
open Unix
exception E of string
let create_tables db =
(* Create two tables in the database. *)
let tables =
[ "people", "pkey INTEGER PRIMARY KEY, first TEXT, last TEXT, age INTEGER" ;
"cars", "pkey INTEGER PRIMARY KEY, make TEXT, model TEXT" ;
]
in
let make_table (name, layout) =
let stmt = Printf.sprintf "CREATE TABLE %s (%s);" name layout in
match Sqlite3.exec db stmt with
| Sqlite3.Rc.OK -> Printf.printf "Table '%s' created.\n" name
| x -> raise (E (Sqlite3.Rc.to_string x))
in
List.iter make_table tables
(* Program main. *)
let () =
(* The database is called test.db. Delete it if it already exists. *)
let db_filename = "test.db" in
( try Unix.unlink db_filename
with _ -> ()
) ;
(* Create a new database. *)
let db = Sqlite3.db_open db_filename in
create_tables db ;
(* Close database when done. *)
if Sqlite3.db_close db then print_endline "All done.\n"
else print_endline "Cannot close database.\n"
Insert Data
#!/usr/bin/env ocaml
(* Need topfind to make require work, need require to use podge package *)
#use "topfind"
#require "sqlite3"
open Sqlite3
exception E of string
let insert_data db =
(* Insert data in both the tables. *)
let people_data =
[ "John", "Smith", 23;
"Helen", "Jones", 29 ;
"Adam", "Von Schmitt", 32 ;
]
in
let car_data =
[ "bugatti", "veyron" ;
"porsche", "911" ;
]
in
let insert_people (first, last, age) =
(* Use NULL for primary key and Sqlite will generate a unique key. *)
let stmt = Printf.sprintf "INSERT INTO people values (NULL, '%s', '%s', %d);"
first last age
in
match Sqlite3.exec db stmt with
| Sqlite3.Rc.OK -> ()
| x -> raise (E (Sqlite3.Rc.to_string x))
in
let insert_car (make, model) =
let stmt = Printf.sprintf "INSERT INTO cars values (NULL, '%s', '%s');"
make model
in
match Sqlite3.exec db stmt with
| Sqlite3.Rc.OK -> ()
| x -> raise (E (Sqlite3.Rc.to_string x))
in
List.iter insert_people people_data ;
List.iter insert_car car_data ;
print_endline "Data inserted."
(* Program main. *)
let () =
let db_filename = "test.db" in
let db = Sqlite3.db_open db_filename in
insert_data db ;
(* Close database when done. *)
if Sqlite3.db_close db then print_endline "All done.\n"
else print_endline "Cannot close database.\n"
Query Data
#!/usr/bin/env ocaml
(* Need topfind to make require work, need require to use podge package *)
#use "topfind"
#require "sqlite3"
open Sqlite3
exception E of string
let search_iterator db =
(* Perform a simple search. *)
let str_of_rc rc =
match rc with
| Sqlite3.Data.NONE -> "none"
| Sqlite3.Data.NULL -> "null"
| Sqlite3.Data.INT i -> Int64.to_string i
| Sqlite3.Data.FLOAT f -> string_of_float f
| Sqlite3.Data.TEXT s -> s
| Sqlite3.Data.BLOB _ -> "blob"
in
let dump_output s =
Printf.printf " Row Col ColName Type Value\n%!" ;
let row = ref 0 in
while Sqlite3.step s = Sqlite3.Rc.ROW do
for col = 0 to Sqlite3.data_count s - 1 do
let type_name =
match Sqlite3.column_decltype s col with
| Some name -> name
| None -> "unknow type"
in
let val_str = str_of_rc (Sqlite3.column s col) in
let col_name = Sqlite3.column_name s col in
Printf.printf " %2d %4d %-10s %-8s %s\n%!"
!row col col_name type_name val_str ;
done ;
row := succ !row ;
done
in
print_endline "People over 25 years of age :" ;
let stmt = Sqlite3.prepare db "SELECT * FROM people WHERE age > 25;" in
dump_output stmt ;
match Sqlite3.finalize stmt with
| Sqlite3.Rc.OK -> ()
| x -> raise (E (Sqlite3.Rc.to_string x))
(* Program main. *)
let () =
let db_filename = "test.db" in
let db = Sqlite3.db_open db_filename in
search_iterator db ;
(* Close database when done. *)
if Sqlite3.db_close db then print_endline "All done.\n"
else print_endline "Cannot close database.\n"
in the problem above, Sqlite3.column_decltype return option string, so I have to add pattern match to make it work.
let type_name =
match Sqlite3.column_decltype s col with
| Some name -> name
| None -> "unknow type"
in