Пример #1
0
// 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);
}
void sg_wc_db__gid__get_gid_from_alias(SG_context * pCtx,
									   sg_wc_db * pDb,
									   SG_uint64 uiAliasGid,
									   char ** ppszGid)
{
	char * pszGid = NULL;
	int rc;

	// TODO 2011/08/01 Should this check for "*null*" and offer to return NULL ?

	//Caching the prepared statement is a pretty huge performance win.
	if (pDb->pSqliteStmt__get_gid_from_alias == NULL)
	{
		SG_ERR_CHECK(  sg_sqlite__prepare(pCtx, pDb->psql, &pDb->pSqliteStmt__get_gid_from_alias,
									  ("SELECT gid FROM tbl_gid WHERE alias_gid = ?"))  );
	}
	SG_ERR_CHECK(  sg_sqlite__bind_int64(pCtx, pDb->pSqliteStmt__get_gid_from_alias, 1, uiAliasGid)  );

	if ((rc=sqlite3_step(pDb->pSqliteStmt__get_gid_from_alias)) != SQLITE_ROW)
	{
		SG_int_to_string_buffer bufui64;
		SG_ERR_THROW2(  SG_ERR_SQLITE(rc),
						(pCtx, "sg_wc_db:tbl_gid can't find alias %s.",
						 SG_uint64_to_sz(uiAliasGid, bufui64))  );
	}

	SG_ERR_CHECK(  SG_STRDUP(pCtx, (const char *)sqlite3_column_text(pDb->pSqliteStmt__get_gid_from_alias, 0), &pszGid)  );
	SG_ERR_CHECK(  sg_sqlite__reset(pCtx, pDb->pSqliteStmt__get_gid_from_alias)  );
	SG_ERR_CHECK(  sg_sqlite__clear_bindings(pCtx, pDb->pSqliteStmt__get_gid_from_alias)  );

	*ppszGid = pszGid;
	return;

fail:
	SG_ERR_IGNORE(  sg_sqlite__reset(pCtx, pDb->pSqliteStmt__get_gid_from_alias)  );
	SG_ERR_IGNORE(  sg_sqlite__clear_bindings(pCtx, pDb->pSqliteStmt__get_gid_from_alias)  );
	SG_NULLFREE(pCtx, pszGid);
}
/**
 * BIND the fields for an INSERT or UPDATE a single row for this TreeNodeEntry (not
 * recursive) to the tne_L0 table.  Caller must compute the
 * GID aliases for the foreign keys and have already added
 * rows to tbl_gid as necessary.
 */
void sg_wc_db__tne__bind_insert(SG_context * pCtx,
								sqlite3_stmt * pStmt,
								SG_uint64 uiAliasGid,
								SG_uint64 uiAliasGidParent,
								const SG_treenode_entry * pTreenodeEntry)
{
	const char * pszHid = NULL;				// we do not own this
	const char * pszEntryname = NULL;		// we do not own this
	SG_int64 attrbits;
	SG_treenode_entry_type tneType;

	// pull all of the fields from the TNE.

	SG_ERR_CHECK(  SG_treenode_entry__get_hid_blob(pCtx, pTreenodeEntry, &pszHid)  );
	SG_ERR_CHECK(  SG_treenode_entry__get_entry_name(pCtx, pTreenodeEntry, &pszEntryname)  );
	SG_ERR_CHECK(  SG_treenode_entry__get_entry_type(pCtx, pTreenodeEntry, &tneType)  );
	SG_ERR_CHECK(  SG_treenode_entry__get_attribute_bits(pCtx, pTreenodeEntry, &attrbits)  );

#if TRACE_WC_ATTRBITS
	SG_ERR_IGNORE(  SG_console(pCtx, SG_CS_STDERR,
				   "TNE: bind_insert (%d) %s\n",
				   ((SG_uint32)attrbits),
				   pszEntryname)  );
#endif

	SG_ERR_CHECK(  sg_sqlite__reset(pCtx, pStmt)  );
	SG_ERR_CHECK(  sg_sqlite__clear_bindings(pCtx, pStmt)  );
	SG_ERR_CHECK(  sg_sqlite__bind_int64(          pCtx, pStmt, 1, uiAliasGid)  );
	SG_ERR_CHECK(  sg_sqlite__bind_int64(          pCtx, pStmt, 2, uiAliasGidParent)  );
	SG_ERR_CHECK(  sg_sqlite__bind_text__transient(pCtx, pStmt, 3, pszHid)  );
	SG_ERR_CHECK(  sg_sqlite__bind_int(            pCtx, pStmt, 4, tneType)  );
	SG_ERR_CHECK(  sg_sqlite__bind_int64(          pCtx, pStmt, 5, attrbits)  );
	SG_ERR_CHECK(  sg_sqlite__bind_text__transient(pCtx, pStmt, 6, pszEntryname)  );

fail:
	return;
}