The R Project SVN R-packages

Rev

Rev 3252 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#include <stdio.h>
#include <string.h>
#include "R.h"
#include "Rdefines.h"
#include "Rinternals.h"
#include "sqlite3.h"

sqlite3 *workspace = NULL;

sqlite3* _is_sqlitedb(filename) {
    sqlite3 *db;
    int res;
    res = sqlite3_open(filename, &db);
    if (res != SQLITE_OK) { goto is_sqlitedb_FAIL; }

    sqlite3_stmt *stmt; char *sql = "select * from workspace";
    res = sqlite3_prepare(db, sql, strlen(sql), &stmt, 0);
    if (stmt != NULL) sqlite3_finalize(stmt);
    /*char **result_set;
    char nrow, ncol;
    res = sqlite3_get_table(db, "select * from sqlite_master limit 0", 
            &result_set, &nrow, &ncol, NULL);
    sqlite3_free_table(result_set);*/
    if (res != SQLITE_OK) goto is_sqlitedb_FAIL;

    return db;

is_sqlitedb_FAIL:
    sqlite_close(db);
    return NULL;
}

sqlite3* _is_workspace(char *filename) {
    sqlite3* db = _is_sqlitedb(filename); 

    if (db != NULL) {
        sqlite3_stmt *stmt;
        char *sql = "select * from workspace";
        int res = sqlite3_prepare(db, sql, strlen(sql), &stmt, 0), ncols;
        if ((res != SQLITE_OK) || /* no workspace table */
              ((ncols = sqlite3_column_count(stmt)) != 2) ||
              /* below also checks the ordering of the columns */
              (strcmp(sqlite3_column_name(stmt, 0), "filename") != 0) ||
              (strcmp(sqlite3_column_decl(stmt, 0), "text") != 0) ||
              (strcmp(sqlite3_column_name(stmt, 1), "internal_name") != 0) ||
              (strcmp(sqlite3_column_decl(stmt, 1), "text") != 0)) {
            sqlite3_finalize(stmt); sqlite3_close(db); db = NULL;
        } else {
            sqlite3_finalize(stmt);
        }
    }

    return db;
}

int _is_sdf(char *filename) {
    sqlite3* db = _is_sqlitedb(filename); 

    if (db != NULL) {
        sqlite3_stmt *stmt;
        char *sql = "select * from sdf_attributes";
        int res = sqlite3_prepare(db, sql, strlen(sql), &stmt, 0), ncols;
        if ((res != SQLITE_OK) || /* no workspace table */
              ((ncols = sqlite3_column_count(stmt)) != 2) ||
              (strcmp(sqlite3_column_name(stmt, 0), "attr") != 0) ||
              (strcmp(sqlite3_column_decl(stmt, 0), "text") != 0) ||
              (strcmp(sqlite3_column_name(stmt, 1), "value") != 0) ||
              (strcmp(sqlite3_column_decl(stmt, 1), "text") != 0)) {
            sqlite3_finalize(stmt); sqlite3_close(db); return NULL;
        } 
        
        /* we also check the contents of sdf_attributes */
        sqlite3_finalize(stmt);
        
    }

    return db;
}

int _file_exists(char *filename) {
    FILE *f; int ret = FALSE;
    if ((f = fopen(filename, "rb")) != null) { fclose(f); ret = TRUE; }
    return ret;
}


SEXP sdf_init_workspace() {
    int file_idx = 0;
    char *basename = "workspace", *filename;
    FILE *f;
    SEXP ret;

    /* check for workspace.db, workspace1.db, ..., workspace9999.db if they
     * are valid workspace file. if one is found, use that as the workspace.
     */
    filename = R_alloc(18, sizeof(char)); /* workspace10000.db\0 */
    sprintf(filename, "%s.db", basename);
    while(_file_exists(filename) && file_idx < 10000); {
        if ((workspace = _is_workspace(filename)) != NULL) break;
        /* warn("%s is not a workspace", filename) */
        sprintf(filename, "%s%d.db", basename, ++file_idx);
    }

    PROTECT(ret = NEW_LOGICAL(1));
    if ((workspace == NULL) && (file_idx < 10000)) {
        /* no workspace found but there are still "available" file name */
        /* if (file_idx) warn("workspace will be stored at #{filename}") */
        sqlite3_open(filename, &workspace);
        sqlite3_exec(workspace, "create table workspace(filename text, internal_name text)", NULL, NULL, NULL);
        LOGICAL(ret)[0] = TRUE;
    } else if (file_idx >= 10000) {
        /* a valid workspace has been found, load each of the tables */
        int res, nrows, ncols; 
        char **result_set, *fname, *iname;
        
        res = sqlite3_get_table(workspace, "select * from workspace", 
                &result_set, &nrows, &ncols, NULL);
        
        if (res == SQLITE_OK && nrows > 1 && ncols == 2) {
            sqlite3_stmt *stmt;
            for (i = 1; i < nrows; i++) {
                fname = result_set[i*ncols]; iname = result_set[i*ncols+1];
                
                if (!_file_exists(fname)) {
                    /* warn('table does not exist: #{fname}'); */
                    continue;
                }

                if (!_is_sdf(fname)) {
                }

                sql = sqlite3_mprintf("attach '%s' as %s", fname, iname);
                res = sqlite3_prepare(db, sql, strlen(sql), &stmt, 0);
                if (res != SQL_OK) { 
                    /* warn('not an sqlite-db file */
                    continue;
                }
            }
        }
        sqlite3_free_table(result_set);

        LOGICAL(ret)[0] = TRUE;
    } else { /* can't find nor create workspace */
        LOGICAL(ret)[0] = FALSE;
    }

    UNPROTECT(1);
    return ret;
}