-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add internal structure for cell-level display formatting (e.g. bold etc) * refactor sql * sheet: fix mutex not destroyed * sql: improve how zsv_opts and custom_prop_handler are passed to sqlite3 csv module TO DO: example extension w sql + cell highlighting + drill-down
- Loading branch information
Showing
13 changed files
with
490 additions
and
219 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#ifndef SQLITE3_CSV_VTAB_ZSV_H | ||
#define SQLITE3_CSV_VTAB_ZSV_H | ||
|
||
#include <pthread.h> | ||
|
||
/** | ||
* see sqlite3_csv_vtab-mem.h for background info | ||
*/ | ||
#if defined(_WIN32) || defined(_WIN64) | ||
#include <process.h> | ||
#else | ||
#include <unistd.h> | ||
#endif | ||
|
||
struct sqlite3_zsv_data { | ||
struct sqlite3_zsv_data *next; | ||
pid_t pid; | ||
char *filename; | ||
struct zsv_opts opts; | ||
struct zsv_prop_handler custom_prop_handler; | ||
}; | ||
|
||
pthread_mutex_t sqlite3_zsv_data_mutex; | ||
struct sqlite3_zsv_data *sqlite3_zsv_data_g = NULL; | ||
|
||
/** | ||
* Our shared memory structure should be locked for read/write | ||
*/ | ||
static int sqlite3_zsv_data_lock(void) { | ||
#ifndef NO_THREADING | ||
pthread_mutex_lock(&sqlite3_zsv_data_mutex); | ||
#endif | ||
return 0; | ||
} | ||
|
||
static int sqlite3_zsv_data_unlock(void) { | ||
#ifndef NO_THREADING | ||
pthread_mutex_unlock(&sqlite3_zsv_data_mutex); | ||
#endif | ||
return 0; | ||
} | ||
|
||
static void sqlite3_zsv_data_delete(struct sqlite3_zsv_data *e) { | ||
if (e) { | ||
free(e->filename); | ||
} | ||
free(e); | ||
} | ||
|
||
void sqlite3_zsv_list_delete(void **list) { | ||
for (struct sqlite3_zsv_data *next, *e = *list; e; e = next) { | ||
next = e->next; | ||
sqlite3_zsv_data_delete(e); | ||
} | ||
#ifndef NO_THREADING | ||
pthread_mutex_destroy(&sqlite3_zsv_data_mutex); | ||
#endif | ||
*list = NULL; | ||
} | ||
|
||
static struct sqlite3_zsv_data *sqlite3_zsv_data_new(const char *filename, struct zsv_opts *opts, | ||
struct zsv_prop_handler *custom_prop_handler) { | ||
if (!filename) | ||
return NULL; | ||
struct sqlite3_zsv_data *e = calloc(1, sizeof(*e)); | ||
if (e) { | ||
e->pid = getpid(); | ||
e->filename = strdup(filename); | ||
if (opts) | ||
e->opts = *opts; | ||
if (custom_prop_handler) | ||
e->custom_prop_handler = *custom_prop_handler; | ||
if (e->filename) | ||
return e; | ||
} | ||
sqlite3_zsv_data_delete(e); | ||
return NULL; | ||
} | ||
|
||
int sqlite3_zsv_data_add(const char *filename, struct zsv_opts *opts, struct zsv_prop_handler *custom_prop_handler) { | ||
struct sqlite3_zsv_data **list = &sqlite3_zsv_data_g; | ||
struct sqlite3_zsv_data *e = sqlite3_zsv_data_new(filename, opts, custom_prop_handler); | ||
if (e) { | ||
struct sqlite3_zsv_data **next; | ||
if (sqlite3_zsv_data_lock()) { | ||
sqlite3_zsv_data_delete(e); | ||
return -1; | ||
} else { | ||
for (next = list; *next; next = &(*next)->next) | ||
; | ||
*next = e; | ||
sqlite3_zsv_data_unlock(); | ||
return 0; | ||
} | ||
} | ||
return ENOMEM; | ||
} | ||
|
||
static int sqlite3_zsv_data_cmp(struct sqlite3_zsv_data *x, const char *filename, pid_t pid) { | ||
return strcmp(x->filename, filename) && x->pid == pid; | ||
} | ||
|
||
struct sqlite3_zsv_data *sqlite3_zsv_data_find(const char *filename) { | ||
struct sqlite3_zsv_data *list = sqlite3_zsv_data_g; | ||
struct sqlite3_zsv_data *found = NULL; | ||
pid_t pid = getpid(); | ||
if (!sqlite3_zsv_data_lock()) { | ||
for (struct sqlite3_zsv_data *e = list; e && !found; e = e->next) { | ||
if (!sqlite3_zsv_data_cmp(e, filename, pid)) | ||
found = e; | ||
} | ||
if (sqlite3_zsv_data_unlock()) | ||
fprintf(stderr, "Error unlocking sqlite3-csv-zsv shared mem lock\n"); | ||
} | ||
return found; | ||
} | ||
|
||
int sqlite3_zsv_list_remove(const char *filename) { | ||
if (!filename) | ||
return 0; | ||
struct sqlite3_zsv_data **list = &sqlite3_zsv_data_g; | ||
struct sqlite3_zsv_data *found = NULL; | ||
pid_t pid = getpid(); | ||
if (*list) { | ||
if (!sqlite3_zsv_data_cmp(*list, filename, pid)) { | ||
// found a match at the head of list | ||
found = *list; | ||
*list = found->next; | ||
} else { | ||
// look for a match somewhere after the first element | ||
for (struct sqlite3_zsv_data *prior = *list; prior->next != NULL; prior = prior->next) { | ||
if (!sqlite3_zsv_data_cmp(prior->next, filename, pid)) { | ||
found = prior->next; | ||
prior->next = prior->next->next; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
if (found) { | ||
sqlite3_zsv_data_delete(found); | ||
return 0; | ||
} | ||
return ENOENT; // not found | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#ifndef SQLITE3_CSV_VTAB_ZSV_H | ||
#define SQLITE3_CSV_VTAB_ZSV_H | ||
|
||
#include <zsv.h> | ||
#include <zsv/utils/prop.h> | ||
|
||
/** | ||
* when sqlite3 opens a CSV file using ZSV, it needs a way to know | ||
* what options to open with (such as user-specified delimiter, header offset | ||
* or span, etc | ||
* | ||
* In particular, it needs access to: | ||
* - zsv options (struct zsv_opts) | ||
* - custom property handler (struct zsv_prop_handler *) | ||
* - options used (const char *) [but this can be passed via connection string] | ||
* | ||
* Some ways to pass this info are: | ||
* - Embed it in the text of the URI passed to the module's xConnect function. | ||
* This is not practical because we need to pass pointers | ||
* - Use a single global variable that can hold only one set of data at a time. | ||
* This was the old approach, via `zsv_set_default_opts` etc, which has the | ||
* usual drawbacks of using a single global variable structure | ||
* - Use a shared memory structure that can support multiple sets of data | ||
* That is the approach implemented here. Data is identified by the related | ||
* filename and caller pid | ||
* | ||
* sqlite3_create_module_v2 is passed the shared memory root pointer, | ||
* but it's not really needed because there is no way for it to be | ||
* dynamic so it always has to point to the single global location | ||
* | ||
* Prior to calling xConnect, the caller should save data for the related | ||
* file via `sqlite3_zsv_data_add()`; xConnect then does a lookup to | ||
* locate and use the saved data | ||
*/ | ||
|
||
struct sqlite3_zsv_data; | ||
|
||
void sqlite3_zsv_list_delete(struct sqlite3_zsv_data **list); | ||
|
||
int sqlite3_zsv_data_add(const char *filename, struct zsv_opts *opts, struct zsv_prop_handler *custom_prop_handler); | ||
|
||
struct sqlite3_zsv_data *sqlite3_csv_vtab_zsv_find(const char *filename); | ||
|
||
/** | ||
* Remove from list. Return 0 on success, non-zero on error | ||
*/ | ||
int sqlite3_zsv_list_remove(const char *filename); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.