File Annotation
Not logged in
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Copyright (c) 2006 D. Richard Hipp
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is free software; you can redistribute it and/or
dbda8d6ce9 2007-07-21       drh: ** modify it under the terms of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License version 2 as published by the Free Software Foundation.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This program is distributed in the hope that it will be useful,
dbda8d6ce9 2007-07-21       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
dbda8d6ce9 2007-07-21       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dbda8d6ce9 2007-07-21       drh: ** General Public License for more details.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** You should have received a copy of the GNU General Public
dbda8d6ce9 2007-07-21       drh: ** License along with this library; if not, write to the
dbda8d6ce9 2007-07-21       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
dbda8d6ce9 2007-07-21       drh: ** Boston, MA  02111-1307, USA.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Author contact information:
dbda8d6ce9 2007-07-21       drh: **   drh@hwaci.com
dbda8d6ce9 2007-07-21       drh: **   http://www.hwaci.com/drh/
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: *******************************************************************************
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This file contains code used to convert user-supplied object names into
dbda8d6ce9 2007-07-21       drh: ** canonical UUIDs.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** A user-supplied object name is any unique prefix of a valid UUID but
dbda8d6ce9 2007-07-21       drh: ** not necessarily in canonical form.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: #include "config.h"
dbda8d6ce9 2007-07-21       drh: #include "name.h"
dbda8d6ce9 2007-07-21       drh: #include <assert.h>
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** This routine takes a user-entered UUID which might be in mixed
dbda8d6ce9 2007-07-21       drh: ** case and might only be a prefix of the full UUID and converts it
dbda8d6ce9 2007-07-21       drh: ** into the full-length UUID in canonical form.
dbda8d6ce9 2007-07-21       drh: **
3b5514ed82 2007-09-22       drh: ** If the input is not a UUID or a UUID prefix, then try to resolve
3b5514ed82 2007-09-22       drh: ** the name as a tag.
3b5514ed82 2007-09-22       drh: **
dbda8d6ce9 2007-07-21       drh: ** Return the number of errors.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int name_to_uuid(Blob *pName, int iErrPriority){
dbda8d6ce9 2007-07-21       drh:   int rc;
dbda8d6ce9 2007-07-21       drh:   int sz;
dbda8d6ce9 2007-07-21       drh:   sz = blob_size(pName);
dbda8d6ce9 2007-07-21       drh:   if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){
3b5514ed82 2007-09-22       drh:     Stmt q;
3b5514ed82 2007-09-22       drh:     Blob uuid;
3b5514ed82 2007-09-22       drh: 
3b5514ed82 2007-09-22       drh:     db_prepare(&q,
3b5514ed82 2007-09-22       drh:       "SELECT (SELECT uuid FROM blob WHERE rid=objid)"
3b5514ed82 2007-09-22       drh:       "  FROM tagxref JOIN event ON rid=objid"
41cf3e7c1d 2008-02-06       drh:       " WHERE tagid=(SELECT tagid FROM tag WHERE tagname='sym-'||%B)"
09c4adeb6f 2007-09-22       drh:       "   AND tagtype>0"
3b5514ed82 2007-09-22       drh:       "   AND value IS NULL"
3b5514ed82 2007-09-22       drh:       " ORDER BY event.mtime DESC",
3b5514ed82 2007-09-22       drh:       pName
3b5514ed82 2007-09-22       drh:     );
3b5514ed82 2007-09-22       drh:     blob_zero(&uuid);
3b5514ed82 2007-09-22       drh:     if( db_step(&q)==SQLITE_ROW ){
3b5514ed82 2007-09-22       drh:       db_column_blob(&q, 0, &uuid);
3b5514ed82 2007-09-22       drh:     }
3b5514ed82 2007-09-22       drh:     db_finalize(&q);
3b5514ed82 2007-09-22       drh:     if( blob_size(&uuid)==0 ){
3b5514ed82 2007-09-22       drh:       fossil_error(iErrPriority, "not a valid object name: %b", pName);
3b5514ed82 2007-09-22       drh:       blob_reset(&uuid);
3b5514ed82 2007-09-22       drh:       return 1;
3b5514ed82 2007-09-22       drh:     }else{
3b5514ed82 2007-09-22       drh:       blob_reset(pName);
3b5514ed82 2007-09-22       drh:       *pName = uuid;
3b5514ed82 2007-09-22       drh:       return 0;
3b5514ed82 2007-09-22       drh:     }
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_materialize(pName);
dbda8d6ce9 2007-07-21       drh:   canonical16(blob_buffer(pName), sz);
dbda8d6ce9 2007-07-21       drh:   if( sz==UUID_SIZE ){
dbda8d6ce9 2007-07-21       drh:     rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName);
dbda8d6ce9 2007-07-21       drh:     if( rc ){
dbda8d6ce9 2007-07-21       drh:       fossil_error(iErrPriority, "unknown object: %b", pName);
dbda8d6ce9 2007-07-21       drh:       blob_reset(pName);
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:   }else if( sz<UUID_SIZE && sz>=4 ){
dbda8d6ce9 2007-07-21       drh:     char zOrig[UUID_SIZE+1];
dbda8d6ce9 2007-07-21       drh:     memcpy(zOrig, blob_buffer(pName), sz);
dbda8d6ce9 2007-07-21       drh:     zOrig[sz] = 0;
dbda8d6ce9 2007-07-21       drh:     blob_reset(pName);
dbda8d6ce9 2007-07-21       drh:     db_blob(pName, "SELECT uuid FROM blob WHERE uuid>='%s'", zOrig);
dbda8d6ce9 2007-07-21       drh:     if( blob_size(pName)!=UUID_SIZE ){
dbda8d6ce9 2007-07-21       drh:       fossil_error(iErrPriority, "no match: %s", zOrig);
dbda8d6ce9 2007-07-21       drh:       rc = 1;
dbda8d6ce9 2007-07-21       drh:     }else{
dbda8d6ce9 2007-07-21       drh:       zOrig[sz-1]++;
dbda8d6ce9 2007-07-21       drh:       if( db_exists("SELECT 1 FROM blob WHERE uuid>%B AND uuid<'%s'",
dbda8d6ce9 2007-07-21       drh:                     pName, zOrig) ){
dbda8d6ce9 2007-07-21       drh:          zOrig[sz-1]--;
dbda8d6ce9 2007-07-21       drh:          fossil_error(iErrPriority, "non-unique name prefix: %s", zOrig);
dbda8d6ce9 2007-07-21       drh:          rc = 1;
dbda8d6ce9 2007-07-21       drh:       }else{
dbda8d6ce9 2007-07-21       drh:          rc = 0;
dbda8d6ce9 2007-07-21       drh:       }
dbda8d6ce9 2007-07-21       drh:     }
e63a9fd9d0 2007-09-25       jnc:   }else{
e63a9fd9d0 2007-09-25       jnc:     rc = 0;
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   return rc;
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** COMMAND:  test-name-to-uuid
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** Convert a name to a full UUID.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: void test_name_to_uuid(void){
dbda8d6ce9 2007-07-21       drh:   int i;
dbda8d6ce9 2007-07-21       drh:   Blob name;
dbda8d6ce9 2007-07-21       drh:   db_must_be_within_tree();
dbda8d6ce9 2007-07-21       drh:   for(i=2; i<g.argc; i++){
dbda8d6ce9 2007-07-21       drh:     blob_init(&name, g.argv[i], -1);
dbda8d6ce9 2007-07-21       drh:     printf("%s -> ", g.argv[i]);
dbda8d6ce9 2007-07-21       drh:     if( name_to_uuid(&name, 1) ){
dbda8d6ce9 2007-07-21       drh:       printf("ERROR: %s\n", g.zErrMsg);
dbda8d6ce9 2007-07-21       drh:       fossil_error_reset();
dbda8d6ce9 2007-07-21       drh:     }else{
dbda8d6ce9 2007-07-21       drh:       printf("%s\n", blob_buffer(&name));
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:     blob_reset(&name);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh: }
dbda8d6ce9 2007-07-21       drh: 
dbda8d6ce9 2007-07-21       drh: /*
dbda8d6ce9 2007-07-21       drh: ** Convert a name to a rid.  If the name is a small integer value then
dbda8d6ce9 2007-07-21       drh: ** just use atoi() to do the conversion.  If the name contains alphabetic
dbda8d6ce9 2007-07-21       drh: ** characters or is not an existing rid, then use name_to_uuid then
dbda8d6ce9 2007-07-21       drh: ** convert the uuid to a rid.
dbda8d6ce9 2007-07-21       drh: **
dbda8d6ce9 2007-07-21       drh: ** This routine is used in test routines to resolve command-line inputs
dbda8d6ce9 2007-07-21       drh: ** into a rid.
dbda8d6ce9 2007-07-21       drh: */
dbda8d6ce9 2007-07-21       drh: int name_to_rid(const char *zName){
dbda8d6ce9 2007-07-21       drh:   int i;
dbda8d6ce9 2007-07-21       drh:   int rid;
dbda8d6ce9 2007-07-21       drh:   Blob name;
dbda8d6ce9 2007-07-21       drh:   for(i=0; zName[i] && isdigit(zName[i]); i++){}
dbda8d6ce9 2007-07-21       drh:   if( zName[i]==0 ){
dbda8d6ce9 2007-07-21       drh:     rid = atoi(zName);
dbda8d6ce9 2007-07-21       drh:     if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){
dbda8d6ce9 2007-07-21       drh:       return rid;
dbda8d6ce9 2007-07-21       drh:     }
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   blob_init(&name, zName, -1);
dbda8d6ce9 2007-07-21       drh:   if( name_to_uuid(&name, 1) ){
3b5514ed82 2007-09-22       drh:     fossil_fatal("%s", g.zErrMsg);
dbda8d6ce9 2007-07-21       drh:   }
dbda8d6ce9 2007-07-21       drh:   rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name);
dbda8d6ce9 2007-07-21       drh:   blob_reset(&name);
dbda8d6ce9 2007-07-21       drh:   return rid;
dbda8d6ce9 2007-07-21       drh: }