The R Project SVN R-packages

Rev

Rev 3282 | Rev 3308 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3282 Rev 3307
1
#include <stdio.h>
1
#include <stdio.h>
2
#include <string.h>
2
#include <string.h>
3
 
3
 
4
#define __SQLITE_WORKSPACE__
4
#define __SQLITE_WORKSPACE__
5
#include "sqlite_dataframe.h"
5
#include "sqlite_dataframe.h"
6
 
6
 
-
 
7
/* global variables */
7
sqlite3 *g_workspace = NULL;
8
sqlite3 *g_workspace = NULL;
8
char *g_sql_buf[NBUFS];
9
char *g_sql_buf[NBUFS];
9
int g_sql_buf_sz[NBUFS];
10
int g_sql_buf_sz[NBUFS];
10
 
11
 
-
 
12
/****************************************************************************
-
 
13
 * UTILITY FUNCTIONS
-
 
14
 ****************************************************************************/
-
 
15
 
-
 
16
/* test if a file is a sqlite database file */
11
sqlite3* _is_sqlitedb(char *filename) {
17
sqlite3* _is_sqlitedb(char *filename) {
12
    sqlite3 *db;
18
    sqlite3 *db;
13
    int res;
19
    int res;
14
    res = sqlite3_open(filename, &db);
20
    res = sqlite3_open(filename, &db);
15
    if (res != SQLITE_OK) { goto is_sqlitedb_FAIL; }
21
    if (res != SQLITE_OK) { goto is_sqlitedb_FAIL; }
16
 
22
 
17
    sqlite3_stmt *stmt; char *sql = "select * from sqlite_master";
23
    sqlite3_stmt *stmt; char *sql = "select * from sqlite_master";
18
    res = sqlite3_prepare(db, sql, -1, &stmt, 0);
24
    res = sqlite3_prepare(db, sql, -1, &stmt, 0);
19
    if (stmt != NULL) sqlite3_finalize(stmt);
25
    if (stmt != NULL) sqlite3_finalize(stmt);
20
    /*char **result_set;
26
    /*char **result_set;
21
    char nrow, ncol;
27
    char nrow, ncol;
22
    res = sqlite3_get_table(db, "select * from sqlite_master limit 0", 
28
    res = sqlite3_get_table(db, "select * from sqlite_master limit 0", 
23
            &result_set, &nrow, &ncol, NULL);
29
            &result_set, &nrow, &ncol, NULL);
24
    sqlite3_free_table(result_set);*/
30
    sqlite3_free_table(result_set);*/
25
    if (res != SQLITE_OK) goto is_sqlitedb_FAIL;
31
    if (res != SQLITE_OK) goto is_sqlitedb_FAIL;
26
 
32
 
27
    return db;
33
    return db;
28
 
34
 
29
is_sqlitedb_FAIL:
35
is_sqlitedb_FAIL:
30
    sqlite3_close(db);
36
    sqlite3_close(db);
31
    return NULL;
37
    return NULL;
32
}
38
}
33
 
39
 
-
 
40
/* test if a file is a SQLiteDF workspace */
34
sqlite3* _is_workspace(char *filename) {
41
sqlite3* _is_workspace(char *filename) {
35
    sqlite3* db = _is_sqlitedb(filename); 
42
    sqlite3* db = _is_sqlitedb(filename); 
36
 
43
 
37
    if (db != NULL) {
44
    if (db != NULL) {
38
        sqlite3_stmt *stmt;
45
        sqlite3_stmt *stmt;
39
        char *sql = "select * from workspace";
46
        char *sql = "select * from workspace";
40
        int res = sqlite3_prepare(db, sql, -1, &stmt, 0), ncols;
47
        int res = sqlite3_prepare(db, sql, -1, &stmt, 0), ncols;
41
        if ((res != SQLITE_OK) || /* no workspace table */
48
        if ((res != SQLITE_OK) || /* no workspace table */
42
              ((ncols = sqlite3_column_count(stmt)) != WORKSPACE_COLUMNS) ||
49
              ((ncols = sqlite3_column_count(stmt)) != WORKSPACE_COLUMNS) ||
43
              /* below also checks the ordering of the columns */
50
              /* below also checks the ordering of the columns */
44
              (strcmp(sqlite3_column_name(stmt, 0), "rel_filename") != 0) ||
51
              (strcmp(sqlite3_column_name(stmt, 0), "rel_filename") != 0) ||
45
              (strcmp(sqlite3_column_decltype(stmt, 0), "text") != 0) ||
52
              (strcmp(sqlite3_column_decltype(stmt, 0), "text") != 0) ||
46
              (strcmp(sqlite3_column_name(stmt, 1), "full_filename") != 0) ||
53
              (strcmp(sqlite3_column_name(stmt, 1), "full_filename") != 0) ||
47
              (strcmp(sqlite3_column_decltype(stmt, 1), "text") != 0) ||
54
              (strcmp(sqlite3_column_decltype(stmt, 1), "text") != 0) ||
48
              (strcmp(sqlite3_column_name(stmt, 2), "internal_name") != 0) ||
55
              (strcmp(sqlite3_column_name(stmt, 2), "internal_name") != 0) ||
49
              (strcmp(sqlite3_column_decltype(stmt, 2), "text") != 0)) {
56
              (strcmp(sqlite3_column_decltype(stmt, 2), "text") != 0)) {
50
            sqlite3_finalize(stmt); sqlite3_close(db); db = NULL;
57
            sqlite3_finalize(stmt); sqlite3_close(db); db = NULL;
51
        } else {
58
        } else {
52
            sqlite3_finalize(stmt);
59
            sqlite3_finalize(stmt);
53
        }
60
        }
54
    }
61
    }
55
 
62
 
56
    return db;
63
    return db;
57
}
64
}
58
 
65
 
-
 
66
/* test if a file is a sqlite.data.frame. returns the internal name of the
-
 
67
 * sdf if file is an sdf or NULL otherwise */
59
int _is_sdf(char *filename) {
68
char * _is_sdf2(char *filename) {
60
    sqlite3* db = _is_sqlitedb(filename); 
69
    sqlite3* db = _is_sqlitedb(filename); 
61
    int ret = (db != NULL);
70
    char *ret = (db == NULL) ? NULL : filename;
62
 
71
 
63
    if (ret) {
72
    if (ret) {
64
        sqlite3_stmt *stmt;
73
        sqlite3_stmt *stmt;
65
        char *sql = "select * from sdf_attributes";
74
        char *sql = "select * from sdf_attributes where attr='name'";
-
 
75
        int res, ncols;
66
        int res = sqlite3_prepare(db, sql, -1, &stmt, NULL), ncols;
76
        res = sqlite3_prepare(db, sql, -1, &stmt, NULL);
67
        ret = ((res == SQLITE_OK) && /* no attribute table */
77
        ret = (((res == SQLITE_OK) && /* no attribute table */
68
               ((ncols = sqlite3_column_count(stmt)) == 2) &&
78
               ((ncols = sqlite3_column_count(stmt)) == 2) &&
69
               (strcmp(sqlite3_column_name(stmt, 0), "attr") == 0) &&
79
               (strcmp(sqlite3_column_name(stmt, 0), "attr") == 0) &&
70
               (strcmp(sqlite3_column_decltype(stmt, 0), "text") == 0) &&
80
               (strcmp(sqlite3_column_decltype(stmt, 0), "text") == 0) &&
71
               (strcmp(sqlite3_column_name(stmt, 1), "value") == 0) &&
81
               (strcmp(sqlite3_column_name(stmt, 1), "value") == 0) &&
72
               (strcmp(sqlite3_column_decltype(stmt, 1), "text") == 0)) ;
82
               (strcmp(sqlite3_column_decltype(stmt, 1), "text") == 0))) ? ret : NULL ;
73
        
-
 
74
        if (!ret) goto _is_sdf_cleanup;
-
 
75
        sqlite3_finalize(stmt); 
-
 
76
        
83
        
-
 
84
        if (ret == NULL) goto _is_sdf_cleanup;
-
 
85
 
-
 
86
        /* get internal name */
-
 
87
        res = sqlite3_step(stmt);
-
 
88
        ret = (res == SQLITE_ROW) ? ret : NULL;
-
 
89
        if (ret == NULL) goto _is_sdf_cleanup;
-
 
90
 
-
 
91
        /* copy to buf2, because when we finalize stmt, we won't be sure
-
 
92
         * if sqlite3_column_text()'s ret value will still be there */
-
 
93
        strcpy(g_sql_buf[2], (char *)sqlite3_column_text(stmt, 1));
-
 
94
        ret = g_sql_buf[2];
-
 
95
        sqlite3_finalize(stmt);
77
        
96
        
78
        sql = "select * from sdf_data";
97
        sql = "select * from sdf_data";
79
        res = sqlite3_prepare(db, sql, -1, &stmt, NULL);
98
        res = sqlite3_prepare(db, sql, -1, &stmt, NULL);
80
        ret = (res == SQLITE_OK);  /* if not, missing data table */
99
        ret = (res == SQLITE_OK) ? ret : NULL;  /* if not, missing data table */
81
 
100
 
82
_is_sdf_cleanup:
101
_is_sdf_cleanup:
83
        sqlite3_finalize(stmt);
102
        sqlite3_finalize(stmt);
84
        sqlite3_close(db);
103
        sqlite3_close(db);
85
    }
104
    }
86
 
105
 
87
    return ret;
106
    return ret;
88
}
107
}
89
 
108
 
-
 
109
/* remove an sdf from the workspace */
90
void _delete_sdf2(char *iname) {
110
void _delete_sdf2(char *iname) {
91
    sprintf(g_sql_buf[2], "delete from workspace where internal_name='%s';", iname);
111
    sprintf(g_sql_buf[2], "delete from workspace where internal_name='%s';", iname);
92
    _sqlite_exec(g_sql_buf[2]);
112
    _sqlite_exec(g_sql_buf[2]);
93
}
113
}
94
 
114
 
-
 
115
/* add a sdf to the workspace */
95
int _add_sdf1(char *filename, char *internal_name) {
116
int _add_sdf1(char *filename, char *internal_name) {
96
    sprintf(g_sql_buf[1], "insert into workspace(rel_filename, full_filename, internal_name) values('%s', '%s', '%s')",
117
    sprintf(g_sql_buf[1], "insert into workspace(rel_filename, full_filename, internal_name) values('%s', '%s', '%s')",
97
            filename, _get_full_pathname2(filename), internal_name);
118
            filename, _get_full_pathname2(filename), internal_name);
98
    return _sqlite_exec(g_sql_buf[1]);
119
    return _sqlite_exec(g_sql_buf[1]);
99
}
120
}
100
 
121
 
-
 
122
 
-
 
123
static char* _get_sdf_detail2(char *iname, int what) {
-
 
124
    sqlite3_stmt *stmt;
-
 
125
    char * ret; int res;
-
 
126
 
-
 
127
    sprintf(g_sql_buf[2], "select full_filename from workspace where "
-
 
128
            "internal_name='%s'", iname);
-
 
129
    sqlite3_prepare(g_workspace, g_sql_buf[2], -1, &stmt, NULL);
-
 
130
    res = sqlite3_step(stmt);
-
 
131
    sqlite3_finalize(stmt);
-
 
132
 
-
 
133
    if (res == SQLITE_DONE) {
-
 
134
        ret = NULL;
-
 
135
    } else {
-
 
136
        ret = g_sql_buf[2];
-
 
137
        switch (what) {
-
 
138
            case SDF_DETAIL_EXISTS: 
-
 
139
                break; /* doesn't matter */
-
 
140
            case SDF_DETAIL_FULLFILENAME:
-
 
141
                strcpy(g_sql_buf[2], (char *)sqlite3_column_text(stmt, 0));
-
 
142
                break;
-
 
143
        }
-
 
144
    }
-
 
145
 
-
 
146
    return ret;
-
 
147
}
-
 
148
 
-
 
149
/* returns TRUE if sdf exists in the workspace */
-
 
150
int _sdf_exists2(char *iname) {
-
 
151
    return _get_sdf_detail2(iname, SDF_DETAIL_EXISTS) != NULL;
-
 
152
}
-
 
153
 
-
 
154
/****************************************************************************
-
 
155
 * WORKSPACE FUNCTIONS
-
 
156
 ****************************************************************************/
-
 
157
 
101
SEXP sdf_init_workspace() {
158
SEXP sdf_init_workspace() {
102
    int file_idx = 0, i;
159
    int file_idx = 0, i;
103
    char *basename = "workspace", *filename;
160
    char *basename = "workspace", *filename;
104
    SEXP ret;
161
    SEXP ret;
105
 
162
 
106
    /* initialize sql_buf */
163
    /* initialize sql_buf */
107
    for (i = 0; i < NBUFS; i++) {
164
    for (i = 0; i < NBUFS; i++) {
108
        if (g_sql_buf[i] == NULL) {
165
        if (g_sql_buf[i] == NULL) {
109
            g_sql_buf_sz[i] = 1024;
166
            g_sql_buf_sz[i] = 1024;
110
            g_sql_buf[i] = Calloc(g_sql_buf_sz[i], char);
167
            g_sql_buf[i] = Calloc(g_sql_buf_sz[i], char);
111
        }
168
        }
112
    }
169
    }
113
 
170
 
114
    /*
171
    /*
115
     * check for workspace.db, workspace1.db, ..., workspace9999.db if they
172
     * check for workspace.db, workspace1.db, ..., workspace9999.db if they
116
     * are valid workspace file. if one is found, use that as the workspace.
173
     * are valid workspace file. if one is found, use that as the workspace.
117
     */
174
     */
118
    filename = R_alloc(18, sizeof(char)); /* workspace10000.db\0 */
175
    filename = R_alloc(18, sizeof(char)); /* workspace10000.db\0 */
119
    sprintf(filename, "%s.db", basename);
176
    sprintf(filename, "%s.db", basename);
120
    while(_file_exists(filename) && file_idx < 10000) {
177
    while(_file_exists(filename) && file_idx < 10000) {
121
        if ((g_workspace = _is_workspace(filename)) != NULL) break;
178
        if ((g_workspace = _is_workspace(filename)) != NULL) break;
122
        /* warn("%s is not a workspace", filename) */
179
        /* warn("%s is not a workspace", filename) */
123
        sprintf(filename, "%s%d.db", basename, ++file_idx);
180
        sprintf(filename, "%s%d.db", basename, ++file_idx);
124
    }
181
    }
125
 
182
 
126
    PROTECT(ret = NEW_LOGICAL(1));
183
    PROTECT(ret = NEW_LOGICAL(1));
127
    if ((g_workspace == NULL) && (file_idx < 10000)) {
184
    if ((g_workspace == NULL) && (file_idx < 10000)) {
128
        /* no workspace found but there are still "available" file name */
185
        /* no workspace found but there are still "available" file name */
129
        /* if (file_idx) warn("workspace will be stored at #{filename}") */
186
        /* if (file_idx) warn("workspace will be stored at #{filename}") */
130
        sqlite3_open(filename, &g_workspace);
187
        sqlite3_open(filename, &g_workspace);
131
        _sqlite_exec("create table workspace(rel_filename text, full_filename text, internal_name text)");
188
        _sqlite_exec("create table workspace(rel_filename text, full_filename text, internal_name text)");
132
        LOGICAL(ret)[0] = TRUE;
189
        LOGICAL(ret)[0] = TRUE;
133
    } else if (g_workspace != NULL) {
190
    } else if (g_workspace != NULL) {
134
        /* a valid workspace has been found, load each of the tables */
191
        /* a valid workspace has been found, load each of the tables */
135
        int res, nrows, ncols; 
192
        int res, nrows, ncols; 
136
        char **result_set, *fname, *iname;
193
        char **result_set, *fname, *iname;
137
        
194
        
138
        res = sqlite3_get_table(g_workspace, "select * from workspace", 
195
        res = sqlite3_get_table(g_workspace, "select * from workspace", 
139
                &result_set, &nrows, &ncols, NULL);
196
                &result_set, &nrows, &ncols, NULL);
140
        
197
        
141
        if (res == SQLITE_OK && nrows >= 1 && ncols == WORKSPACE_COLUMNS) {
198
        if (res == SQLITE_OK && nrows >= 1 && ncols == WORKSPACE_COLUMNS) {
142
            for (i = 1; i <= nrows; i++) {
199
            for (i = 1; i <= nrows; i++) {
143
                /* we will use rel_filename in opening the file, so that
200
                /* we will use rel_filename in opening the file, so that
144
                 * if the user is "sensible", files will be dir agnostic */
201
                 * if the user is "sensible", files will be dir agnostic */
145
                fname = result_set[i*ncols]; iname = result_set[i*ncols+2];
202
                fname = result_set[i*ncols]; iname = result_set[i*ncols+2];
146
                
203
                
147
                if (!_file_exists(fname)) {
204
                if (!_file_exists(fname)) {
148
                    Rprintf("Warning: SDF %s does not exist.\n", iname);
205
                    Rprintf("Warning: SDF %s does not exist.\n", iname);
149
                    _delete_sdf2(iname);
206
                    _delete_sdf2(iname);
150
                    continue;
207
                    continue;
151
                }
208
                }
152
 
209
 
153
                if (!_is_sdf(fname)) {
210
                if (_is_sdf2(fname) == NULL) {
154
                    Rprintf("Warning: %s is not a valid SDF.\n", fname);
211
                    Rprintf("Warning: %s is not a valid SDF.\n", fname);
155
                    _delete_sdf2(iname);
212
                    _delete_sdf2(iname);
156
                    continue;
213
                    continue;
157
                }
214
                }
158
 
215
 
159
                /* attach db */
216
                /* attach db */
160
                sprintf(g_sql_buf[0], "attach '%s' as %s", fname, iname);
217
                sprintf(g_sql_buf[0], "attach '%s' as %s", fname, iname);
161
                _sqlite_exec(g_sql_buf[0]);
218
                _sqlite_exec(g_sql_buf[0]);
162
 
219
 
163
                /* update full_filename */
220
                /* update full_filename */
164
                sprintf(g_sql_buf[0], "update workspace set full_filename='%s' where iname='%s'", _get_full_pathname2(fname), iname);
221
                sprintf(g_sql_buf[0], "update workspace set full_filename='%s' where iname='%s'", _get_full_pathname2(fname), iname);
165
                _sqlite_exec(g_sql_buf[0]);
222
                _sqlite_exec(g_sql_buf[0]);
166
            }
223
            }
167
        }
224
        }
168
        sqlite3_free_table(result_set);
225
        sqlite3_free_table(result_set);
169
 
226
 
170
        LOGICAL(ret)[0] = TRUE;
227
        LOGICAL(ret)[0] = TRUE;
171
    } else { /* can't find nor create workspace */
228
    } else { /* can't find nor create workspace */
172
        LOGICAL(ret)[0] = FALSE;
229
        LOGICAL(ret)[0] = FALSE;
173
    }
230
    }
174
 
231
 
175
    UNPROTECT(1);
232
    UNPROTECT(1);
-
 
233
 
-
 
234
    /* register sqlite math functions */
-
 
235
    __register_vector_math();
176
    return ret;
236
    return ret;
177
}
237
}
178
        
238
        
179
 
239
 
180
    
240
    
181
SEXP sdf_finalize_workspace() {
241
SEXP sdf_finalize_workspace() {
182
    SEXP ret;
242
    SEXP ret;
183
    PROTECT(ret = NEW_LOGICAL(1)); 
243
    PROTECT(ret = NEW_LOGICAL(1)); 
184
    LOGICAL(ret)[0] = (sqlite3_close(g_workspace) == SQLITE_OK);
244
    LOGICAL(ret)[0] = (sqlite3_close(g_workspace) == SQLITE_OK);
185
    for (int i = 0; i < NBUFS; i++) Free(g_sql_buf[i]);
245
    for (int i = 0; i < NBUFS; i++) Free(g_sql_buf[i]);
186
    UNPROTECT(1);
246
    UNPROTECT(1);
187
    return ret;
247
    return ret;
188
} 
248
} 
189
 
249
 
190
 
250
 
191
SEXP sdf_list_sdfs(SEXP pattern) {
251
SEXP sdf_list_sdfs(SEXP pattern) {
192
    SEXP ret;
252
    SEXP ret;
193
    char **result;
253
    char **result;
194
    int nrow, ncol, res, i;
254
    int nrow, ncol, res, i;
195
 
255
 
196
    if (TYPEOF(pattern) != STRSXP) {
256
    if (TYPEOF(pattern) != STRSXP) {
197
        res = sqlite3_get_table(g_workspace, "select internal_name from workspace",
257
        res = sqlite3_get_table(g_workspace, "select internal_name from workspace",
198
                &result, &nrow, &ncol, NULL);
258
                &result, &nrow, &ncol, NULL);
199
    } else {
259
    } else {
200
        /* since internal_names must be a valid r symbol, 
260
        /* since internal_names must be a valid r symbol, 
201
           did not check for "'" */
261
           did not check for "'" */
202
        sprintf(g_sql_buf[0], "select internal_name from workspace where "
262
        sprintf(g_sql_buf[0], "select internal_name from workspace where "
203
                "internal_name like '%s%%'", CHAR(STRING_ELT(pattern, 0)));
263
                "internal_name like '%s%%'", CHAR(STRING_ELT(pattern, 0)));
204
        res = sqlite3_get_table(g_workspace, g_sql_buf[0], &result, &nrow,
264
        res = sqlite3_get_table(g_workspace, g_sql_buf[0], &result, &nrow,
205
                &ncol, NULL);
265
                &ncol, NULL);
206
    }
266
    }
207
 
267
 
208
    if (_sqlite_error(res)) return R_NilValue;
268
    if (_sqlite_error(res)) return R_NilValue;
209
    PROTECT(ret = NEW_CHARACTER(nrow));
269
    PROTECT(ret = NEW_CHARACTER(nrow));
210
    
270
    
211
    for (i = 0; i < nrow; i++) SET_STRING_ELT(ret, i, mkChar(result[i+1]));
271
    for (i = 0; i < nrow; i++) SET_STRING_ELT(ret, i, mkChar(result[i+1]));
212
 
272
 
213
    sqlite3_free_table(result);
273
    sqlite3_free_table(result);
214
    UNPROTECT(1);
274
    UNPROTECT(1);
215
    return ret;
275
    return ret;
216
}
276
}
217
 
277
 
218
SEXP sdf_get_sdf(SEXP name) {    
278
SEXP sdf_get_sdf(SEXP name) {    
219
    if (TYPEOF(name) != STRSXP) {
279
    if (TYPEOF(name) != STRSXP) {
220
        Rprintf("Error: Argument must be a string containing the SDF name.\n");
280
        Rprintf("Error: Argument must be a string containing the SDF name.\n");
221
        return R_NilValue;
281
        return R_NilValue;
222
    }
282
    }
223
 
283
 
224
    char *iname = CHAR(STRING_ELT(name, 0));
284
    char *iname = CHAR(STRING_ELT(name, 0));
225
    SEXP ret;
285
    SEXP ret;
226
    sqlite3_stmt *stmt;
286
    sqlite3_stmt *stmt;
227
    int res;
287
    int res;
228
 
288
 
229
    res = sqlite3_prepare(g_workspace, "select * from workspace where internal_name=?",
289
    res = sqlite3_prepare(g_workspace, "select * from workspace where internal_name=?",
230
            -1, &stmt, NULL);
290
            -1, &stmt, NULL);
231
    if (_sqlite_error(res)) return R_NilValue;
291
    if (_sqlite_error(res)) return R_NilValue;
232
 
292
 
233
    sqlite3_bind_text(stmt, 1, iname, strlen(iname), SQLITE_STATIC);
293
    sqlite3_bind_text(stmt, 1, iname, strlen(iname), SQLITE_STATIC);
234
    res = sqlite3_step(stmt);
294
    res = sqlite3_step(stmt);
235
 
295
 
236
    if (res == SQLITE_ROW) ret = _create_sdf_sexp(iname);
296
    if (res == SQLITE_ROW) ret = _create_sdf_sexp(iname);
237
    else ret = R_NilValue;
297
    else { Rprintf("Error: SDF %s not found.\n", iname); ret = R_NilValue; }
238
    
298
    
239
    sqlite3_finalize(stmt);
299
    sqlite3_finalize(stmt);
240
 
300
 
241
    return ret;
301
    return ret;
242
}
302
}
243
 
303
 
244
SEXP sdf_attach_sdf(SEXP filename, SEXP internal_name) {
304
SEXP sdf_attach_sdf(SEXP filename, SEXP internal_name) {
-
 
305
    /* when studying this, please be mindful of the global buffers used.
-
 
306
     * you have been warned */
245
    char *fname, *iname;
307
    char *fname, *iname, *iname_orig;;
246
    int fnamelen, res;
308
    int fnamelen, res;
247
    sqlite3_stmt *stmt;
309
    sqlite3_stmt *stmt;
248
 
310
 
249
    if (IS_CHARACTER(filename)) {
311
    if (IS_CHARACTER(filename)) {
250
        fname = CHAR_ELT(filename, 0);
312
        fname = CHAR_ELT(filename, 0);
251
        fnamelen = strlen(fname);
313
        fnamelen = strlen(fname);
252
    } else {
314
    } else {
253
        Rprintf("Error: filename argument must be a string.\n");
315
        Rprintf("Error: filename argument must be a string.\n");
254
        return R_NilValue;
316
        return R_NilValue;
255
    }
317
    }
256
 
318
 
257
    if (strcmp(fname+(fnamelen-3),".db") != 0) {
319
    if (strcmp(fname+(fnamelen-3),".db") != 0) {
258
        Rprintf("Error: Cannot attach because extension is not .db, which may cause problems [%s].\n");
320
        Rprintf("Error: Cannot attach because extension is not .db, which may cause problems [%s].\n");
259
        return R_NilValue;
321
        return R_NilValue;
260
    }
322
    }
261
 
323
 
-
 
324
    /* check if it is a valid sdf file */
-
 
325
    if (_is_sdf2(fname) == NULL) {
-
 
326
        Rprintf("Error: %s is not a valid SDF.\n", fname);
-
 
327
        return R_NilValue;
-
 
328
    } else {
-
 
329
        /* _is_sdf2 puts the orig iname in buf2. transfer data to buf0 since
-
 
330
         * functions called below will use buf2 */
-
 
331
        strcpy(g_sql_buf[0], g_sql_buf[2]);
-
 
332
        iname_orig = g_sql_buf[0];
-
 
333
    }
-
 
334
 
262
    /* check if it exists in the workspace already */
335
    /* check if file to be attached exists in the workspace already */
263
    _get_full_pathname2(fname);
336
    _get_full_pathname2(fname);
264
    res = sqlite3_prepare(g_workspace, "select internal_name from workspace where full_filename=?",
337
    res = sqlite3_prepare(g_workspace, "select internal_name from workspace where full_filename=?",
265
            -1, &stmt, NULL);
338
            -1, &stmt, NULL);
266
    sqlite3_bind_text(stmt, 1, g_sql_buf[2], strlen(g_sql_buf[2]), SQLITE_STATIC);
339
    sqlite3_bind_text(stmt, 1, g_sql_buf[2], -1, SQLITE_STATIC);
267
    res = sqlite3_step(stmt);
340
    res = sqlite3_step(stmt);
268
    if (res == SQLITE_ROW) {
341
    if (res == SQLITE_ROW) {
269
        Rprintf("Warning: That sdf is already attached as '%s'\n",
342
        Rprintf("Warning: That sdf is already attached as '%s'\n",
270
                sqlite3_column_text(stmt, 0));
343
                sqlite3_column_text(stmt, 0));
271
        sqlite3_finalize(stmt);
344
        sqlite3_finalize(stmt);
272
        return R_NilValue;
345
        return R_NilValue;
273
    } else sqlite3_finalize(stmt);
346
    } else sqlite3_finalize(stmt);
274
 
347
 
275
 
348
 
276
    /* internal_name checking and processing. */
349
    /* internal_name checking and processing. */
277
    int file_idx, inamelen;
-
 
278
    if (IS_CHARACTER(internal_name)) {
350
    if (IS_CHARACTER(internal_name)) {
-
 
351
        /* if name is specified, rename the sdf. original internal name is the
-
 
352
         * one stored at sdf_attribute */
279
        iname = CHAR_ELT(internal_name, 0);
353
        iname = CHAR_ELT(internal_name, 0);
280
        if (!_is_r_sym(iname)) {
354
        if (!_is_r_sym(iname)) {
281
            Rprintf("Error: %s is not a valid R symbol.", iname);
355
            Rprintf("Error: %s is not a valid R symbol.\n", iname);
282
            return R_NilValue;
356
            return R_NilValue;
283
        }
357
        }
284
 
-
 
285
        res = sqlite3_prepare(g_workspace, "select full_filename from workspace "
-
 
286
               " where internal_name=?", -1, &stmt, NULL);
-
 
287
        sqlite3_bind_text(stmt, 1, iname, strlen(iname), SQLITE_STATIC);
-
 
288
        res = sqlite3_step(stmt);
-
 
289
        if (res == SQLITE_ROW) {
-
 
290
            Rprintf("Warning: The sdf internal name '%s' is already taken by file %s.\n",
-
 
291
                    iname, sqlite3_column_text(stmt, 1));
-
 
292
            sqlite3_finalize(stmt);
-
 
293
            return R_NilValue;
-
 
294
        } else sqlite3_finalize(stmt);
-
 
295
    } else {
358
    } else {
296
        file_idx = 1;
-
 
297
        res = sqlite3_prepare(g_workspace, "select 1 from workspace "
-
 
298
               " where internal_name=?", -1, &stmt, NULL);
-
 
299
        
-
 
300
        do {
-
 
301
            inamelen = sprintf(g_sql_buf[0], "data%d", file_idx++);
359
        /* if no name is specified, use original internal name */
302
            sqlite3_bind_text(stmt, 1, g_sql_buf[0], inamelen, SQLITE_STATIC);
-
 
303
            res = sqlite3_step(stmt);
-
 
304
            sqlite3_reset(stmt);
-
 
305
        } while (res == SQLITE_ROW && file_idx < 10000);
-
 
306
 
-
 
307
        sqlite3_finalize(stmt);
-
 
308
 
-
 
309
        if (file_idx < 10000) {
-
 
310
            iname = g_sql_buf[0];
360
        iname = (char *)iname_orig;  /* g_sql_buf[0]! */
311
        } else {
-
 
312
            Rprintf("Error: Cannot find a free default file name.\n");
-
 
313
            return R_NilValue;
-
 
314
        }
-
 
315
    }
361
    }
316
 
362
 
317
 
-
 
318
    /* check if it is a valid sdf file */
363
    /* check if internal name is already used in the workspace */
-
 
364
    res = sqlite3_prepare(g_workspace, "select full_filename from workspace "
-
 
365
           " where internal_name=?", -1, &stmt, NULL);
-
 
366
    sqlite3_bind_text(stmt, 1, iname, -1, SQLITE_STATIC);
-
 
367
    res = sqlite3_step(stmt);
319
    if (!_is_sdf(fname)) {
368
    if (res == SQLITE_ROW) {
320
        Rprintf("Error: %s is not a valid SDF.\n", fname);
369
        Rprintf("Error: The sdf internal name '%s' is already used by file %s.\n",
-
 
370
                iname, sqlite3_column_text(stmt, 1));
-
 
371
        sqlite3_finalize(stmt);
321
        return R_NilValue;
372
        return R_NilValue;
322
    }
373
    } 
-
 
374
    sqlite3_finalize(stmt);
323
 
375
    
324
    /* finally, attach it. */
376
    /* finally, attach it. */
325
    sprintf(g_sql_buf[1], "attach '%s' as [%s]", fname, iname);
377
    sprintf(g_sql_buf[1], "attach '%s' as [%s]", fname, iname);
326
    res = _sqlite_exec(g_sql_buf[1]);
378
    res = _sqlite_exec(g_sql_buf[1]);
327
    if (_sqlite_error(res)) return R_NilValue;
379
    if (_sqlite_error(res)) return R_NilValue;
328
 
380
 
-
 
381
    /* if internal name found in newly-attached-SDF is the same as the
-
 
382
     * name wanted by the user, do nothing. otherwise, update sdf_attribute
-
 
383
     * on attached-SDF. this is like attachSdf then renameSdf */
-
 
384
    if (iname != iname_orig && strcmp(iname, iname_orig) != 0) {
-
 
385
        sprintf(g_sql_buf[1], "update [%s].sdf_attributes set value=? where attr='name'",
-
 
386
                iname);
-
 
387
        res = sqlite3_prepare(g_workspace, g_sql_buf[0], -1, &stmt, NULL);
-
 
388
        if (_sqlite_error(res)) { 
-
 
389
            sqlite3_finalize(stmt); 
-
 
390
            sprintf(g_sql_buf[1], "detach [%s]", iname);
-
 
391
            _sqlite_exec(g_sql_buf[1]);
-
 
392
            return R_NilValue;
-
 
393
        }
-
 
394
        res = sqlite3_bind_text(stmt, 1, iname, -1, SQLITE_STATIC);
-
 
395
        res = sqlite3_step(stmt);
-
 
396
        sqlite3_finalize(stmt);
-
 
397
    } 
-
 
398
 
329
    /* .. and update workspace */
399
    /* .. and update workspace */
330
    res = _add_sdf1(fname, iname);
400
    res = _add_sdf1(fname, iname);
331
    if (_sqlite_error(res)) return R_NilValue;
401
    if (_sqlite_error(res)) return R_NilValue;
332
 
402
 
333
    return _create_sdf_sexp(iname);
403
    return _create_sdf_sexp(iname);
334
}
404
}
335
 
405
 
336
SEXP sdf_detach_sdf(SEXP internal_name) {
406
SEXP sdf_detach_sdf(SEXP internal_name) {
337
    if (!IS_CHARACTER(internal_name)) {
407
    if (!IS_CHARACTER(internal_name)) {
338
        Rprintf("Error: iname argument is not a string.\n");
408
        Rprintf("Error: iname argument is not a string.\n");
339
        return R_NilValue;
409
        return R_NilValue;
340
    }
410
    }
341
 
411
 
342
    char *iname = CHAR_ELT(internal_name, 0);
412
    char *iname = CHAR_ELT(internal_name, 0);
343
    sprintf(g_sql_buf[0], "detach [%s]", iname);
413
    sprintf(g_sql_buf[0], "detach [%s]", iname);
344
 
414
 
345
    SEXP ret; int res;
415
    SEXP ret; int res;
346
    res = _sqlite_exec(g_sql_buf[0]);
416
    res = _sqlite_exec(g_sql_buf[0]);
347
    res = !_sqlite_error(res);
417
    res = !_sqlite_error(res);
348
 
418
 
349
    if (res) _delete_sdf2(iname);
419
    if (res) _delete_sdf2(iname);
350
 
420
 
351
    PROTECT(ret = NEW_LOGICAL(1));
421
    PROTECT(ret = NEW_LOGICAL(1));
352
    LOGICAL(ret)[0] = res;
422
    LOGICAL(ret)[0] = res;
353
    UNPROTECT(1);
423
    UNPROTECT(1);
354
 
424
 
355
    return ret;
425
    return ret;
356
}
426
}
-
 
427
 
-
 
428
SEXP sdf_rename_sdf(SEXP sdf, SEXP name) {
-
 
429
    char *iname, *path, *newname;
-
 
430
    SEXP ret;
-
 
431
    int res, ret_tmp;
-
 
432
 
-
 
433
    iname = SDF_INAME(sdf);
-
 
434
    newname = CHAR_ELT(name, 0);
-
 
435
    
-
 
436
    /* check if valid r name */
-
 
437
    if (!_is_r_sym(newname)) {
-
 
438
        Rprintf("Error: %s is not a valid R symbol.", iname);
-
 
439
        return R_NilValue;
-
 
440
    }
-
 
441
 
-
 
442
    /* check if sdf already exists */
-
 
443
    if (_sdf_exists2(newname)) { /* name is already taken */
-
 
444
        Rprintf("Error: the name \"%s\" is already taken.\n", newname);
-
 
445
        return R_NilValue;
-
 
446
    }
-
 
447
 
-
 
448
    /* get path of the sdf file, because we're goint to detach it */
-
 
449
    path = _get_sdf_detail2(iname, SDF_DETAIL_FULLFILENAME);
-
 
450
    if (path == NULL) {
-
 
451
        Rprintf("Error: no sdf named \"%s\" exists.\n", iname);
-
 
452
        return R_NilValue;
-
 
453
    }
-
 
454
 
-
 
455
    /* change name in sdf_attribute */
-
 
456
    sprintf(g_sql_buf[0], "update [%s].sdf_attributes set value='%s' "
-
 
457
            "where attr='name'", iname, newname);
-
 
458
    res = _sqlite_exec(g_sql_buf[0]);
-
 
459
    Rprintf("result: %d\n", res);
-
 
460
    /* if (_sqlite_error(res)) return R_NilValue; */
-
 
461
 
-
 
462
    /* detach and remove sdf from workspace */
-
 
463
    sprintf(g_sql_buf[0], "detach '%s'", iname);
-
 
464
    res = _sqlite_exec(g_sql_buf[0]);
-
 
465
    ret_tmp = !_sqlite_error(res);
-
 
466
 
-
 
467
    /* remove from ws, attach and add again to ws using new name */
-
 
468
    if (ret_tmp) {
-
 
469
        _delete_sdf2(iname);
-
 
470
        sprintf(g_sql_buf[0], "attach '%s' as '%s'", path, newname);
-
 
471
        res = _sqlite_exec(g_sql_buf[0]);
-
 
472
        ret_tmp = !_sqlite_error(res);
-
 
473
        
-
 
474
        /* TODO: make path relative! */
-
 
475
        _add_sdf1(iname, path);
-
 
476
    }
-
 
477
 
-
 
478
    PROTECT(ret = NEW_LOGICAL(1));
-
 
479
    LOGICAL(ret)[0] = ret_tmp;
-
 
480
    UNPROTECT(1);
-
 
481
 
-
 
482
    return ret;
-
 
483
}
-
 
484