SQLite User Forum

Including decimal.c in compiled binary and enabling by default
Login

Including decimal.c in compiled binary and enabling by default

(1) By Austin (aarbor989) on 2021-05-04 01:37:47 [link] [source]

Hello, I am trying to include decimal.c in the compiled binary and having it enabled by default. I am able to get it into the amalgation and compile successfully, however, when I try and use the decimal functions, SQLite is still saying "no such function".

I read through the documents, and it seems like I may need to add a call to sqlite3_auto_extension from within sqlite3_decimal_init.

Using vfsstat as a reference, I think I'll need something similar to the below which gets called from sqlite3_decimal_init. However, I don't see an equivalent DecimalModule that I could use to pass in, so I'm not sure what is supposed to go there instead. Unfortunately C is not my strong suit, so I'm not really able to follow what the documentation is suggesting. Any help would be much appreciated!

Thanks

static int vstatRegister(
  sqlite3 *db,
  char **pzErrMsg,
  const sqlite3_api_routines *pThunk
){
  return sqlite3_create_module(db, "vfsstat", &VfsStatModule, 0);
}

(2) By Keith Medcalf (kmedcalf) on 2021-05-04 05:24:49 in reply to 1 [link] [source]

Append decimal.c to the amalgamation source. The same goes for any extension you want to be part of the amalgamation.

Append the following code after that:

int core_init(const char* dummy)
{
    int nErr = 0;

    nErr += sqlite3_auto_extension((void*)sqlite3_decimal_init);
    // repeat above for any other extensions you append and want to init on each connection
    return nErr ? SQLITE_ERROR : SQLITE_OK;
}

Then compile the amalgamation with -DSQLITE_EXTRA_INIT=core_init (the preprocessor symbol SQLITE_EXTRA_INIT set to the name of the extra init function above).

On SQLite3 initialization, AFTER all the builtin stuff is initialized, the function defined by the SQLITE_EXTRA_INIT will be called. Similarly, when the library is shutdown a function defined by SQLITE_EXTRA_SHUTDOWN will be called before the rest of the library shutdown. This is to allow you to add stuffs to be initialized on startup and released on shutdown.

(3) By Austin (aarbor989) on 2021-05-04 15:11:44 in reply to 2 [link] [source]

this worked perfectly, thank you!

(4) By anonymous on 2021-05-04 17:57:14 in reply to 2 [source]

Well ... that probably works in Linux but not Windows.

A DLL built this way is not even recognized as a SQLite library by (for example) SQLite Expert.

Why? File sqlite3.def gives a hint - it only contains

EXPORTS sqlite3_decimal_init @1

Normally it contains a lot more.

The issue is in decimal.c with the block

#ifdef _WIN32 __declspec(dllexport) #endif

While __declspec(dllexport) is required to export all functions it packs an unpleasant surprise: when specified more than once it forgets all previous definitions. So to built this in Windows this block has to be removed from decimal.c.

(5.1) By Keith Medcalf (kmedcalf) on 2021-05-05 03:31:35 edited from 5.0 in reply to 4 [link] [source]

You either need (a) an export (.def) file with all the exports in it included in the compile/link so the linker knows what to export; or, (b) to compile with SQLITE_API=__declspec(dllexport) in order to mark the SQLite3 API functions as exports ...

(7) By Austin (aarbor989) on 2021-05-05 03:46:43 in reply to 5.1 [link] [source]

I did run a test on a Windows 10 64 bit VM before my original reply back here and didn’t notice any issues. I am doing this as a fork of xerial/sqlite-jdbc and don’t see that compile flag in the makefile. I’ll try adding it and see if it makes a difference

(10) By Keith Medcalf (kmedcalf) on 2021-05-06 06:56:04 in reply to 7 [link] [source]

You only need that flag if you want to annotate the API symbols with the dllexport flag so that you do not have to use a .def file to tell the linker which global symbols to export.

By default on unix/linux all visible global symbols are exported in discontiguous saved segments.

By default on Windows nothing is exported from discontiguous saved segments.

You can tell the linkers on Windows which global symbols to export by either (a) including a .def file in the input to the linker or (b) marking the global symbols for export in the object file.

If a .def file is presented to the linker then any directives it contains override the same class of directive in the object files. That is, if the .def file specifies EXPORTS then those exports override all exports defined in all object files. If the .def file includes special segment flags, then those flags override the specification of the segment flags embedded in the object files.

(6) By Austin (aarbor989) on 2021-05-05 03:44:04 in reply to 4 [link] [source]

Interesting..I am doing this as a fork of xerial/sqlite-jdbc and I ran a quick test on a Windows 10 64bit VM before reporting back here and everything seemed fine. I’ll have to dig deeper and see if I need to make any changes

(8) By anonymous on 2021-05-06 01:16:02 in reply to 2 [link] [source]

Using SQLITE_EXTRA_INIT is a bad idea.

in https://sqlite.org/forum/info/e9e218e1ee6355e0 it says about SQLITE_EXTRA_INIT

Because, if it is documented, we have to support it. As it stands currently, we are free to change or remove it as we see fit.

Just as SQLITE_HAS_CODEC it can be removed at any moment

quoted from https://sqlite.org/forum/forumpost/08481b3fac

Unfortunately, SQLITE_HAS_CODEC was never a documented or supported interface.

(9) By Austin (aarbor989) on 2021-05-06 02:53:16 in reply to 8 [link] [source]

Is there a better alternative?

(11) By anonymous on 2021-05-07 16:25:17 in reply to 9 [link] [source]

I don't know if it is better as such ...

When I tried to integrate some extensions in the amalgamation I looked how extensions like FTS5 and JSON1 where already included and I basically copied that solution.

Search for "An array of pointers to extension initializer functions" and look at the code above and below.

And finally include the extension(s) at the end of the amalgamtion (modify entry and remove superfluous code). One caveat: some extensions don't play nice together - for example when they define indentical functions.