void sg_wc_db__gid__create_table(SG_context * pCtx, sg_wc_db * pDb) { SG_ERR_CHECK_RETURN( sg_wc_db__tx__assert(pCtx, pDb) ); SG_ERR_CHECK_RETURN( sg_sqlite__exec__va(pCtx, pDb->psql, ("CREATE TABLE tbl_gid" " (" " alias_gid INTEGER PRIMARY KEY AUTOINCREMENT," " gid VARCHAR NOT NULL," " tmp INTEGER NOT NULL" " )")) ); SG_ERR_CHECK_RETURN( sg_sqlite__exec__va(pCtx, pDb->psql, ("CREATE UNIQUE INDEX index_gid ON tbl_gid ( gid )")) ); // put (0,"*undefined*") in the table as a GID string so that we // have a mapping for a fictional temporary id (for FOUND and // IGNORED items until we decide they need a real/permanent id). SG_ERR_CHECK_RETURN( sg_wc_db__gid__insert_known(pCtx, pDb, SG_WC_DB__ALIAS_GID__UNDEFINED, SG_WC_DB__GID__UNDEFINED) ); // put (1,"*null*)" in the table as a GID string so that we have a mapping // for a fictional parent of the root directory. this lets us // keep the non-null constraint on the column and avoid having // to special case it in the SQL. SG_ERR_CHECK_RETURN( sg_wc_db__gid__insert_known(pCtx, pDb, SG_WC_DB__ALIAS_GID__NULL_ROOT, SG_WC_DB__GID__NULL_ROOT) ); }
// TODO consider the possible perf benefits of changing this routine // to accept lots of changeset ids instead of just one, so it // can handle them all at once. void SG_treendx__update__multiple( SG_context* pCtx, SG_treendx* pTreeNdx, SG_stringarray* psa ) { SG_changeset* pcs = NULL; sqlite3_stmt* pStmt = NULL; SG_vhash* pvh_treepaths = NULL; SG_uint32 count_treepaths = 0; SG_uint32 count_changesets = 0; SG_uint32 ics = 0; SG_NULLARGCHECK_RETURN(psa); SG_NULLARGCHECK_RETURN(pTreeNdx); SG_ERR_CHECK( SG_stringarray__count(pCtx, psa, &count_changesets) ); SG_ERR_CHECK( sg_sqlite__exec__va(pCtx, pTreeNdx->psql, "BEGIN TRANSACTION; ") ); SG_ERR_CHECK( sg_sqlite__prepare(pCtx, pTreeNdx->psql, &pStmt, "INSERT OR IGNORE INTO treendx (gid, strpath) VALUES (?, ?)") ); for (ics=0; ics<count_changesets; ics++) { const char* psz_hid = NULL; SG_uint32 i = 0; SG_ERR_CHECK( SG_stringarray__get_nth(pCtx, psa, ics, &psz_hid) ); SG_ERR_CHECK( SG_changeset__load_from_repo(pCtx, pTreeNdx->pRepo, psz_hid, &pcs) ); SG_ERR_CHECK( SG_changeset__get_treepaths(pCtx, pcs, &pvh_treepaths) ); if (pvh_treepaths) { SG_ERR_CHECK( SG_vhash__count(pCtx, pvh_treepaths, &count_treepaths) ); for (i=0; i<count_treepaths; i++) { const char* psz_gid = NULL; const SG_variant* pv = NULL; const char* psz_path = NULL; SG_ERR_CHECK( SG_vhash__get_nth_pair(pCtx, pvh_treepaths, i, &psz_gid, &pv) ); SG_ERR_CHECK( SG_variant__get__sz(pCtx, pv, &psz_path) ); SG_ERR_CHECK( sg_sqlite__reset(pCtx, pStmt) ); SG_ERR_CHECK( sg_sqlite__clear_bindings(pCtx, pStmt) ); SG_ERR_CHECK( sg_sqlite__bind_text(pCtx, pStmt, 1, psz_gid) ); SG_ERR_CHECK( sg_sqlite__bind_text(pCtx, pStmt, 2, psz_path) ); SG_ERR_CHECK( sg_sqlite__step(pCtx, pStmt, SQLITE_DONE) ); } } SG_CHANGESET_NULLFREE(pCtx, pcs); } SG_ERR_CHECK( sg_sqlite__nullfinalize(pCtx, &pStmt) ); SG_ERR_CHECK( sg_sqlite__exec__va(pCtx, pTreeNdx->psql, "COMMIT TRANSACTION; ") ); fail: SG_CHANGESET_NULLFREE(pCtx, pcs); }
/** * Create an INDEX on the above table. * We probably only need this for the L0 cset * since we drive everything from it. If we * have tables for L1 (or others) we tend to * use them for random lookups from a loop or * something driven from L0, so we don't really * need indexes for them. But we DO allow it. * (See the tricks that UPDATE plays with the * DB.) * */ void sg_wc_db__tne__create_index(SG_context * pCtx, sg_wc_db * pDb, const sg_wc_db__cset_row * pCSetRow) { SG_ERR_CHECK_RETURN( sg_wc_db__tx__assert(pCtx, pDb) ); SG_ERR_CHECK_RETURN( sg_sqlite__exec__va(pCtx, pDb->psql, ("CREATE INDEX ndx_%s ON %s ( alias_gid_parent, entryname )"), pCSetRow->psz_tne_table_name, pCSetRow->psz_tne_table_name) ); }
void sg_wc_db__branch__create_table(SG_context * pCtx, sg_wc_db * pDb) { SG_ERR_CHECK_RETURN( sg_wc_db__tx__assert(pCtx, pDb) ); SG_ERR_CHECK_RETURN( sg_sqlite__exec__va(pCtx, pDb->psql, ("CREATE TABLE tbl_branch" " (" " id INTEGER PRIMARY KEY," " name VARCHAR NULL" " )")) ); }
void sg_wc_db__tne__drop_named_table(SG_context * pCtx, sg_wc_db * pDb, const sg_wc_db__cset_row * pCSetRow) { SG_ERR_CHECK_RETURN( sg_wc_db__tx__assert(pCtx, pDb) ); SG_ERR_CHECK_RETURN( sg_wc_db__tx__free_cached_statements(pCtx, pDb) ); // DROP INDEX is implicit when the referenced table is dropped. SG_ERR_CHECK_RETURN( sg_sqlite__exec__va(pCtx, pDb->psql, ("DROP TABLE IF EXISTS %s"), pCSetRow->psz_tne_table_name) ); }
void sg_wc_db__tne__create_named_table(SG_context * pCtx, sg_wc_db * pDb, const sg_wc_db__cset_row * pCSetRow) { SG_ERR_CHECK_RETURN( sg_wc_db__tx__assert(pCtx, pDb) ); SG_ERR_CHECK_RETURN( sg_sqlite__exec__va(pCtx, pDb->psql, ("CREATE TABLE %s" " (" " alias_gid INTEGER PRIMARY KEY REFERENCES tbl_gid( alias_gid )," " alias_gid_parent INTEGER NOT NULL REFERENCES tbl_gid( alias_gid )," " hid VARCHAR NOT NULL," " type INTEGER NOT NULL," " attrbits INTEGER NOT NULL," " entryname VARCHAR NOT NULL" " )"), pCSetRow->psz_tne_table_name) ); }