The R Project SVN R-packages

Rev

Rev 3251 | Rev 3255 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3251 Rev 3252
Line 2... Line 2...
2
#include <string.h>
2
#include <string.h>
3
#include "R.h"
3
#include "R.h"
4
#include "Rdefines.h"
4
#include "Rdefines.h"
5
#include "Rinternals.h"
5
#include "Rinternals.h"
6
#include "sqlite3.h"
6
#include "sqlite3.h"
-
 
7
#include "sqlite_dataframe.h"
7
 
8
 
8
SEXP sdf_create_sdf(SEXP df, SEXP name) {
9
SEXP sdf_create_sdf(SEXP df, SEXP name, SEXP sql_create) {
9
    SEXP ret, tmp;
10
    SEXP ret;
10
    char *basename, *filename; 
11
    char *rname, *iname, *biname; 
11
    int file_idx = 0;
12
    int file_idx = 0, namelen, res;
12
 
13
 
13
    /* check if name exists */
14
    /* check if arg name is supplied */
14
    if (IS_CHARACTER(name)) {
15
    if (IS_CHARACTER(name)) {
15
        int baselen = strlen(CHAR(STRING_ELT(name,0)));
16
        rname = CHAR(STRING_ELT(name,0));
16
        basename = R_alloc(baselen, sizeof(char));
17
        if (!_is_r_sym(rname)) { /* error */ return R_NilValue; }
17
        strcpy(basename, CHAR(STRING_ELT(name,0)));
18
        namelen = strlen(rname);
18
        R_alloc(baselen + 9, sizeof(char)); /* <name>10000.db\0 */
19
        iname = R_alloc(namelen + 9, sizeof(char)); /* <name>10000.db\0 */
19
        sprintf(filename, "%s.db", basename);
20
        sprintf(iname, "%s.db", rname);
20
    } else if (name == R_NilValue) {
21
    } else if (name == R_NilValue) {
21
        basename = "data";
22
        rname = "data";
-
 
23
        namelen = 5;
22
        filename = R_alloc(13, sizeof(char)); /* data10000.db\0 */
24
        iname = R_alloc(13, sizeof(char)); /* data10000.db\0 */
23
        sprintf(filename, "%s.db", basename);
-
 
24
        file_idx = 1;
25
        file_idx = 1;
-
 
26
        sprintf(iname, "%s%d.db", rname, file_idx);
25
    } else {
27
    } else {
26
        /* how to error??? */
28
        /* how to error??? */
27
        return R_NilValue;
29
        return R_NilValue;
28
    }
30
    }
29
 
31
 
30
    FILE *f;
32
    /* here, iname will contain #{iname}.db */
31
    do {
33
    do {
32
        f = fopen(filename, "rb+");
-
 
33
        if (f == NULL) break;
34
        if (!_file_exists(iname)) break;
34
        fclose(f);
-
 
35
        sprintf(filename, "%s%d.db", file_idx, basename);
35
        namelen = sprintf(iname, "%s%d.db", rname, ++file_idx) - 3;
36
    } while (file_idx < 10000);
36
    } while (file_idx < 10000);
37
    
37
    
38
    /* found a free number */
38
    /* found a free number */
39
    if (file_idx < 10000) {
39
    if (file_idx < 10000) {
-
 
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
 
40
        /* create a sdf db file */
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
 
41
            /* attach to workspace.db */
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]);
42
            /* create tables */
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
        /*
43
            /* add rows to workspace */
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);
44
        /* register */
188
        ret = R_NilValue;
45
    }
189
    }
46
        
190
        
-
 
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);
-
 
214
    UNPROTECT(1);
-
 
215
    return ret;
-
 
216
}
-
 
217
 
-
 
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);
-
 
221
 
-
 
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;
47
    PROTECT(ret = NEW_LOGICAL(1));
231
    PROTECT(ret = NEW_INTEGER(1));
48
    LOGICAL(ret)[0] = (name == R_NilValue);
232
    INTEGER(ret)[0] = len;
-
 
233
 
-
 
234
    sqlite3_finalize(stmt);
49
    UNPROTECT(1);
235
    UNPROTECT(1);
50
    return ret;
236
    return ret;
51
}
237
}
52
 
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
 
53
 
264
 
54
SEXP sopen(SEXP name) {
265
SEXP sopen(SEXP name) {
55
    char *filename;
266
    char *filename;
56
    
267
    
57
    if (IS_CHARACTER(name)) {
268
    if (IS_CHARACTER(name)) {