| 3397 |
mrmanese |
1 |
#include <stdio.h>
|
|
|
2 |
#include <string.h>
|
|
|
3 |
#include "sqlite_dataframe.h"
|
|
|
4 |
|
|
|
5 |
|
|
|
6 |
SEXP sdf_import_sqlite_table(SEXP _dbfilename, SEXP _tblname, SEXP _sdfiname) {
|
|
|
7 |
sqlite3 *db;
|
|
|
8 |
sqlite3_stmt *stmt;
|
|
|
9 |
int res, nrows, ncols, buflen0, buflen1, buflen3, i;
|
|
|
10 |
int tblname_len, colname_len, iname_len;
|
|
|
11 |
char *dbfilename, *tblname, *iname, *type;
|
|
|
12 |
const char *colname;
|
|
|
13 |
SEXP ret = NULL;
|
|
|
14 |
|
|
|
15 |
dbfilename = CHAR_ELT(_dbfilename, 0);
|
|
|
16 |
tblname = CHAR_ELT(_tblname, 0);
|
|
|
17 |
/* determine if we were passed a real sqlite db */
|
|
|
18 |
db = _is_sqlitedb(dbfilename);
|
|
|
19 |
|
|
|
20 |
if (!db) {
|
|
|
21 |
Rprintf("Error: %s is not a SQLite database.\n", dbfilename);
|
|
|
22 |
return R_NilValue;
|
|
|
23 |
}
|
|
|
24 |
|
|
|
25 |
/* check if the table exists in the db */
|
|
|
26 |
sprintf(g_sql_buf[0], "select count(*) from [%s]", tblname);
|
|
|
27 |
res = sqlite3_prepare(db, g_sql_buf[0], -1, &stmt, 0);
|
|
|
28 |
if (_sqlite_error(res)) {
|
|
|
29 |
sqlite3_finalize(stmt); sqlite3_close(db);
|
|
|
30 |
return R_NilValue;
|
|
|
31 |
}
|
|
|
32 |
sqlite3_step(stmt);
|
|
|
33 |
nrows = sqlite3_column_int(stmt, 0);
|
|
|
34 |
sqlite3_finalize(stmt); sqlite3_close(db);
|
|
|
35 |
if (nrows == 0) {
|
|
|
36 |
Rprintf("Error: Table contains no rows. Aborting import operation.\n");
|
|
|
37 |
return R_NilValue;
|
|
|
38 |
}
|
|
|
39 |
|
|
|
40 |
/* we have to attach it so we can transfer easily */
|
|
|
41 |
|
|
|
42 |
/* unload sdf's if we run to the MAX_ATTACHED limit */
|
|
|
43 |
_prepare_attach2();
|
|
|
44 |
|
|
|
45 |
/* attach the table to be imported */
|
|
|
46 |
sprintf(g_sql_buf[0], "attach '%s' as [@@import@@]", dbfilename);
|
|
|
47 |
res = _sqlite_exec(g_sql_buf[0]);
|
|
|
48 |
if (_sqlite_error(res)) return R_NilValue;
|
|
|
49 |
|
|
|
50 |
|
|
|
51 |
/* create the sdf where the data will be imported to */
|
| 3419 |
mrmanese |
52 |
iname = _create_sdf_skeleton1(_sdfiname, NULL, FALSE);
|
| 3397 |
mrmanese |
53 |
if (iname == NULL) goto sdf_import_sqlite_table__out;
|
|
|
54 |
|
|
|
55 |
iname_len = strlen(iname); /* needed for buf resizing below */
|
|
|
56 |
tblname_len = strlen(tblname);
|
|
|
57 |
|
|
|
58 |
/* get column types and names */
|
|
|
59 |
sprintf(g_sql_buf[0], "select * from [@@import@@].[%s]", tblname);
|
|
|
60 |
res = sqlite3_prepare(g_workspace, g_sql_buf[0], -1, &stmt, 0);
|
|
|
61 |
_sqlite_error(res);
|
|
|
62 |
sqlite3_step(stmt);
|
|
|
63 |
ncols = sqlite3_column_count(stmt);
|
|
|
64 |
|
|
|
65 |
/* create the sql scripts to execute: the create table and the insert-select */
|
|
|
66 |
buflen0 = sprintf(g_sql_buf[0], "create table [%s].sdf_data([row name] text", iname);
|
|
|
67 |
buflen1 = sprintf(g_sql_buf[1], "select cumsum(1)");
|
|
|
68 |
buflen3 = sprintf(g_sql_buf[3], "from [@@import@@].[%s] ", tblname);
|
|
|
69 |
for (i = 0; i < ncols; i++) {
|
|
|
70 |
type = _str_tolower(g_sql_buf[2], sqlite3_column_decltype(stmt, i));
|
|
|
71 |
colname = sqlite3_column_name(stmt, i);
|
|
|
72 |
colname_len = strlen(colname);
|
|
|
73 |
if (strstr(type, "int")) {
|
|
|
74 |
_expand_buf(0, buflen0 + strlen(colname) + 10);
|
|
|
75 |
buflen0 += sprintf(g_sql_buf[0]+buflen0, ",[%s] int", colname);
|
|
|
76 |
|
|
|
77 |
_expand_buf(1, buflen1 + colname_len + 10);
|
|
|
78 |
buflen1 += sprintf(g_sql_buf[1]+buflen1, ",[%s]", colname);
|
|
|
79 |
} else if (strstr(type, "char") || strcmp(type, "text")) {
|
|
|
80 |
_expand_buf(0, buflen0 + strlen(colname) + 10);
|
|
|
81 |
buflen0 += sprintf(g_sql_buf[0]+buflen0, ",[%s] int", colname);
|
|
|
82 |
|
|
|
83 |
_expand_buf(1, buflen1 + colname_len + iname_len + 20);
|
|
|
84 |
buflen1 += sprintf(g_sql_buf[1]+buflen1, ",[%s].[factor %s].level",
|
|
|
85 |
iname, colname);
|
|
|
86 |
|
|
|
87 |
/* create factor table */
|
|
|
88 |
_create_factor_table2(iname, "factor", colname);
|
|
|
89 |
|
|
|
90 |
/* insert factor levels and labels */
|
|
|
91 |
sprintf(g_sql_buf[2], "insert into [%s].[factor %s] (label, level)"
|
|
|
92 |
" select distinct [%s], cumsum(1) from [@@import@@].[%s]",
|
|
|
93 |
iname, colname, colname, tblname);
|
|
|
94 |
res = _sqlite_exec(g_sql_buf[2]);
|
|
|
95 |
_sqlite_error(res);
|
|
|
96 |
|
|
|
97 |
/* add join clause to from clause */
|
|
|
98 |
_expand_buf(3, buflen3 + colname_len * 3 + iname_len * 2 + strlen(tblname) + 32);
|
|
|
99 |
buflen3 += sprintf(g_sql_buf[3] + buflen3, " join [%s].[factor %s] "
|
|
|
100 |
"on [@@import@@].[%s].[%s] = [%s].[factor %s].label",
|
|
|
101 |
iname, colname, tblname, colname, iname, colname);
|
|
|
102 |
} else if (strcmp(type, "blob") || !*type) {
|
|
|
103 |
/* not supported */
|
|
|
104 |
Rprintf("Warning: skipping column %s because it is a blob.\n", colname);
|
|
|
105 |
} else { /* numeric / float / real / ... */
|
|
|
106 |
_expand_buf(0, buflen0 + strlen(colname) + 10);
|
|
|
107 |
buflen0 += sprintf(g_sql_buf[0]+buflen0, ",[%s] double", colname);
|
|
|
108 |
|
|
|
109 |
_expand_buf(1, buflen1 + colname_len + 10);
|
|
|
110 |
buflen1 += sprintf(g_sql_buf[1]+buflen1, ",[%s]", colname);
|
|
|
111 |
}
|
|
|
112 |
}
|
|
|
113 |
|
|
|
114 |
sqlite3_finalize(stmt);
|
|
|
115 |
|
|
|
116 |
/* execute create script */
|
|
|
117 |
_expand_buf(0, buflen0 + 10);
|
|
|
118 |
sprintf(g_sql_buf[0] + buflen0, ")");
|
|
|
119 |
res = _sqlite_exec(g_sql_buf[0]);
|
|
|
120 |
if (_sqlite_error(res)) {
|
|
|
121 |
sdf_detach_sdf(mkString(iname));
|
|
|
122 |
goto sdf_import_sqlite_table__out;
|
|
|
123 |
}
|
|
|
124 |
|
|
|
125 |
_expand_buf(0, buflen1 + buflen3 + iname_len + 32 );
|
|
|
126 |
sprintf(g_sql_buf[0], "insert into [%s].sdf_data %s %s", iname, g_sql_buf[1], g_sql_buf[3]);
|
|
|
127 |
res = _sqlite_exec(g_sql_buf[0]);
|
|
|
128 |
if (_sqlite_error(res)) {
|
|
|
129 |
sdf_detach_sdf(mkString(iname));
|
|
|
130 |
goto sdf_import_sqlite_table__out;
|
|
|
131 |
}
|
|
|
132 |
|
|
|
133 |
/* create sexp sdf */
|
|
|
134 |
ret = _create_sdf_sexp(iname);
|
|
|
135 |
|
|
|
136 |
sdf_import_sqlite_table__out:
|
|
|
137 |
_sqlite_exec("detach [@@import@@]");
|
|
|
138 |
return ret;
|
|
|
139 |
}
|