示例#1
0
/*
** Load the record ID rid and up to N-1 closest ancestors into
** the "ok" table.
*/
void compute_ancestors(int rid, int N, int directOnly){
  Bag seen;
  PQueue queue;
  Stmt ins;
  Stmt q;
  bag_init(&seen);
  pqueuex_init(&queue);
  bag_insert(&seen, rid);
  pqueuex_insert(&queue, rid, 0.0, 0);
  db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
  db_prepare(&q,
    "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
    " WHERE a.cid=:rid %s",
    directOnly ? " AND a.isprim" : ""
  );
  while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){
    db_bind_int(&ins, ":rid", rid);
    db_step(&ins);
    db_reset(&ins);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int pid = db_column_int(&q, 0);
      double mtime = db_column_double(&q, 1);
      if( bag_insert(&seen, pid) ){
        pqueuex_insert(&queue, pid, -mtime, 0);
      }
    }
    db_reset(&q);
  }
  bag_clear(&seen);
  pqueuex_clear(&queue);
  db_finalize(&ins);
  db_finalize(&q);
}
示例#2
0
文件: util.c 项目: fadec/sqlpilot
/* Find or create a record the value of a column and return the id */
DBint64 id_of_with_insert(DB *db, const char *table, const char *column, const char *value, int *inserted)
{
    DBStatement *select, *insert;
    DBint64 id;
    char sql[256];

    snprintf(sql, sizeof(sql), "select id from %s where %s = ?;", table, column);
    select = db_prep(db, sql);
    db_bind_text(select, 1, value);

    if (db_step(select) == DB_DONE) {
        snprintf(sql, sizeof(sql), "insert into %s (%s) values (?);", table, column);
        insert = db_prep(db, sql);
        db_bind_text(insert, 1, value);
        db_step(insert);
        id = db_last_insert_rowid(db);
        db_finalize(insert);
        *inserted = TRUE;
    } else {
        id = db_column_int64(select, 0);
        *inserted = FALSE;
    }

    db_finalize(select);

    return id;
}
示例#3
0
/*
** Load the record ID rid and up to N-1 closest descendants into
** the "ok" table.
*/
void compute_descendants(int rid, int N){
  Bag seen;
  PQueue queue;
  Stmt ins;
  Stmt q;

  bag_init(&seen);
  pqueuex_init(&queue);
  bag_insert(&seen, rid);
  pqueuex_insert(&queue, rid, 0.0, 0);
  db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)");
  db_prepare(&q, "SELECT cid, mtime FROM plink WHERE pid=:rid");
  while( (N--)>0 && (rid = pqueuex_extract(&queue, 0))!=0 ){
    db_bind_int(&ins, ":rid", rid);
    db_step(&ins);
    db_reset(&ins);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int pid = db_column_int(&q, 0);
      double mtime = db_column_double(&q, 1);
      if( bag_insert(&seen, pid) ){
        pqueuex_insert(&queue, pid, mtime, 0);
      }
    }
    db_reset(&q);
  }
  bag_clear(&seen);
  pqueuex_clear(&queue);
  db_finalize(&ins);
  db_finalize(&q);
}
示例#4
0
/*
** Compute up to N direct ancestors (merge ancestors do not count)
** for the check-in rid and put them in a table named "ancestor".
** Label each generation with consecutive integers going backwards
** in time such that rid has the smallest generation number and the oldest
** direct ancestor as the largest generation number.
*/
void compute_direct_ancestors(int rid, int N){
  Stmt ins;
  Stmt q;
  int gen = 0;
  db_multi_exec(
    "CREATE TEMP TABLE IF NOT EXISTS ancestor(rid INTEGER UNIQUE NOT NULL,"
                                            " generation INTEGER PRIMARY KEY);"
    "DELETE FROM ancestor;"
    "INSERT INTO ancestor VALUES(%d, 0);", rid
  );
  db_prepare(&ins, "INSERT INTO ancestor VALUES(:rid, :gen)");
  db_prepare(&q,
    "SELECT pid FROM plink"
    " WHERE cid=:rid AND isprim"
  );
  while( (N--)>0 ){
    db_bind_int(&q, ":rid", rid);
    if( db_step(&q)!=SQLITE_ROW ) break;
    rid = db_column_int(&q, 0);
    db_reset(&q);
    gen++;
    db_bind_int(&ins, ":rid", rid);
    db_bind_int(&ins, ":gen", gen);
    db_step(&ins);
    db_reset(&ins);
  }
  db_finalize(&ins);
  db_finalize(&q);
}
/*
** Add to table zTab the record ID (rid) of every check-in that contains
** the file fid.
*/
void compute_uses_file(const char *zTab, int fid, int usesFlags){
  Bag seen;
  Bag pending;
  Stmt ins;
  Stmt q;
  int rid;

  bag_init(&seen);
  bag_init(&pending);
  db_prepare(&ins, "INSERT OR IGNORE INTO \"%s\" VALUES(:rid)", zTab);
  db_prepare(&q, "SELECT mid FROM mlink WHERE fid=%d", fid);
  while( db_step(&q)==SQLITE_ROW ){
    int mid = db_column_int(&q, 0);
    bag_insert(&pending, mid);
    bag_insert(&seen, mid);
    db_bind_int(&ins, ":rid", mid);
    db_step(&ins);
    db_reset(&ins);
  }
  db_finalize(&q);

  db_prepare(&q, "SELECT mid FROM mlink WHERE pid=%d", fid);
  while( db_step(&q)==SQLITE_ROW ){
    int mid = db_column_int(&q, 0);
    bag_insert(&seen, mid);
    if( usesFlags & USESFILE_DELETE ){
      db_bind_int(&ins, ":rid", mid);
      db_step(&ins);
      db_reset(&ins);
    }
  }
  db_finalize(&q);
  db_prepare(&q, "SELECT cid FROM plink WHERE pid=:rid");

  while( (rid = bag_first(&pending))!=0 ){
    bag_remove(&pending, rid);
    db_bind_int(&q, ":rid", rid);
    while( db_step(&q)==SQLITE_ROW ){
      int mid = db_column_int(&q, 0);
      if( bag_find(&seen, mid) ) continue;
      bag_insert(&seen, mid);
      bag_insert(&pending, mid);
      db_bind_int(&ins, ":rid", mid);
      db_step(&ins);
      db_reset(&ins);
    }
    db_reset(&q);
  }
  db_finalize(&q);
  db_finalize(&ins);
  bag_clear(&seen);
  bag_clear(&pending);
}
示例#6
0
/*
** Attempt to convert more full-text blobs into delta-blobs for
** storage efficiency.
*/
static void extra_deltification(void){
  Stmt q;
  int topid, previd, rid;
  int prevfnid, fnid;
  db_begin_transaction();
  db_prepare(&q,
     "SELECT rid FROM event, blob"
     " WHERE blob.rid=event.objid"
     "   AND event.type='ci'"
     "   AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
     " ORDER BY event.mtime DESC"
  );
  topid = previd = 0;
  while( db_step(&q)==SQLITE_ROW ){
    rid = db_column_int(&q, 0);
    if( topid==0 ){
      topid = previd = rid;
    }else{
      if( content_deltify(rid, previd, 0)==0 && previd!=topid ){
        content_deltify(rid, topid, 0);
      }
      previd = rid;
    }
  }
  db_finalize(&q);

  db_prepare(&q,
     "SELECT blob.rid, mlink.fnid FROM blob, mlink, plink"
     " WHERE NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
     "   AND mlink.fid=blob.rid"
     "   AND mlink.mid=plink.cid"
     "   AND plink.cid=mlink.mid"
     " ORDER BY mlink.fnid, plink.mtime DESC"
  );
  prevfnid = 0;
  while( db_step(&q)==SQLITE_ROW ){
    rid = db_column_int(&q, 0);
    fnid = db_column_int(&q, 1);
    if( prevfnid!=fnid ){
      prevfnid = fnid;
      topid = previd = rid;
    }else{
      if( content_deltify(rid, previd, 0)==0 && previd!=topid ){
        content_deltify(rid, topid, 0);
      }
      previd = rid;
    }
  }
  db_finalize(&q);

  db_end_transaction(0);
}
示例#7
0
/*
** Extract an item from content from the bundle
*/
static void bundle_extract_item(
  int blobid,          /* ID of the item to extract */
  Blob *pOut           /* Write the content into this blob */
){
  Stmt q;
  Blob x, basis, h1, h2;
  static Bag busy;

  db_prepare(&q, "SELECT uuid, delta, data FROM bblob"
                 " WHERE blobid=%d", blobid);
  if( db_step(&q)!=SQLITE_ROW ){
    db_finalize(&q);
    fossil_fatal("no such item: %d", blobid);
  }
  if( bag_find(&busy, blobid) ) fossil_fatal("delta loop");
  blob_zero(&x);
  db_column_blob(&q, 2, &x);
  blob_uncompress(&x, &x);
  if( db_column_type(&q,1)==SQLITE_INTEGER ){
    bundle_extract_item(db_column_int(&q,1), &basis);
    blob_delta_apply(&basis, &x, pOut);
    blob_reset(&basis);
    blob_reset(&x);
  }else if( db_column_type(&q,1)==SQLITE_TEXT ){
    int rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
                     db_column_text(&q,1));
    if( rid==0 ){
      fossil_fatal("cannot find delta basis %s", db_column_text(&q,1));
    }
    content_get(rid, &basis);
    db_column_blob(&q, 2, &x);
    blob_delta_apply(&basis, &x, pOut);
    blob_reset(&basis);
    blob_reset(&x);
  }else{
    *pOut = x;
  }
  blob_zero(&h1);
  db_column_blob(&q, 0, &h1);
  sha1sum_blob(pOut, &h2);
  if( blob_compare(&h1, &h2)!=0 ){
    fossil_fatal("SHA1 hash mismatch - wanted %s, got %s",
                 blob_str(&h1), blob_str(&h2));
  }
  blob_reset(&h1);
  blob_reset(&h2);
  bag_remove(&busy, blobid);
  db_finalize(&q);
}
示例#8
0
/*
**  fossil bundle ls BUNDLE ?OPTIONS?
**
** Display the content of a bundle in human-readable form.
*/
static void bundle_ls_cmd(void){
  Stmt q;
  sqlite3_int64 sumSz = 0;
  sqlite3_int64 sumLen = 0;
  int bDetails = find_option("details","l",0)!=0;
  verify_all_options();
  if( g.argc!=4 ) usage("ls BUNDLE ?OPTIONS?");
  bundle_attach_file(g.argv[3], "b1", 0);
  db_prepare(&q,
    "SELECT bcname, bcvalue FROM bconfig"
    " WHERE typeof(bcvalue)='text'"
    "   AND bcvalue NOT GLOB char(0x2a,0x0a,0x2a);"
  );
  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("%s: %s\n", db_column_text(&q,0), db_column_text(&q,1));
  }
  db_finalize(&q);
  fossil_print("%.78c\n",'-');
  if( bDetails ){
    db_prepare(&q,
      "SELECT blobid, substr(uuid,1,10), coalesce(substr(delta,1,10),''),"
      "       sz, length(data), notes"
      "  FROM bblob"
    );
    while( db_step(&q)==SQLITE_ROW ){
      fossil_print("%4d %10s %10s %8d %8d %s\n",
        db_column_int(&q,0),
        db_column_text(&q,1),
        db_column_text(&q,2),
        db_column_int(&q,3),
        db_column_int(&q,4),
        db_column_text(&q,5));
      sumSz += db_column_int(&q,3);
      sumLen += db_column_int(&q,4);
    }
    db_finalize(&q);
    fossil_print("%27s %8lld %8lld\n", "Total:", sumSz, sumLen);
  }else{
    db_prepare(&q,
      "SELECT substr(uuid,1,16), notes FROM bblob"
    );
    while( db_step(&q)==SQLITE_ROW ){
      fossil_print("%16s %s\n",
        db_column_text(&q,0),
        db_column_text(&q,1));
    }
    db_finalize(&q);
  }
}
示例#9
0
/*
** Change the storage of rid so that it is a delta of srcid.
**
** If rid is already a delta from some other place then no
** conversion occurs and this is a no-op unless force==1.
**
** Never generate a delta that carries a private artifact into a public
** artifact.  Otherwise, when we go to send the public artifact on a
** sync operation, the other end of the sync will never be able to receive
** the source of the delta.  It is OK to delta private->private and
** public->private and public->public.  Just no private->public delta.
**
** If srcid is a delta that depends on rid, then srcid is
** converted to undeltaed text.
**
** If either rid or srcid contain less than 50 bytes, or if the
** resulting delta does not achieve a compression of at least 25% 
** the rid is left untouched.
**
** Return 1 if a delta is made and 0 if no delta occurs.
*/
int content_deltify(int rid, int srcid, int force){
  int s;
  Blob data, src, delta;
  Stmt s1, s2;
  int rc = 0;

  if( srcid==rid ) return 0;
  if( !force && findSrcid(rid)>0 ) return 0;
  if( content_is_private(srcid) && !content_is_private(rid) ){
    return 0;
  }
  s = srcid;
  while( (s = findSrcid(s))>0 ){
    if( s==rid ){
      content_undelta(srcid);
      break;
    }
  }
  content_get(srcid, &src);
  if( blob_size(&src)<50 ){
    blob_reset(&src);
    return 0;
  }
  content_get(rid, &data);
  if( blob_size(&data)<50 ){
    blob_reset(&src);
    blob_reset(&data);
    return 0;
  }
  blob_delta_create(&src, &data, &delta);
  if( blob_size(&delta) <= blob_size(&data)*0.75 ){
    blob_compress(&delta, &delta);
    db_prepare(&s1, "UPDATE blob SET content=:data WHERE rid=%d", rid);
    db_prepare(&s2, "REPLACE INTO delta(rid,srcid)VALUES(%d,%d)", rid, srcid);
    db_bind_blob(&s1, ":data", &delta);
    db_begin_transaction();
    db_exec(&s1);
    db_exec(&s2);
    db_end_transaction(0);
    db_finalize(&s1);
    db_finalize(&s2);
    verify_before_commit(rid);
    rc = 1;
  }
  blob_reset(&src);
  blob_reset(&data);
  blob_reset(&delta);
  return rc;
}
示例#10
0
/*
** Load a vfile from a record ID.
*/
void load_vfile_from_rid(int vid){
  int rid, size;
  Stmt ins, ridq;
  Manifest *p;
  ManifestFile *pFile;

  if( db_exists("SELECT 1 FROM vfile WHERE vid=%d", vid) ){
    return;
  }

  db_begin_transaction();
  p = manifest_get(vid, CFTYPE_MANIFEST, 0);
  if( p==0 ) {
    db_end_transaction(1);
    return;
  }
  db_prepare(&ins,
    "INSERT INTO vfile(vid,isexe,islink,rid,mrid,pathname) "
    " VALUES(:vid,:isexe,:islink,:id,:id,:name)");
  db_prepare(&ridq, "SELECT rid,size FROM blob WHERE uuid=:uuid");
  db_bind_int(&ins, ":vid", vid);
  manifest_file_rewind(p);
  while( (pFile = manifest_file_next(p,0))!=0 ){
    if( pFile->zUuid==0 || uuid_is_shunned(pFile->zUuid) ) continue;
    db_bind_text(&ridq, ":uuid", pFile->zUuid);
    if( db_step(&ridq)==SQLITE_ROW ){
      rid = db_column_int(&ridq, 0);
      size = db_column_int(&ridq, 1);
    }else{
      rid = 0;
      size = 0;
    }
    db_reset(&ridq);
    if( rid==0 || size<0 ){
      fossil_warning("content missing for %s", pFile->zName);
      continue;
    }
    db_bind_int(&ins, ":isexe", ( manifest_file_mperm(pFile)==PERM_EXE ));
    db_bind_int(&ins, ":id", rid);
    db_bind_text(&ins, ":name", pFile->zName);
    db_bind_int(&ins, ":islink", ( manifest_file_mperm(pFile)==PERM_LNK ));
    db_step(&ins);
    db_reset(&ins);
  }
  db_finalize(&ridq);
  db_finalize(&ins);
  manifest_destroy(p);
  db_end_transaction(0);
}
示例#11
0
/*
** Query the database for all TICKET fields for the specific
** ticket whose name is given by the "name" CGI parameter.
** Load the values for all fields into the interpreter.
**
** Only load those fields which do not already exist as
** variables.
**
** Fields of the TICKET table that begin with "private_" are
** expanded using the db_reveal() function.  If g.perm.RdAddr is
** true, then the db_reveal() function will decode the content
** using the CONCEALED table so that the content legable.
** Otherwise, db_reveal() is a no-op and the content remains
** obscured.
*/
static void initializeVariablesFromDb(void){
  const char *zName;
  Stmt q;
  int i, n, size, j;

  zName = PD("name","-none-");
  db_prepare(&q, "SELECT datetime(tkt_mtime,'localtime') AS tkt_datetime, *"
                 "  FROM ticket WHERE tkt_uuid GLOB '%q*'", zName);
  if( db_step(&q)==SQLITE_ROW ){
    n = db_column_count(&q);
    for(i=0; i<n; i++){
      const char *zVal = db_column_text(&q, i);
      const char *zName = db_column_name(&q, i);
      char *zRevealed = 0;
      if( zVal==0 ){
        zVal = "";
      }else if( strncmp(zName, "private_", 8)==0 ){
        zVal = zRevealed = db_reveal(zVal);
      }
      for(j=0; j<nField; j++){
        if( fossil_strcmp(azField[j],zName)==0 ){
          azValue[j] = mprintf("%s", zVal);
          break;
        }
      }
      if( Th_Fetch(zName, &size)==0 ){
        Th_Store(zName, zVal);
      }
      free(zRevealed);
    }
  }else{
    db_finalize(&q);
    db_prepare(&q, "PRAGMA table_info(ticket)");
    if( Th_Fetch("tkt_uuid",&size)==0 ){
      Th_Store("tkt_uuid",zName);
    }
    while( db_step(&q)==SQLITE_ROW ){
      const char *zField = db_column_text(&q, 1);
      if( Th_Fetch(zField, &size)==0 ){
        Th_Store(zField, "");
      }
    }
    if( Th_Fetch("tkt_datetime",&size)==0 ){
      Th_Store("tkt_datetime","");
    }
  }
  db_finalize(&q);
}
示例#12
0
/*
** Obtain a list of all fields of the TICKET and TICKETCHNG tables.  Put them 
** in sorted order in aField[].
**
** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
** TICKETCHANGE tables exist, respectively.
*/
static void getAllTicketFields(void){
  Stmt q;
  int i;
  static int once = 0;
  if( once ) return;
  once = 1;
  db_prepare(&q, "PRAGMA table_info(ticket)");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFieldName = db_column_text(&q, 1);
    haveTicket = 1;
    if( memcmp(zFieldName,"tkt_",4)==0 ){
      if( strcmp(zFieldName, "tkt_ctime")==0 ) haveTicketCTime = 1;
      continue;
    }
    if( nField%10==0 ){
      aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) );
    }
    aField[nField].zName = mprintf("%s", zFieldName);
    aField[nField].mUsed = USEDBY_TICKET;
    nField++;
  }
  db_finalize(&q);
  db_prepare(&q, "PRAGMA table_info(ticketchng)");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFieldName = db_column_text(&q, 1);
    haveTicketChng = 1;
    if( memcmp(zFieldName,"tkt_",4)==0 ){
      if( strcmp(zFieldName,"tkt_rid")==0 ) haveTicketChngRid = 1;
      continue;
    }
    if( (i = fieldId(zFieldName))>=0 ){
      aField[i].mUsed |= USEDBY_TICKETCHNG;
      continue;
    }
    if( nField%10==0 ){
      aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) );
    }
    aField[nField].zName = mprintf("%s", zFieldName);
    aField[nField].mUsed = USEDBY_TICKETCHNG;
    nField++;
  }
  db_finalize(&q);
  qsort(aField, nField, sizeof(aField[0]), nameCmpr);
  for(i=0; i<nField; i++){
    aField[i].zValue = "";
    aField[i].zAppend = 0;
  }
}
示例#13
0
/*
** Print information about a particular check-in.
*/
void print_checkin_description(int rid, int indent, const char *zLabel){
  Stmt q;
  db_prepare(&q,
     "SELECT datetime(mtime%s),"
     "       coalesce(euser,user), coalesce(ecomment,comment),"
     "       (SELECT uuid FROM blob WHERE rid=%d),"
     "       (SELECT group_concat(substr(tagname,5), ', ') FROM tag, tagxref"
     "         WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid"
     "           AND tagxref.rid=%d AND tagxref.tagtype>0)"
     "  FROM event WHERE objid=%d", timeline_utc(), rid, rid, rid);
  if( db_step(&q)==SQLITE_ROW ){
    const char *zTagList = db_column_text(&q, 4);
    char *zCom;
    if( zTagList && zTagList[0] ){
      zCom = mprintf("%s (%s)", db_column_text(&q, 2), zTagList);
    }else{
      zCom = mprintf("%s", db_column_text(&q,2));
    }
    fossil_print("%-*s [%S] by %s on %s\n%*s",
       indent-1, zLabel,
       db_column_text(&q, 3),
       db_column_text(&q, 1),
       db_column_text(&q, 0),
       indent, "");
    comment_print(zCom, db_column_text(&q,2), indent, -1, g.comFmtFlags);
    fossil_free(zCom);
  }
  db_finalize(&q);
}
示例#14
0
文件: branch.c 项目: oopos/fossil
/*
** COMMAND: branch
**
** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
**
** Run various subcommands to manage branches of the open repository or
** of the repository identified by the -R or --repository option.
**
**    %fossil branch new BRANCH-NAME BASIS ?--bgcolor COLOR? ?--private?
**
**        Create a new branch BRANCH-NAME off of check-in BASIS.
**        You can optionally give the branch a default color.  The
**        --private option makes the branch private.
**
**    %fossil branch list ?-all | --closed?
**    %fossil branch ls ?-all | --closed?
**
**        List all branches.  Use --all or --closed to list all branches
**        or closed branches.  The default is to show only open branches.
**
** Options:
**    -R|--repository FILE       Run commands on repository FILE
*/
void branch_cmd(void){
  int n;
  const char *zCmd = "list";
  db_find_and_open_repository(0, 0);
  if( g.argc<2 ){
    usage("new|list|ls ...");
  }
  if( g.argc>=3 ) zCmd = g.argv[2];
  n = strlen(zCmd);
  if( strncmp(zCmd,"new",n)==0 ){
    branch_new();
  }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){
    Stmt q;
    int vid;
    char *zCurrent = 0;
    int showAll = find_option("all",0,0)!=0;
    int showClosed = find_option("closed",0,0)!=0;

    if( g.localOpen ){
      vid = db_lget_int("checkout", 0);
      zCurrent = db_text(0, "SELECT value FROM tagxref"
                            " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH);
    }
    branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0));
    while( db_step(&q)==SQLITE_ROW ){
      const char *zBr = db_column_text(&q, 0);
      int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0;
      fossil_print("%s%s\n", (isCur ? "* " : "  "), zBr);
    }
    db_finalize(&q);
  }else{
    fossil_panic("branch subcommand should be one of: "
                 "new list ls");
  }
}
示例#15
0
文件: merge.c 项目: digsrc/fossil
/*
** Check content that was received with rcvid and return true if any
** fork was created.
*/
int fossil_any_has_fork(int rcvid){
  static Stmt q;
  int fForkSeen = 0;

  if( rcvid==0 ) return 0;
  db_static_prepare(&q,
    "  SELECT pid FROM plink WHERE pid>0 AND isprim"
    "     AND cid IN (SELECT blob.rid FROM blob"
    "   WHERE rcvid=:rcvid)");
  db_bind_int(&q, ":rcvid", rcvid);
  while( !fForkSeen && db_step(&q)==SQLITE_ROW ){
    int pid = db_column_int(&q, 0);
    if( count_nonbranch_children(pid)>1 ){
      compute_leaves(pid,1);
      if( db_int(0, "SELECT count(*) FROM leaves")>1 ){
        int rid = db_int(0, "SELECT rid FROM leaves, event"
                            " WHERE event.objid=leaves.rid"
                            " ORDER BY event.mtime DESC LIMIT 1");
        fForkSeen = fossil_find_nearest_fork(rid, db_open_local(0))!=0;
      }
    }
  }
  db_finalize(&q);
  return fForkSeen;
}
示例#16
0
文件: branch.c 项目: 3615pipou/coopy
/*
** COMMAND: branch
**
** Usage: %fossil branch SUBCOMMAND ... ?-R|--repository FILE?
**
** Run various subcommands to manage branches of the open repository or
** of the repository identified by the -R or --repository option.
**
**    %fossil branch new BRANCH-NAME BASIS ?-bgcolor COLOR? 
**
**        Create a new branch BRANCH-NAME off of check-in BASIS.
**        You can optionally give the branch a default color.
**
**    %fossil branch list
**
**        List all branches
**
*/
void branch_cmd(void){
  int n;
  db_find_and_open_repository(1);
  if( g.argc<3 ){
    usage("new|list ...");
  }
  n = strlen(g.argv[2]);
  if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
    branch_new();
  }else if( n>=2 && strncmp(g.argv[2],"list",n)==0 ){
    Stmt q;
    db_prepare(&q,
      "%s"
      "   AND blob.rid IN (SELECT rid FROM tagxref"
      "                     WHERE tagid=%d AND tagtype==2 AND srcid!=0)"
      " ORDER BY event.mtime DESC",
      timeline_query_for_tty(), TAG_BRANCH
    );
    print_timeline(&q, 2000);
    db_finalize(&q);
  }else{
    fossil_panic("branch subcommand should be one of: "
                 "new list");
  }
}
示例#17
0
文件: tkt.c 项目: 3615pipou/coopy
/*
** Obtain a list of all fields of the TICKET table.  Put them 
** in sorted order in azField[].
**
** Also allocate space for azValue[] and azAppend[] and initialize
** all the values there to zero.
*/
static void getAllTicketFields(void){
  Stmt q;
  int i;
  if( nField>0 ) return;
  db_prepare(&q, "PRAGMA table_info(ticket)");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zField = db_column_text(&q, 1);
    if( strncmp(zField,"tkt_",4)==0 ) continue;
    if( nField%10==0 ){
      azField = realloc(azField, sizeof(azField)*3*(nField+10) );
      if( azField==0 ){
        fossil_fatal("out of memory");
      }
    }
    azField[nField] = mprintf("%s", zField);
    nField++;
  }
  db_finalize(&q);
  qsort(azField, nField, sizeof(azField[0]), nameCmpr);
  azAppend = &azField[nField];
  memset(azAppend, 0, sizeof(azAppend[0])*nField);
  azValue = &azAppend[nField];
  for(i=0; i<nField; i++){
    azValue[i] = "";
  }
}
示例#18
0
/*
** Query the database for all TICKET fields for the specific
** ticket whose name is given by the "name" CGI parameter.
** Load the values for all fields into the interpreter.
**
** Only load those fields which do not already exist as
** variables.
**
** Fields of the TICKET table that begin with "private_" are
** expanded using the db_reveal() function.  If g.perm.RdAddr is
** true, then the db_reveal() function will decode the content
** using the CONCEALED table so that the content legible.
** Otherwise, db_reveal() is a no-op and the content remains
** obscured.
*/
static void initializeVariablesFromDb(void){
  const char *zName;
  Stmt q;
  int i, n, size, j;

  zName = PD("name","-none-");
  db_prepare(&q, "SELECT datetime(tkt_mtime%s) AS tkt_datetime, *"
                 "  FROM ticket WHERE tkt_uuid GLOB '%q*'",
                 timeline_utc(), zName);
  if( db_step(&q)==SQLITE_ROW ){
    n = db_column_count(&q);
    for(i=0; i<n; i++){
      const char *zVal = db_column_text(&q, i);
      const char *zName = db_column_name(&q, i);
      char *zRevealed = 0;
      if( zVal==0 ){
        zVal = "";
      }else if( strncmp(zName, "private_", 8)==0 ){
        zVal = zRevealed = db_reveal(zVal);
      }
      if( (j = fieldId(zName))>=0 ){
        aField[j].zValue = mprintf("%s", zVal);
      }else if( memcmp(zName, "tkt_", 4)==0 && Th_Fetch(zName, &size)==0 ){
        Th_Store(zName, zVal);
      }
      free(zRevealed);
    }
  }
  db_finalize(&q);
  for(i=0; i<nField; i++){
    if( Th_Fetch(aField[i].zName, &size)==0 ){
      Th_Store(aField[i].zName, aField[i].zValue);
    }
  }
}
示例#19
0
/*
** Rebuild an entire entry in the TICKET table
*/
void ticket_rebuild_entry(const char *zTktUuid){
  char *zTag = mprintf("tkt-%s", zTktUuid);
  int tagid = tag_findid(zTag, 1);
  Stmt q;
  Manifest *pTicket;
  int tktid;
  int createFlag = 1;

  fossil_free(zTag);
  getAllTicketFields();
  if( haveTicket==0 ) return;
  tktid = db_int(0, "SELECT tkt_id FROM ticket WHERE tkt_uuid=%Q", zTktUuid);
  if( haveTicketChng ){
    db_multi_exec("DELETE FROM ticketchng WHERE tkt_id=%d;", tktid);
  }
  db_multi_exec("DELETE FROM ticket WHERE tkt_id=%d", tktid);
  tktid = 0;
  db_prepare(&q, "SELECT rid FROM tagxref WHERE tagid=%d ORDER BY mtime",tagid);
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    pTicket = manifest_get(rid, CFTYPE_TICKET, 0);
    if( pTicket ){
      tktid = ticket_insert(pTicket, rid, tktid);
      manifest_ticket_event(rid, pTicket, createFlag, tagid);
      manifest_destroy(pTicket);
    }
    createFlag = 0;
  }
  db_finalize(&q);
}
示例#20
0
/*
** Implement the "fossil bundle append BUNDLE FILE..." command.  Add
** the named files into the BUNDLE.  Create the BUNDLE if it does not
** alraedy exist.
*/
static void bundle_append_cmd(void){
  Blob content, hash;
  int i;
  Stmt q;

  verify_all_options();
  bundle_attach_file(g.argv[3], "b1", 1);
  db_prepare(&q,
    "INSERT INTO bblob(blobid, uuid, sz, delta, data, notes) "
    "VALUES(NULL, $uuid, $sz, NULL, $data, $filename)");
  db_begin_transaction();
  for(i=4; i<g.argc; i++){
    int sz;
    blob_read_from_file(&content, g.argv[i]);
    sz = blob_size(&content);
    sha1sum_blob(&content, &hash);
    blob_compress(&content, &content);
    db_bind_text(&q, "$uuid", blob_str(&hash));
    db_bind_int(&q, "$sz", sz);
    db_bind_blob(&q, "$data", &content);
    db_bind_text(&q, "$filename", g.argv[i]);
    db_step(&q);
    db_reset(&q);
    blob_reset(&content);
    blob_reset(&hash);
  }
  db_end_transaction(0);
  db_finalize(&q);
}
示例#21
0
文件: vfile.c 项目: ilchenkoanna/VCS
/*
** Compute an aggregate MD5 checksum over the repository image of every
** file in vid.  The file names are part of the checksum.  The resulting
** checksum is suitable for the R-card of a manifest.
**
** Return the resulting checksum in blob pOut.
*/
void vfile_aggregate_checksum_repository(int vid, Blob *pOut){
  Blob file;
  Stmt q;
  char zBuf[100];

  db_must_be_within_tree();
 
  db_prepare(&q, "SELECT pathname, origname, rid, file_is_selected(id)"
                 " FROM vfile"
                 " WHERE (NOT deleted OR NOT file_is_selected(id))"
                 "   AND rid>0 AND vid=%d"
                 " ORDER BY pathname /*scan*/",
                 vid);
  blob_zero(&file);
  md5sum_init();
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName = db_column_text(&q, 0);
    const char *zOrigName = db_column_text(&q, 1);
    int rid = db_column_int(&q, 2);
    int isSelected = db_column_int(&q, 3);
    if( zOrigName && !isSelected ) zName = zOrigName;
    md5sum_step_text(zName, -1);
    content_get(rid, &file);
    sqlite3_snprintf(sizeof(zBuf), zBuf, " %d\n", blob_size(&file));
    md5sum_step_text(zBuf, -1);
    /*printf("%s %s %s",md5sum_current_state(),zName,zBuf); fflush(stdout);*/
    md5sum_step_blob(&file);
    blob_reset(&file);
  }
  db_finalize(&q);
  md5sum_finish(pOut);
}
示例#22
0
/*
** WEBPAGE: /tagtimeline
*/
void tagtimeline_page(void){
  Stmt q;

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }

  style_header("Tagged Check-ins");
  style_submenu_element("List", "List", "taglist");
  login_anonymous_available();
  cgi_printf("<h2>Check-ins with non-propagating tags:</h2>\n");
  db_prepare(&q,
    "%s AND blob.rid IN (SELECT rid FROM tagxref"
    "                     WHERE tagtype=1 AND srcid>0"
    "                       AND tagid IN (SELECT tagid FROM tag "
    "                                      WHERE tagname GLOB 'sym-*'))"
    " ORDER BY event.mtime DESC",
    timeline_query_for_www()
  );
  www_print_timeline(&q, 0, 0, 0, 0);
  db_finalize(&q);
  cgi_printf("<br />\n"
         "<script  type=\"text/JavaScript\">\n"
         "function xin(id){\n"
         "}\n"
         "function xout(id){\n"
         "}\n"
         "</script>\n");
  style_footer();
}
示例#23
0
/*
** WEBPAGE: /taglist
*/
void taglist_page(void){
  Stmt q;

  login_check_credentials();
  if( !g.perm.Read ){
    login_needed();
  }
  login_anonymous_available();
  style_header("Tags");
  style_submenu_element("Timeline", "Timeline", "tagtimeline");
  cgi_printf("<h2>Non-propagating tags:</h2>\n");
  db_prepare(&q,
    "SELECT substr(tagname,5)"
    "  FROM tag"
    " WHERE EXISTS(SELECT 1 FROM tagxref"
    "               WHERE tagid=tag.tagid"
    "                 AND tagtype=1)"
    " AND tagname GLOB 'sym-*'"
    " ORDER BY tagname"
  );
  cgi_printf("<ul>\n");
  while( db_step(&q)==SQLITE_ROW ){
    const char *zName = db_column_text(&q, 0);
    if( g.perm.Hyperlink ){
      cgi_printf("<li>%z\n"
             "%h</a></li>\n",(xhref("class='taglink'","%R/timeline?t=%T",zName)),(zName));
    }else{
      cgi_printf("<li><span class=\"tagDsp\">%h</span></li>\n",(zName));
    }
  }
  cgi_printf("</ul>\n");
  db_finalize(&q);
  style_footer();
}
示例#24
0
/*
** COMMAND: test-orphans
**
** Search the repository for orphaned artifacts
*/
void test_orphans(void){
  Stmt q;
  int cnt = 0;

  db_find_and_open_repository(0, 0);
  db_multi_exec(
    "CREATE TEMP TABLE used(id INTEGER PRIMARY KEY ON CONFLICT IGNORE);"
    "INSERT INTO used SELECT mid FROM mlink;"  /* Manifests */
    "INSERT INTO used SELECT fid FROM mlink;"  /* Files */
    "INSERT INTO used SELECT srcid FROM tagxref WHERE srcid>0;" /* Tags */
    "INSERT INTO used SELECT rid FROM tagxref;" /* Wiki & tickets */
    "INSERT INTO used SELECT rid FROM attachment JOIN blob ON src=uuid;"
    "INSERT INTO used SELECT attachid FROM attachment;"
    "INSERT INTO used SELECT objid FROM event;"
  );
  db_prepare(&q, "SELECT rid, uuid, size FROM blob WHERE rid NOT IN used");
  while( db_step(&q)==SQLITE_ROW ){
    fossil_print("%7d %s size: %d\n",
      db_column_int(&q, 0),
      db_column_text(&q, 1),
      db_column_int(&q,2));
    cnt++;
  }
  db_finalize(&q);
  fossil_print("%d orphans\n", cnt);
}
示例#25
0
文件: name.c 项目: digsrc/fossil
/*
** Return the RID that is the "root" of the branch that contains
** check-in "rid" if inBranch==0 or the first check-in in the branch
** if inBranch==1.
*/
int start_of_branch(int rid, int inBranch){
  Stmt q;
  int rc;
  char *zBr;
  zBr = db_text("trunk","SELECT value FROM tagxref"
                        " WHERE rid=%d AND tagid=%d"
                        " AND tagtype>0",
                        rid, TAG_BRANCH);
  db_prepare(&q,
    "SELECT pid, EXISTS(SELECT 1 FROM tagxref"
                       " WHERE tagid=%d AND tagtype>0"
                       "   AND value=%Q AND rid=plink.pid)"
    "  FROM plink"
    " WHERE cid=:cid AND isprim",
    TAG_BRANCH, zBr
  );
  fossil_free(zBr);
  do{
    db_reset(&q);
    db_bind_int(&q, ":cid", rid);
    rc = db_step(&q);
    if( rc!=SQLITE_ROW ) break;
    if( inBranch && db_column_int(&q,1)==0 ) break;
    rid = db_column_int(&q, 0);
  }while( db_column_int(&q, 1)==1 && rid>0 );
  db_finalize(&q);
  return rid;
}
示例#26
0
/*
** Do a file-by-file comparison of the content of the repository and
** the working check-out on disk.  Report any errors.
*/
void vfile_compare_repository_to_disk(int vid){
  int rc;
  Stmt q;
  Blob disk, repo;
  char *zOut;
  
  db_must_be_within_tree();
  db_prepare(&q, 
      "SELECT %Q || pathname, pathname, rid FROM vfile"
      " WHERE NOT deleted AND vid=%d AND is_selected(id)"
      " ORDER BY if_selected(id, pathname, origname) /*scan*/",
      g.zLocalRoot, vid
  );
  md5sum_init();
  while( db_step(&q)==SQLITE_ROW ){
    const char *zFullpath = db_column_text(&q, 0);
    const char *zName = db_column_text(&q, 1);
    int rid = db_column_int(&q, 2);

    blob_zero(&disk);
    if( file_wd_islink(zFullpath) ){
      rc = blob_read_link(&disk, zFullpath);
    }else{
      rc = blob_read_from_file(&disk, zFullpath);
    }
    if( rc<0 ){
      fossil_print("ERROR: cannot read file [%s]\n", zFullpath);
      blob_reset(&disk);
      continue;
    }
    blob_zero(&repo);
    content_get(rid, &repo);
    if( blob_size(&repo)!=blob_size(&disk) ){
      fossil_print("ERROR: [%s] is %d bytes on disk but %d in the repository\n",
             zName, blob_size(&disk), blob_size(&repo));
      zOut = write_blob_to_temp_file(&repo);
      fossil_print("NOTICE: Repository version of [%s] stored in [%s]\n",
                   zName, zOut);
      sqlite3_free(zOut);
      blob_reset(&disk);
      blob_reset(&repo);
      continue;
    }
    if( blob_compare(&repo, &disk) ){
      fossil_print(
          "ERROR: [%s] is different on disk compared to the repository\n",
          zName);
      zOut = write_blob_to_temp_file(&repo);
      fossil_print("NOTICE: Repository version of [%s] stored in [%s]\n",
          zName, zOut);
      sqlite3_free(zOut);
    }
    blob_reset(&disk);
    blob_reset(&repo);
  }
  db_finalize(&q);
}
示例#27
0
/*
** Implementation of /json/timeline/wiki.
**
*/
cson_value * json_timeline_wiki(){
  /* This code is 95% the same as json_timeline_ci(), by the way. */
  cson_value * payV = NULL;
  cson_object * pay = NULL;
  cson_array * list = NULL;
  int check = 0;
  Stmt q = empty_Stmt;
  Blob sql = empty_blob;
  if( !g.perm.RdWiki && !g.perm.Read ){
    json_set_err( FSL_JSON_E_DENIED, "Wiki timeline requires 'o' or 'j' access.");
    return NULL;
  }
  payV = cson_value_new_object();
  pay = cson_value_get_object(payV);
  check = json_timeline_setup_sql( "w", &sql, pay );
  if(check){
    json_set_err(check, "Query initialization failed.");
    goto error;
  }

#if 0
  /* only for testing! */
  cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))));
#endif
  db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/);
  blob_reset(&sql);
  db_prepare(&q, "SELECT"
             " uuid AS uuid,"
             " mtime AS timestamp,"
#if 0
             " timestampString AS timestampString,"
#endif
             " comment AS comment, "
             " user AS user,"
             " eventType AS eventType"
#if 0
             /* can wiki pages have tags? */
             " tags AS tags," /*FIXME: split this into
                                a JSON array*/
             " tagId AS tagId,"
#endif
             " FROM json_timeline"
             " ORDER BY rowid");
  list = cson_new_array();
  json_stmt_to_array_of_obj(&q, list);
  cson_object_set(pay, "timeline", cson_array_value(list));
  goto ok;
  error:
  assert( 0 != g.json.resultCode );
  cson_value_free(payV);
  payV = NULL;
  ok:
  db_finalize(&q);
  blob_reset(&sql);
  return payV;
}
示例#28
0
/*
** COMMAND: test-missing
**
** Usage: %fossil test-missing
**
** Look at every artifact in the repository and verify that
** all references are satisfied.  Report any referenced artifacts
** that are missing or shunned.
**
** Options:
**
**    --notshunned          Do not report shunned artifacts
**    --quiet               Only show output if there are errors
*/
void test_missing(void){
  Stmt q;
  Blob content;
  int nErr = 0;
  int nArtifact = 0;
  int i;
  Manifest *p;
  unsigned flags = 0;
  int quietFlag;

  if( find_option("notshunned", 0, 0)!=0 ) flags |= MISSING_SHUNNED;
  quietFlag = find_option("quiet","q",0)!=0;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
  db_prepare(&q,
     "SELECT mid FROM mlink UNION "
     "SELECT srcid FROM tagxref WHERE srcid>0 UNION "
     "SELECT rid FROM tagxref UNION "
     "SELECT rid FROM attachment JOIN blob ON src=uuid UNION "
     "SELECT objid FROM event");
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    content_get(rid, &content);
    p = manifest_parse(&content, rid, 0);
    if( p ){
      nArtifact++;
      nErr += check_exists(p->zBaseline, flags, p, "baseline of", 0);
      nErr += check_exists(p->zAttachSrc, flags, p, "file of", 0);
      for(i=0; i<p->nFile; i++){
        nErr += check_exists(p->aFile[i].zUuid, flags, p, "file of", 
                             p->aFile[i].zName);
      }
      for(i=0; i<p->nParent; i++){
        nErr += check_exists(p->azParent[i], flags, p, "parent of", 0);
      }
      for(i=0; i<p->nCherrypick; i++){
        nErr +=  check_exists(p->aCherrypick[i].zCPTarget+1, flags, p,
                              "cherry-pick target of", 0);
        nErr +=  check_exists(p->aCherrypick[i].zCPBase, flags, p,
                              "cherry-pick baseline of", 0);
      }
      for(i=0; i<p->nCChild; i++){
        nErr += check_exists(p->azCChild[i], flags, p, "in", 0);
      }
      for(i=0; i<p->nTag; i++){
        nErr += check_exists(p->aTag[i].zUuid, flags, p, "target of", 0);
      }
      manifest_destroy(p);      
    }
  }
  db_finalize(&q);
  if( nErr>0 || quietFlag==0 ){
    fossil_print("%d missing or shunned references in %d control artifacts\n",
                 nErr, nArtifact);
  }
}
示例#29
0
文件: db_test.c 项目: fadec/sqlpilot
void test_db_prepare(void)
{
	DB *db;
	DBStatement *stmt;
	const char *sql_tail;
	db = db_open("test.db");
	db_prepare(db, "select * from memos;", &stmt, &sql_tail);
	assert_equal_str(sql_tail, "");
	db_finalize(stmt);
	db_close(db);
}
示例#30
0
文件: user.c 项目: 3615pipou/coopy
/*
** Figure out what user is at the controls.
**
**   (1)  Use the --user and -U command-line options.
**
**   (2)  If the local database is open, check in VVAR.
**
**   (3)  Check the default user in the repository
**
**   (4)  Try the USER environment variable.
**
**   (5)  Use the first user in the USER table.
**
** The user name is stored in g.zLogin.  The uid is in g.userUid.
*/
void user_select(void){
  Stmt s;

  if( g.userUid ) return;
  if( attempt_user(g.zLogin) ) return;

  if( g.localOpen && attempt_user(db_lget("default-user",0)) ) return;

  if( attempt_user(db_get("default-user", 0)) ) return;

  if( attempt_user(getenv("USER")) ) return;

  db_prepare(&s,
    "SELECT uid, login FROM user"
    " WHERE login NOT IN ('anonymous','nobody','reader','developer')"
  );
  if( db_step(&s)==SQLITE_ROW ){
    g.userUid = db_column_int(&s, 0);
    g.zLogin = mprintf("%s", db_column_text(&s, 1));
  }
  db_finalize(&s);

  if( g.userUid==0 ){
    db_prepare(&s, "SELECT uid, login FROM user");
    if( db_step(&s)==SQLITE_ROW ){
      g.userUid = db_column_int(&s, 0);
      g.zLogin = mprintf("%s", db_column_text(&s, 1));
    }
    db_finalize(&s);
  }

  if( g.userUid==0 ){
    db_multi_exec(
      "INSERT INTO user(login, pw, cap, info)"
      "VALUES('anonymous', '', 'cfghjkmnoqw', '')"
    );
    g.userUid = db_last_insert_rowid();
    g.zLogin = "******";
  }
}