Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

sqlite.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion mod sqlite
#
# -----------------------------------------------------------------------

lm : mutate is

# NYI: UNDER DEVELOPMENT: not yet supported by fzextract

# int sqlite3_open(
#   const char *filename,   /* Database filename (UTF-8) */
#   sqlite3 **ppDb          /* OUT: SQLite db handle */
# );
#
sqlite3_open(filename lm.array u8, db lm.array Native_Ref) i32 => native

# int sqlite3_exec(
#   sqlite3*,                                  /* An open database */
#   const char *sql,                           /* SQL to be evaluated */
#   int (*callback)(void*,int,char**,char**),  /* Callback function */
#   void *,                                    /* 1st argument to callback */
#   char **errmsg                              /* Error msg written here */
# );
#
sqlite3_exec(F type : Function i32 Native_Ref i32 Native_Ref Native_Ref, db Native_Ref, sql lm.array u8, callback F, arg Native_Ref, errmsg lm.array Native_Ref) i32 => native


#
# minimal usage example:
#
#     _ := (sqlite.open "test.db").bind unit db->
#       db.query "select * from table_name;" res->
#         say (res.map t->"{t.0} => {t.1}")
#         0
#
# run:
#
#     fz -modules=sqlite -jvm -JLibraries=sqlite3 path_to_example.fz
#
# compile:
#
#     fz -modules=sqlite -c -CLink=sqlite3 -CInclude=sqlite3.h path_to_example.fz
#
#
public sqlite(db Native_Ref) : Database is

  c => c lm

  public redef type.open(path String) outcome Database =>
    open outcome Database =>
      db := lm.array Native_Ref .from_Sequence [ffi.null]
      if sqlite3_open (path.as_c_string lm) db = 0
        check !(ffi.is_null db[0])
        sqlite db[0]
      else
        error "could not open database"

    lm ! open


  public redef close outcome unit =>
    # NYI: proper error handling
    check c.sqlite3_close db = 0
    unit


  public redef query(query_string String, callback Function i32 (Sequence (String, String))) outcome unit =>

    cb_wrapper : Function i32 Native_Ref i32 Native_Ref Native_Ref is
      public redef call(_ Native_Ref, len i32, column_text Native_Ref, column_name Native_Ref) i32 =>
        column_texts := ffi.from_native_array Native_Ref column_text len
        column_names := ffi.from_native_array Native_Ref column_name len
        data := (column_names.map ffi.from_native_string)
          .zip (column_texts.map ffi.from_native_string) x,y->(x,y)

        callback data

    query outcome unit =>
      ret := sqlite3_exec db (query_string.as_c_string lm) cb_wrapper ffi.null (lm.array Native_Ref .from_Sequence [ffi.null])
      if ret = 0
        unit
      else
        error "error executing query $query_string, sqlite3_exec." ret.as_i64

    lm ! query

last changed: 2026-06-12