File: sql_internal.c

package info (click to toggle)
zsv 1.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 49,160 kB
  • sloc: ansic: 175,811; cpp: 56,301; sh: 3,623; makefile: 3,048; javascript: 577; cs: 90; awk: 70; python: 41; sql: 15
file content (101 lines) | stat: -rw-r--r-- 3,216 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "sql_internal.h"

struct zsv_sqlite3_db *zsv_sqlite3_db_new(struct zsv_sqlite3_dbopts *dbopts) {
  struct zsv_sqlite3_db *zdb = calloc(1, sizeof(*zdb));
  if (!zdb) {
    perror(NULL);
    return NULL;
  }
  const char *db_url = dbopts && dbopts->in_memory ? "file::memory:" : "";
  int flags = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE;
  zdb->rc = sqlite3_open_v2(db_url, &zdb->db, flags, NULL);
  if (zdb->rc == SQLITE_OK && zdb->db)
    zdb->rc = sqlite3_create_module(zdb->db, "csv", &CsvModule, 0);
  if (zdb->rc != SQLITE_OK && !zdb->err_msg)
    zdb->err_msg = strdup(sqlite3_errstr(zdb->rc));
  return zdb;
}

void zsv_sqlite3_db_delete(struct zsv_sqlite3_db *zdb) {
  if (zdb) {
    for (struct zsv_sqlite3_csv_file *next, *zcf = zdb->csv_files; zcf; zcf = next) {
      next = zcf->next;
      if (zcf->added)
        sqlite3_zsv_list_remove(zcf->path);
      free(zcf->path);
      free(zcf);
    }
    if (zdb->db)
      sqlite3_close(zdb->db);
    free(zdb);
  }
}

static int create_virtual_csv_table(const char *fname, sqlite3 *db, // int max_columns,
                                    char **err_msgp, int table_ix) {
  // TO DO: set customizable maximum number of columns to prevent
  // runaway in case no line ends found
  char *sql = NULL;
  char table_name_suffix[64];

  if (table_ix == 0)
    *table_name_suffix = '\0';
  else if (table_ix < 0 || table_ix > 1000)
    return -1;
  else
    snprintf(table_name_suffix, sizeof(table_name_suffix), "%i", table_ix + 1);

  sql = sqlite3_mprintf("CREATE VIRTUAL TABLE data%s USING csv(filename=%Q)", table_name_suffix, fname);

  char *err_msg_tmp;
  int rc = sqlite3_exec(db, sql, NULL, NULL, &err_msg_tmp);
  if (err_msg_tmp) {
    *err_msgp = strdup(err_msg_tmp);
    sqlite3_free(err_msg_tmp);
  }
  sqlite3_free(sql);
  return rc;
}

int zsv_sqlite3_add_csv(struct zsv_sqlite3_db *zdb, const char *csv_filename, struct zsv_opts *opts,
                        struct zsv_prop_handler *custom_prop_handler) {
  struct zsv_sqlite3_csv_file *zcf = calloc(1, sizeof(*zcf));
  if (!zcf || !(zcf->path = strdup(csv_filename)))
    zdb->rc = SQLITE_ERROR;
  else {
    int err = 0;
    if (opts) {
      err = sqlite3_zsv_list_add(csv_filename, opts, custom_prop_handler);
      if (!err)
        zcf->added = 1;
    }
    if (err)
      zdb->rc = SQLITE_ERROR;
    else {
      zcf->next = zdb->csv_files;
      zdb->csv_files = zcf;
      zdb->rc = create_virtual_csv_table(csv_filename, zdb->db, &zdb->err_msg, zdb->table_count);
      if (zdb->rc == SQLITE_OK) {
        zdb->table_count++;
        return SQLITE_OK;
      }
    }
  }
  if (zcf) {
    free(zcf->path);
    free(zcf);
  }
  return zdb->rc;
}

/**
 * zsv_sqlite3_add_csv_no_dq is the same as zsv_sqlite3_add_csv() but also executes
 * sqlite3_db_config(db, SQLITE_DBCONFIG_DQS_DML, 0, (void*)0);
 */
int zsv_sqlite3_add_csv_no_dq(struct zsv_sqlite3_db *zdb, const char *csv_filename, struct zsv_opts *opts,
                              struct zsv_prop_handler *custom_prop_handler) {
  int rc = zsv_sqlite3_add_csv(zdb, csv_filename, opts, custom_prop_handler);
  if (rc == SQLITE_OK)
    sqlite3_db_config(zdb->db, SQLITE_DBCONFIG_DQS_DDL, 0, (void *)0);
  return rc;
}