The R Project SVN R-packages

Rev

Rev 3251 | Rev 3255 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3251 mrmanese 1
#include <stdio.h>
2
#include <string.h>
3
#include "R.h"
4
#include "Rdefines.h"
5
#include "Rinternals.h"
6
#include "sqlite3.h"
3252 mrmanese 7
#include "sqlite_dataframe.h"
3251 mrmanese 8
 
3252 mrmanese 9
SEXP sdf_create_sdf(SEXP df, SEXP name, SEXP sql_create) {
10
    SEXP ret;
11
    char *rname, *iname, *biname; 
12
    int file_idx = 0, namelen, res;
3251 mrmanese 13
 
3252 mrmanese 14
    /* check if arg name is supplied */
3251 mrmanese 15
    if (IS_CHARACTER(name)) {
3252 mrmanese 16
        rname = CHAR(STRING_ELT(name,0));
17
        if (!_is_r_sym(rname)) { /* error */ return R_NilValue; }
18
        namelen = strlen(rname);
19
        iname = R_alloc(namelen + 9, sizeof(char)); /* <name>10000.db\0 */
20
        sprintf(iname, "%s.db", rname);
3251 mrmanese 21
    } else if (name == R_NilValue) {
3252 mrmanese 22
        rname = "data";
23
        namelen = 5;
24
        iname = R_alloc(13, sizeof(char)); /* data10000.db\0 */
3251 mrmanese 25
        file_idx = 1;
3252 mrmanese 26
        sprintf(iname, "%s%d.db", rname, file_idx);
3251 mrmanese 27
    } else {
28
        /* how to error??? */
29
        return R_NilValue;
30
    }
31
 
3252 mrmanese 32
    /* here, iname will contain #{iname}.db */
3251 mrmanese 33
    do {
3252 mrmanese 34
        if (!_file_exists(iname)) break;
35
        namelen = sprintf(iname, "%s%d.db", rname, ++file_idx) - 3;
3251 mrmanese 36
    } while (file_idx < 10000);
37
 
38
    /* found a free number */
39
    if (file_idx < 10000) {
3252 mrmanese 40
        /* create a sdf db file by running "attach" statement to non-existent
41
         * db file
42
         */
43
        int sql_len, sql_len2, sql_len3, i, j;
44
        sqlite3_stmt *stmt;
45
 
46
        iname[namelen] = 0;  /* remove ".db" */
47
        sql_len = sprintf(g_sql_buf[0], "attach '%s.db' as %s", iname, iname);
48
 
49
        res = _sqlite_exec(g_sql_buf[0]);
50
        if (_sqlite_error(res)) return R_NilValue; /* duplicate dbname */
51
 
52
 
53
        /* 
54
         * create tables for the sdf db
55
         */
56
        SEXP names = GET_NAMES(df), variable, levels;
57
        int ncols = GET_LENGTH(names), type, *types;
58
        char *col_name, *class, *factor;
59
 
60
        /* TODO: put constraints on table after inserting everything? */
61
 
62
        /* create sdf_attributes table */
63
        sprintf(g_sql_buf[0], "create table [%s].sdf_attributes(attr text, "
64
                "value text, primary key (attr))", iname);
65
        res = _sqlite_exec(g_sql_buf[0]);
66
        sprintf(g_sql_buf[0], "insert into [%s].sdf_attributes values ('name',"
67
                "'%s');", iname, iname);
68
        _sqlite_exec(g_sql_buf[0]);
69
 
70
 
71
        /* 
72
         * create the create table and insert sql scripts by looping through
73
         * the columns of df
74
         */
75
        types = (int *)R_alloc(ncols, sizeof(int));
76
        sql_len = sprintf(g_sql_buf[0], "create table [%s].sdf_data ([row name] text", iname);
77
        sql_len2 = sprintf(g_sql_buf[1], "insert into [%s].sdf_data values(?", iname);
78
 
79
        for (i = 0; i < ncols; i++) {
80
            col_name = CHAR(STRING_ELT(names, i));
81
 
82
            /* add column definition to the create table sql */
83
            _expand_buf(0, sql_len+strlen(col_name)+10);
84
 
85
            variable = _getListElement(df, col_name);
86
            class = CHAR(STRING_ELT(GET_CLASS(variable), 0));
87
            type = TYPEOF(variable);
88
            types[i] = type;
89
 
90
            sql_len += sprintf(g_sql_buf[0]+sql_len, ", [%s] %s", col_name, 
91
                    _get_column_type(class, type));
92
 
93
            /* add handler to insert table sql */
94
            _expand_buf(1, sql_len+5);
95
            strcpy(g_sql_buf[1]+sql_len2, ",?");
96
            sql_len2 += 2; 
97
 
98
            /* create separate table for factors decode */
99
            if (strcmp(class, "factor") == 0 || strcmp(class, "ordered") == 0){
100
                sprintf(g_sql_buf[2], "create table [%s].[factor %s] ("
101
                        "level int, label text, primary key(level), "
102
                        "unique(label));", iname, col_name);
103
                res = _sqlite_exec(g_sql_buf[2]);
104
                if (_sqlite_error(res)) return R_NilValue; /* dup tbl name? */
105
 
106
                levels = GET_LEVELS(variable);
107
                sql_len3 = sprintf(g_sql_buf[2], "insert into [%s].[factor %s] values(?, ?);", iname, col_name);
108
                res = sqlite3_prepare(g_workspace, g_sql_buf[2], sql_len3, &stmt, NULL);
109
                if (_sqlite_error(res)) return R_NilValue; /* dup tbl name? */
110
 
111
                for (j = 0; j < GET_LENGTH(levels); j++) {
112
                    sqlite3_reset(stmt);
113
                    factor = CHAR(STRING_ELT(levels, j));
114
                    sqlite3_bind_int(stmt, 1, j+1);
115
                    sqlite3_bind_text(stmt, 2, factor, strlen(factor), SQLITE_STATIC);
116
                    sqlite3_step(stmt);
117
                }
118
                sqlite3_finalize(stmt);
119
            }
120
        }
121
 
122
        _expand_buf(0,sql_len+35);
123
        /* sql_len += sprintf(g_sql_buf[0]+sql_len, ", primary key([row name]));");*/
124
        sql_len += sprintf(g_sql_buf[0]+sql_len, ");");
125
        res = _sqlite_exec(g_sql_buf[0]);
126
        if (_sqlite_error(res)) return R_NilValue; /* why? */
127
 
128
        /*
129
         * add the data in df to the sdf
130
         */
131
        SEXP rownames = getAttrib(df, R_RowNamesSymbol);
132
        int nrows = GET_LENGTH(rownames);
133
        char *row_name;
134
 
135
        sql_len2 += sprintf(g_sql_buf[1]+sql_len2, ")");
136
        res = sqlite3_prepare(g_workspace, g_sql_buf[1], sql_len2, &stmt, NULL);
137
 
138
        for (i = 0; i < nrows; i++) {
139
            row_name = CHAR(STRING_ELT(rownames, i));
140
            sqlite3_reset(stmt);
141
 
142
            if (*row_name)
143
                sqlite3_bind_text(stmt, 1, row_name, strlen(row_name), SQLITE_STATIC);
144
            else
145
                sqlite3_bind_int(stmt, 1, i);
146
 
147
            for (j = 0; j < ncols; j++) {
148
                variable = VECTOR_ELT(df, j);
149
                switch(types[j]) {
150
                    case INTSXP : 
151
                        sqlite3_bind_int(stmt, j+2, INTEGER(variable)[i]);
152
                        break;
153
                    case REALSXP:
154
                        sqlite3_bind_double(stmt, j+2, REAL(variable)[i]);
155
                        break;
156
                    case CHARSXP:
157
                        col_name = CHAR(STRING_ELT(variable,i));
158
                        sqlite3_bind_text(stmt, j+2, col_name, strlen(col_name), SQLITE_STATIC);
159
                }
160
                /* TODO: handle NA's & NULL's */
161
            }
162
 
163
            res = sqlite3_step(stmt);
164
            if (res != SQLITE_DONE) { 
165
                sqlite3_finalize(stmt);
166
                Rprintf("ERROR: %s\n", sqlite3_errmsg(g_workspace));
167
                return R_NilValue; /* why? */
168
            }
169
        }
170
 
171
        sqlite3_finalize(stmt);
172
 
173
        /*
174
         * add the new sdf to the workspace
175
         */
176
        sprintf(g_sql_buf[0], "insert into workspace(filename, internal_name)"
177
                " values('%s.db','%s')", iname, iname);
178
        res = _sqlite_exec(g_sql_buf[0]);
179
        if (_sqlite_error(res)) return R_NilValue; /* why? */
180
 
181
        /*
182
         * create a new object representing the sdf
183
         */
184
        ret = _create_sdf_sexp(iname);
185
 
186
    } else {
187
        Rprintf("ERROR: cannot find a free internal name for %s", rname);
188
        ret = R_NilValue;
3251 mrmanese 189
    }
190
 
3252 mrmanese 191
    return ret;
192
}
193
 
194
SEXP sdf_get_names(SEXP sdf) {
195
    char *iname = CHAR(STRING_ELT(_getListElement(sdf, "iname"),0));
196
    int len = sprintf(g_sql_buf[0], "select * from [%s].sdf_data;", iname);
197
 
198
    sqlite3_stmt *stmt;
199
    int res;
200
 
201
    res = sqlite3_prepare(g_workspace, g_sql_buf[0], len, &stmt, NULL);
202
    if (_sqlite_error(res)) return R_NilValue;
203
 
204
    SEXP ret;
205
 
206
    len = sqlite3_column_count(stmt)-1;
207
    PROTECT(ret = NEW_CHARACTER(len));
208
 
209
    for (int i = 0; i < len; i++) {
210
        SET_STRING_ELT(ret, i, mkChar(sqlite3_column_name(stmt, i+1)));
211
    }
212
 
213
    sqlite3_finalize(stmt);
3251 mrmanese 214
    UNPROTECT(1);
215
    return ret;
216
}
217
 
3252 mrmanese 218
SEXP sdf_get_length(SEXP sdf) {
219
    char *iname = CHAR(STRING_ELT(_getListElement(sdf, "iname"),0));
220
    int len = sprintf(g_sql_buf[0], "select * from [%s].sdf_data;", iname);
3251 mrmanese 221
 
3252 mrmanese 222
    sqlite3_stmt *stmt;
223
    int res;
224
 
225
    res = sqlite3_prepare(g_workspace, g_sql_buf[0], len, &stmt, NULL);
226
    if (_sqlite_error(res)) return R_NilValue;
227
 
228
    SEXP ret;
229
 
230
    len = sqlite3_column_count(stmt)-1;
231
    PROTECT(ret = NEW_INTEGER(1));
232
    INTEGER(ret)[0] = len;
233
 
234
    sqlite3_finalize(stmt);
235
    UNPROTECT(1);
236
    return ret;
237
}
238
 
239
SEXP sdf_get_rows(SEXP sdf) {
240
    char *iname = CHAR(STRING_ELT(_getListElement(sdf, "iname"),0));
241
    char **out;
242
    int res, ncol, nrow;
243
    SEXP ret;
244
 
245
    sprintf(g_sql_buf[0], "select count(*) from [%s].sdf_data;", iname);
246
    res = sqlite3_get_table(g_workspace, g_sql_buf[0], &out, &nrow, &ncol, NULL);
247
    if (_sqlite_error(res)) return R_NilValue;
248
 
249
 
250
    if (nrow != 1) ret = R_NilValue;
251
    else {
252
        PROTECT(ret = NEW_INTEGER(1));
253
        INTEGER(ret)[0] = atoi(out[1]);
254
        UNPROTECT(1);
255
    }
256
 
257
    sqlite3_free_table(out);
258
    return ret;
259
}
260
 
261
 
262
 
263
 
264
 
3251 mrmanese 265
SEXP sopen(SEXP name) {
266
    char *filename;
267
 
268
    if (IS_CHARACTER(name)) {
269
        filename = CHAR(STRING_ELT(name,0));
270
        Rprintf("%s\n", filename);
271
    }
272
    /* sqlite3 *db;
273
    int res = sqlite3_open(filename, &db); */
274
    SEXP ret;
275
    PROTECT(ret = NEW_LOGICAL(1));
276
    LOGICAL(ret)[0] = IS_CHARACTER(name);
277
    /* sqlite3_close(db); */ 
278
    UNPROTECT(1);
279
    return ret;
280
}