pgocaml icon indicating copy to clipboard operation
pgocaml copied to clipboard

Conditionally compose / build queries, avoiding repetition?

Open nezartarbin opened this issue 1 year ago • 0 comments

Hi, I was wondering if it is possible to avoid repeating parts of a query, and somehow compose a query from different parts.

I have this code for example:

let add_task title tag = 
  let dbh = PGOCaml.connect () in
  let insert_without_tag title = [%pgsql dbh "insert into tasks (title) values ($title)"] in 
  let insert_with_tag title tag = [%pgsql dbh "
    with added_task_id AS (
      insert into tasks (title) values ($title) returning task_id
    ), selected_tag_id AS (
      select tag_id from tags where name = $tag
    ) insert into task_tags (task_id, tag_id) (select task_id, tag_id from added_task_id, selected_tag_id)"] in 
  match tag with
    | None -> insert_without_tag title
    | Some some_tag -> insert_with_tag title some_tag

As you might notice, the insert into tasks (title) values ($title) part of the query is repeated. I picked a simple example, but more complex examples will have more shared parts and repetitions.

Is there a way to compose the SQL query instead of having to write out the entire thing at once?

For example, I tried this but it did not work:

let add_task title tag = 
  let dbh = PGOCaml.connect () in
  let shared_query = "insert into tasks (title) values ($title)" in
  let insert_without_tag title = [%pgsql dbh shared_query] in 
  let insert_with_tag title tag = [%pgsql dbh "
    with added_task_id AS (
      $shared_query
    ), selected_tag_id AS (
      select tag_id from tags where name = $tag
    ) insert into task_tags (task_id, tag_id) (select task_id, tag_id from added_task_id, selected_tag_id)"] in 
  match tag with
    | None -> insert_without_tag title
    | Some some_tag -> insert_with_tag title some_tag\

or any other way I can think of to construct queries conditionally, did not work.

Is this possible with this library? Thanks!

nezartarbin avatar Aug 10 '24 07:08 nezartarbin