3. SQLite Insert Statements

This section pertains to the actual SQLite insert statements that occur. Generally speaking, data in Worgle can be broken up into two perspectives: tangled data (the generated code for the compiler), and woven data (the markup and semantics).

3.1. SQLite Woven Data

Unlike Tangled data, woven data is inserted while the file is being parsed. As a result of this, the functionality is split up amongst a few functions instead of having one top-level function.

3.1.1. Top-level Weave Insert

Entry point for inserting woven data are the org file lists.

<<inserts>>=
worgle_db_insert_orglist(worg, db);

3.1.2. Org Filelist Insert

<<function_declarations>>=
void worgle_db_insert_orglist(worgle_d *worg, sqlite3 *db);

A thing to think about when inserting multiple orgs at once is the top-level section number. If left unattended, the internal number will always go back to 1 at the start of the file. To prevent this, the program must be able to save the top-most section number.

<<functions>>=
void worgle_db_insert_orglist(worgle_d *worg, sqlite3 *db)
{
    worgle_orgfile *orgs;
    worgle_textbuf *txt;
    int n;
    int sec;

    orgs = worg->orgs;
    txt = worg->buffers;
    sec = 0;
    for(n = 0; n < worg->nbuffers; n++) {
        worgle_db_insert_orgfile(worg,
                                 &orgs[n],
                                 &txt[n].filename,
                                 db,
                                 &sec);
    }
}

3.1.3. Org File Insert

<<function_declarations>>=
void worgle_db_insert_orgfile(worgle_d *worg,
                              worgle_orgfile *f,
                              worgle_string *filename,
                              sqlite3 *db,
                              int *sec);
<<functions>>=
void worgle_db_insert_orgfile(worgle_d *worg,
                              worgle_orgfile *f,
                              worgle_string *filename,
                              sqlite3 *db,
                              int *sec)
{
    size_t n;
    worgle_orglet *o;
    worgle_orglet *nxt;
    int curlvl;
    int counter[10];
    char strbuf[256];

    if (f->size <= 0) return;

    curlvl = 0;
    o = f->head;
    for (n = 1; n < 10; n++) counter[n] = 0;
    counter[0] = *sec;
    for (n = 0; n < f->size; n++) {
        nxt = o->next;
        switch (o->type) {
            case 0: /* Header */
                worgle_db_insert_header(worg,
                                        o,
                                        filename,
                                        &curlvl,
                                        counter,
                                        strbuf,
                                        db);
                break;
            case 1: /* Content */
                worgle_db_insert_content(worg,
                                         o,
                                         filename,
                                         curlvl,
                                         counter,
                                         strbuf,
                                         db);
                break;
            case 2: /* blkref */
                worgle_db_insert_blkref(worg,
                                        o,
                                        filename,
                                        curlvl,
                                        counter,
                                        strbuf,
                                        db);
                break;
        }
        o = nxt;
    }
    *sec = counter[0];
}

3.1.4. Header Insert

<<function_declarations>>=
void worgle_db_insert_header(worgle_d *worg,
                             worgle_orglet *o,
                             worgle_string *fname,
                             int *curlvl,
                             int *counter,
                             char *strbuf,
                             sqlite3 *db);
<<functions>>=
void worgle_db_insert_header(worgle_d *worg,
                             worgle_orglet *o,
                             worgle_string *fname,
                             int *curlvl,
                             int *counter,
                             char *strbuf,
                             sqlite3 *db)
{
    worgle_orglet_header *h;
    int diff;
    int n;
    int bufpos;
    sqlite3_stmt *stmt;
    int rc;
    int prog;

    h = o->ud;

    prog = worg->prog;

    if (*curlvl <= 0) *curlvl = 1;

    if (h->lvl > *curlvl) {
        diff = h->lvl - *curlvl;
        for (n = 1; n <= diff; n++) {
            counter[(*curlvl + n) - 1] = 0;
        }
    }

    counter[h->lvl - 1]++;

    bufpos = 0;
    for (n = 0; n < h->lvl; n++) {
        bufpos += sprintf(&strbuf[bufpos], "%d.", counter[n]);
    }
    *curlvl = h->lvl;

    insert_resource(db, prog, o->id, RES_HEADER);

    sqlite3_prepare_v2(db,
                       "INSERT INTO headers"
                       "(id, section, level, name, "
                       "filename, linum, next, program, "
                       "top_level) "
                       "VALUES(?1,?2,?3,?4,"
                       "?5,?6,?7,?8,?9);",
                       -1,
                       &stmt,
                       NULL);

    sqlite3_bind_int(stmt, 1, o->id);
    sqlite3_bind_text(stmt, 2, strbuf, bufpos, NULL);
    sqlite3_bind_int(stmt, 3, h->lvl);
    sqlite3_bind_text(stmt, 4,
                      h->str.str, h->str.size,
                      NULL);
    sqlite3_bind_text(stmt, 5,
                      fname->str, fname->size,
                      NULL);
    sqlite3_bind_int(stmt, 6, o->linum);

    if (o->next == NULL) {
        sqlite3_bind_int(stmt, 7, 0);
    } else {
        sqlite3_bind_int(stmt, 7, o->next->id);
    }

    sqlite3_bind_int(stmt, 8, prog);
    sqlite3_bind_int(stmt, 9, counter[0]);

    rc = sqlite3_step(stmt);

    if (rc != SQLITE_DONE) {
        fprintf(stderr,
                "SQLite error: %s\n",
                sqlite3_errmsg(db));
    }
    sqlite3_finalize(stmt);
}

3.1.5. Content Insert

Anything in between a header and the start of a code block is considered to be "content". Any time a new header or codeblock is started, this function will be inserted

<<function_declarations>>=
void worgle_db_insert_content(worgle_d *worg,
                              worgle_orglet *o,
                              worgle_string *fname,
                              int curlvl,
                              int *counter,
                              char *strbuf,
                              sqlite3 *db);
<<functions>>=
void worgle_db_insert_content(worgle_d *worg,
                              worgle_orglet *o,
                              worgle_string *fname,
                              int curlvl,
                              int *counter,
                              char *strbuf,
                              sqlite3 *db)
{
    worgle_orglet_content *c;
    int n;
    int bufpos;
    sqlite3_stmt *stmt;
    int rc;
    int prog;

    c = o->ud;

    prog = worg->prog;

    bufpos = 0;

    for (n = 0; n < curlvl; n++) {
        bufpos += sprintf(&strbuf[bufpos], "%d.",
                          counter[n]);
    }

    insert_resource(db, prog, o->id, RES_CONTENT);

    sqlite3_prepare_v2(db,
                       "INSERT INTO content"
                       "(program, id, section, "
                       "filename, linum, content, next)"
                       "VALUES(?1,?2,?3,?4,?5,?6,?7);",
                       -1,
                       &stmt,
                       NULL);

    sqlite3_bind_int(stmt, 1, prog);
    sqlite3_bind_int(stmt, 2, o->id);
    sqlite3_bind_text(stmt, 3, strbuf, bufpos, NULL);
    sqlite3_bind_text(stmt, 4,
                      fname->str, fname->size,
                      NULL);
    sqlite3_bind_int(stmt, 5, o->linum);

    sqlite3_bind_text(stmt, 6,
                      c->text.str, c->text.size,
                      NULL);

    if (o->next == NULL) {
        sqlite3_bind_int(stmt, 7, 0);
    } else {
        sqlite3_bind_int(stmt, 7, o->next->id);
    }

    rc = sqlite3_step(stmt);

    if (rc != SQLITE_DONE) {
        fprintf(stderr,
                "SQLite error: %s\n",
                sqlite3_errmsg(db));
    }

    sqlite3_finalize(stmt);
}

3.1.6. Block (Position) Insert

Any time a block is started, a note of the position it is in is stored as metadata. This will include the section, as well as line number and filename.

<<function_declarations>>=
void worgle_db_insert_blkref(worgle_d *worg,
                             worgle_orglet *o,
                             worgle_string *fname,
                             int curlvl,
                             int *counter,
                             char *strbuf,
                             sqlite3 *db);
<<functions>>=
void worgle_db_insert_blkref(worgle_d *worg,
                             worgle_orglet *o,
                             worgle_string *fname,
                             int curlvl,
                             int *counter,
                             char *strbuf,
                             sqlite3 *db)
{
    worgle_orglet_blkref *b;
    int n;
    int bufpos;
    sqlite3_stmt *stmt;
    int rc;
    int prog;

    b = o->ud;

    prog = worg->prog;

    bufpos = 0;

    for (n = 0; n < curlvl; n++) {
        bufpos += sprintf(&strbuf[bufpos], "%d.",
                          counter[n]);
    }

    insert_resource(db, prog, o->id, RES_BLKREF);

    sqlite3_prepare_v2(db,
                       "INSERT INTO blkref"
                       "(program, id, section, "
                       "filename, linum, next, ref, pos,"
                       "segoff, prev_lastseg)"
                       "VALUES(?1,?2,?3,?4,?5,?6,?7,?8,?9,?10);",
                       -1,
                       &stmt,
                       NULL);

    sqlite3_bind_int(stmt, 1, prog);
    sqlite3_bind_int(stmt, 2, o->id);
    sqlite3_bind_text(stmt, 3, strbuf, bufpos, NULL);
    sqlite3_bind_text(stmt, 4,
                      fname->str, fname->size,
                      NULL);
    sqlite3_bind_int(stmt, 5, o->linum);

    if (o->next == NULL) {
        sqlite3_bind_int(stmt, 6, 0);
    } else {
        sqlite3_bind_int(stmt, 6, o->next->id);
    }

    sqlite3_bind_int(stmt, 7, b->blk->id);
    sqlite3_bind_int(stmt, 8, b->pos);
    sqlite3_bind_int(stmt, 9, b->segoff);
    sqlite3_bind_int(stmt, 10, b->prev_lastseg);

    rc = sqlite3_step(stmt);

    if (rc != SQLITE_DONE) {
        fprintf(stderr,
                "SQLite error: %s\n",
                sqlite3_errmsg(db));
    }

    sqlite3_finalize(stmt);
}

3.2. SQLite Tangled Data

The way Worgle generates data is by recursively iterating through the file list. The SQLite table will be populated in the same way.

3.2.1. Top-level tangle insert

Table population tangle insert is done inside the function worgle_db_generate.

<<inserts>>=
worgle_db_insert_filelist(worg, &worg->flist, db);

3.2.2. Filelist Insert

The top-level part of the code walks through the file list inside of worgle_db_insert_filelist.

<<function_declarations>>=
void worgle_db_insert_filelist(worgle_d *worg,
                               worgle_filelist *flist,
                               sqlite3 *db);
<<functions>>=
void worgle_db_insert_filelist(worgle_d *worg,
                               worgle_filelist *flist,
                               sqlite3 *db)
{
    worgle_file *f;
    int n;

    f = flist->head;
    for(n = 0; n < flist->nfiles; n++) {
        worgle_db_insert_file(worg, f, db);
        f = f->nxt;
    }
}

3.2.3. File Insert

A file is inserted with the function worgle_db_insert_file.

<<function_declarations>>=
void worgle_db_insert_file(worgle_d *worg,
                           worgle_file *file,
                           sqlite3 *db);
<<functions>>=
void worgle_db_insert_file(worgle_d *worg,
                           worgle_file *file,
                           sqlite3 *db)
{
    worgle_long next_id;
    sqlite3_stmt *stmt;
    worgle_string *filename;
    int rc;
    int prog;

    if (file->nxt == NULL) next_id = 0;
    else next_id = file->nxt->id;

    prog = worg->prog;

    sqlite3_prepare_v2(db,
                       "INSERT INTO files"
                       "(id, next_file, filename, "
                       "top, program)"
                       "VALUES(?1, ?2, ?3, ?4, ?5);",
                       -1,
                       &stmt,
                       NULL);


    sqlite3_bind_int(stmt, 1, file->id);
    sqlite3_bind_int(stmt, 2, next_id);

    filename = &file->filename;
    sqlite3_bind_text(stmt, 3,
                      filename->str, filename->size,
                      NULL);

    sqlite3_bind_int(stmt, 4, file->top->id);
    sqlite3_bind_int(stmt, 5, prog);

    rc = sqlite3_step(stmt);

    if(rc != SQLITE_DONE) {
        fprintf(stderr,
                "SQLite error: %s\n",
                sqlite3_errmsg(db));
    }

    sqlite3_finalize(stmt);
    insert_resource(db, prog, file->id, RES_FILE);
    worgle_db_insert_block(worg, file->top, db);
}

3.2.4. Block Insert

A block is inserted with the function worgle_db_insert_block.

<<function_declarations>>=
void worgle_db_insert_block(worgle_d *worg,
                            worgle_block *block,
                            sqlite3 *db);
<<functions>>=
void worgle_db_insert_block(worgle_d *worg,
                            worgle_block *block,
                            sqlite3 *db)
{
    worgle_segment *s;
    int n;
    worgle_long next_segment;
    worgle_block *blk;
    worgle_hashmap *hm;
    sqlite3_stmt *stmt;
    worgle_string *name;
    int rc;
    int prog;

    s = block->head;
    hm = &worg->dict;

    prog = worg->prog;

    sqlite3_prepare_v2(db,
                       "INSERT INTO blocks"
                       "(id,"
                       "head_segment,"
                       "name,"
                       "program,"
                       "nblocks,"
                       "nsegs)\n"
                       "VALUES(?1, ?2, ?3, ?4, ?5, ?6);",
                       -1,
                       &stmt,
                       NULL);
    sqlite3_bind_int(stmt, 1, block->id);
    sqlite3_bind_int(stmt, 2, block->head->id);

    name = &block->name;
    sqlite3_bind_text(stmt, 3,
                      name->str, name->size,
                      NULL);
    sqlite3_bind_int(stmt, 4, prog);
    sqlite3_bind_int(stmt, 5, block->nblocks);
    sqlite3_bind_int(stmt, 6, block->nsegs);

    rc = sqlite3_step(stmt);

    if(rc != SQLITE_DONE) {
        fprintf(stderr,
                "SQLite error: %s\n",
                sqlite3_errmsg(db));
        return;
    }

    sqlite3_finalize(stmt);

    insert_resource(db, prog, block->id, RES_BLOCK);
    for(n = 0; n < block->nsegs; n++) {
        sqlite3_prepare_v2(db,
                        "INSERT INTO segments"
                        "(id,"
                        "type,"
                        "linum,"
                        "next_segment,"
                        "str,"
                        "filename,"
                        "program)\n"
                        "VALUES(?1,?2,?3,?4,?5,?6,?7);",
                        -1,
                        &stmt,
                        NULL);
        if(s->nxt != NULL) next_segment = s->nxt->id;
        else next_segment = 0;
        sqlite3_bind_int(stmt, 1, s->id);
        sqlite3_bind_int(stmt, 2, s->type);
        sqlite3_bind_int(stmt, 3, s->linum);
        sqlite3_bind_int(stmt, 4, next_segment);

        sqlite3_bind_text(stmt, 5,
                        s->str.str, s->str.size,
                        NULL);
        sqlite3_bind_text(stmt, 6,
                        s->filename->str, s->filename->size,
                        NULL);
        sqlite3_bind_int(stmt, 7, prog);
        if(rc != SQLITE_DONE) {
            fprintf(stderr,
                    "SQLite error: %s\n",
                    sqlite3_errmsg(db));
        }

        rc = sqlite3_step(stmt);

        if(rc != SQLITE_DONE) {
            fprintf(stderr,
                    "SQLite error: %s\n",
                    sqlite3_errmsg(db));
        }
        sqlite3_finalize(stmt);
        insert_resource(db, prog, s->id, RES_SEGMENT);
        if(worgle_segment_is_reference(s)) {
            if(!worgle_hashmap_find(hm, &s->str, &blk)) break;
            worgle_db_insert_block(worg, blk, db);
        }
        s = s->nxt;
    }
}



prev | home | next