summaryrefslogtreecommitdiff
path: root/lib/shared
diff options
context:
space:
mode:
authorpolwex <polwex@sortug.com>2025-06-27 16:34:09 +0700
committerpolwex <polwex@sortug.com>2025-06-27 16:34:09 +0700
commit645e815ebe11dbb86781c3eb645d3d67cd62cf7c (patch)
tree347b03391a5245de8a43198c9646719c2e892373 /lib/shared
parent8be9a806a93b02eada372f3993c34bc6b2f26fea (diff)
nice nice. lsp still doesnt work tho
Diffstat (limited to 'lib/shared')
-rw-r--r--lib/shared/dune8
-rw-r--r--lib/shared/query.ml186
2 files changed, 194 insertions, 0 deletions
diff --git a/lib/shared/dune b/lib/shared/dune
new file mode 100644
index 0000000..12bfe80
--- /dev/null
+++ b/lib/shared/dune
@@ -0,0 +1,8 @@
+(library
+ (name shared)
+ (libraries
+ caqti
+ caqti-eio
+ ppx_rapper_eio)
+ (preprocess
+ (pps ppx_rapper))) \ No newline at end of file
diff --git a/lib/shared/query.ml b/lib/shared/query.ml
new file mode 100644
index 0000000..bd1f11c
--- /dev/null
+++ b/lib/shared/query.ml
@@ -0,0 +1,186 @@
+open Rapper_helper
+
+type conn = (module CONNECTION)
+type pool = ((module CONNECTION), Caqti_error.t) Caqti_eio.Pool.t
+type 'a result_promise = ('a, Caqti_error.t) result Eio.Promise.t
+
+(* Define record types for the query outputs *)
+type post_summary =
+ { id : int
+ ; title : string
+ ; content : string
+ ; date : string
+ }
+
+type post =
+ { id : int
+ ; title : string
+ ; content : string
+ ; date : string
+ ; tags : string
+ ; url : string
+ }
+
+type comment =
+ { id : int
+ ; content : string
+ ; date : string
+ ; tags : string
+ ; url : string
+ }
+
+module Query = struct
+ let poasts =
+ [%rapper
+ get_many
+ {sql|
+ SELECT @int{id}, @string{title}, @string{content}, @string{date}
+ FROM Posts
+ ORDER BY id DESC LIMIT 100
+ |sql}
+ record_out]
+ ;;
+
+ let poast =
+ [%rapper
+ get_opt
+ {sql|
+ SELECT @int{id}, @string{title}, @string{content}, @string{date}, @string{tags}, @string{url}
+ FROM Posts
+ WHERE id = %int{post_id}
+ |sql}
+ record_out]
+ ;;
+
+ let comment =
+ [%rapper
+ get_opt
+ {sql|
+ SELECT @int{id}, @string{content}, @string{date}, @string{tags}, @string{url}
+ FROM Comments
+ WHERE id = %int{id}
+ |sql}
+ record_out]
+ ;;
+
+ let user_comments =
+ [%rapper
+ get_many
+ {sql|
+ SELECT @int{id}, @string{content}, @string{date}, @string{tags}, @string{url}
+ FROM Comments
+ WHERE author = %string{username}
+ |sql}
+ record_out]
+ ;;
+
+ let post_comments =
+ [%rapper
+ get_many
+ {sql|
+ SELECT @int{id}, @string{content}, @string{date}, @string{tags}, @string{url}
+ FROM Comments
+ WHERE post_id = %int{post_id}
+ |sql}
+ record_out]
+ ;;
+
+ let comment_children =
+ [%rapper
+ get_many
+ {sql|
+ SELECT @int{id}, @string{content}, @string{date}, @string{tags}, @string{url}
+ FROM Comments
+ WHERE parent= %int{post_id}
+ |sql}
+ record_out]
+ ;;
+
+ (* Insert queries *)
+ let insert_post =
+ [%rapper
+ execute
+ {sql|
+ INSERT INTO Posts (title, content, date, tags, url)
+ VALUES (%string{title}, %string{content}, %string{date}, %string{tags}, %string{url})
+ |sql}]
+ ;;
+
+ let insert_comment =
+ [%rapper
+ execute
+ {sql|
+ INSERT INTO Comments (content, date, tags, url, post_id, parent, author)
+ VALUES (%string{content}, %string{date}, %string{tags}, %string{url}, %int{post_id}, %int?{parent}, %string{author})
+ |sql}]
+ ;;
+
+ let insert_vote =
+ [%rapper
+ execute
+ {sql|
+ INSERT INTO Votes (post_id, comment_id, user_id, vote_type)
+ VALUES (%int?{post_id}, %int?{comment_id}, %string{user_id}, %string{vote_type})
+ |sql}]
+ ;;
+end
+
+(* let get_poasts pool = Caqti_eio.Pool.use (Query.poasts ()) pool *)
+
+let get_poasts conn = Query.poasts conn
+let get_poast post_id conn = Query.poast ~post_id conn
+
+(* Insert functions *)
+let create_post ~title ~content ~date ~tags ~url conn =
+ Query.insert_post ~title ~content ~date ~tags ~url conn
+;;
+
+let create_comment ~content ~date ~tags ~url ~post_id ?parent ~author conn =
+ Query.insert_comment ~content ~date ~tags ~url ~post_id ~parent ~author conn
+;;
+
+let create_vote ~user_id ~vote_type ?post_id ?comment_id conn =
+ Query.insert_vote ~post_id ~comment_id ~user_id ~vote_type conn
+;;
+
+(* SQLite performance pragmas - to be implemented *)
+let sqlite_pragmas =
+ [ "PRAGMA journal_mode = WAL"
+ ; "PRAGMA foreign_keys = ON"
+ ; "PRAGMA cache_size = -8000"
+ ; "PRAGMA temp_store = MEMORY"
+ ; "PRAGMA synchronous = NORMAL"
+ ; "PRAGMA mmap_size = 30000000000"
+ ]
+;;
+
+(* Example of how to execute raw SQL with Caqti *)
+let init_connection conn =
+ let module C = (val conn : Rapper_helper.CONNECTION) in
+ (* For PRAGMA commands, we don't know the return type, so use a custom approach *)
+ (* Some return strings, some return ints, some return nothing *)
+ let exec_pragma sql =
+ let open Caqti_request.Infix in
+ let open Caqti_type in
+ (* Try to execute as a simple exec first (for pragmas that return nothing) *)
+ match C.exec ((unit ->. unit) sql) () with
+ | Ok () -> Ok ()
+ | Error _ ->
+ (* If that fails, try as a query that returns a string *)
+ (match C.find_opt ((unit ->? string) sql) () with
+ | Ok _ -> Ok ()
+ | Error _ ->
+ (* If that also fails, try as a query that returns an int *)
+ (match C.find_opt ((unit ->? int) sql) () with
+ | Ok _ -> Ok ()
+ | Error e -> Error e))
+ in
+ (* Execute each pragma *)
+ List.fold_left
+ (fun acc sql ->
+ match acc with
+ | Error e -> Error e
+ | Ok () -> exec_pragma sql)
+ (Ok ())
+ sqlite_pragmas
+;;