The R Project SVN R-packages

Rev

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