Fossil

Artifact Content
Login

Artifact 6b4958b9250369d74a0cb0432fa46d4b41797c9a:


     1  /*
     2  ** Copyright (c) 2010 D. Richard Hipp
     3  **
     4  ** This program is free software; you can redistribute it and/or
     5  ** modify it under the terms of the Simplified BSD License (also
     6  ** known as the "2-Clause License" or "FreeBSD License".)
     7  
     8  ** This program is distributed in the hope that it will be useful,
     9  ** but without any warranty; without even the implied warranty of
    10  ** merchantability or fitness for a particular purpose.
    11  **
    12  ** Author contact information:
    13  **   drh@hwaci.com
    14  **   http://www.hwaci.com/drh/
    15  **
    16  *******************************************************************************
    17  **
    18  ** This module contains the code that initializes the "sqlite3" command-line
    19  ** shell against the repository database.  The command-line shell itself
    20  ** is a copy of the "shell.c" code from SQLite.  This file contains logic
    21  ** to initialize the code in shell.c.
    22  */
    23  #include "config.h"
    24  #include "sqlcmd.h"
    25  #include <zlib.h>
    26  
    27  /*
    28  ** Implementation of the "content(X)" SQL function.  Return the complete
    29  ** content of artifact identified by X as a blob.
    30  */
    31  static void sqlcmd_content(
    32    sqlite3_context *context,
    33    int argc,
    34    sqlite3_value **argv
    35  ){
    36    int rid;
    37    Blob cx;
    38    const char *zName;
    39    assert( argc==1 );
    40    zName = (const char*)sqlite3_value_text(argv[0]);
    41    if( zName==0 ) return;
    42    g.db = sqlite3_context_db_handle(context);
    43    g.repositoryOpen = 1;
    44    rid = name_to_rid(zName);
    45    if( rid==0 ) return;
    46    if( content_get(rid, &cx) ){
    47      sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx),
    48                                   SQLITE_TRANSIENT);
    49      blob_reset(&cx);
    50    }
    51  }
    52  
53 /* 54 ** Implementation of the "compress(X)" SQL function. The input X is 55 ** compressed using zLib and the output is returned. 56 */ 57 static void sqlcmd_compress( 58 sqlite3_context *context, 59 int argc, 60 sqlite3_value **argv 61 ){ 62 const unsigned char *pIn; 63 unsigned char *pOut; 64 unsigned int nIn; 65 unsigned long int nOut; 66 67 pIn = sqlite3_value_blob(argv[0]); 68 nIn = sqlite3_value_bytes(argv[0]); 69 nOut = 13 + nIn + (nIn+999)/1000; 70 pOut = sqlite3_malloc( nOut+4 ); 71 pOut[0] = nIn>>24 & 0xff; 72 pOut[1] = nIn>>16 & 0xff; 73 pOut[2] = nIn>>8 & 0xff; 74 pOut[3] = nIn & 0xff; 75 compress(&pOut[4], &nOut, pIn, nIn); 76 sqlite3_result_blob(context, pOut, nOut+4, sqlite3_free); 77 } 78 79 /* 80 ** Implementation of the "decompress(X)" SQL function. The argument X 81 ** is a blob which was obtained from compress(Y). The output will be 82 ** the value Y. 83 */ 84 static void sqlcmd_decompress( 85 sqlite3_context *context, 86 int argc, 87 sqlite3_value **argv 88 ){ 89 const unsigned char *pIn; 90 unsigned char *pOut; 91 unsigned int nIn; 92 unsigned long int nOut; 93 int rc; 94 95 pIn = sqlite3_value_blob(argv[0]); 96 nIn = sqlite3_value_bytes(argv[0]); 97 nOut = (pIn[0]<<24) + (pIn[1]<<16) + (pIn[2]<<8) + pIn[3]; 98 pOut = sqlite3_malloc( nOut+1 ); 99 rc = uncompress(pOut, &nOut, &pIn[4], nIn-4); 100 if( rc==Z_OK ){ 101 sqlite3_result_blob(context, pOut, nOut, sqlite3_free); 102 }else{ 103 sqlite3_result_error(context, "input is not zlib compressed", -1); 104 } 105 } 106 107 /* 108 ** This is the "automatic extension" initializer that runs right after 109 ** the connection to the repository database is opened. Set up the 110 ** database connection to be more useful to the human operator. 111 */ 112 static int sqlcmd_autoinit( 113 sqlite3 *db, 114 const char **pzErrMsg, 115 const void *notUsed 116 ){ 117 sqlite3_create_function(db, "content", 1, SQLITE_ANY, 0, 118 sqlcmd_content, 0, 0); 119 sqlite3_create_function(db, "compress", 1, SQLITE_ANY, 0, 120 sqlcmd_compress, 0, 0); 121 sqlite3_create_function(db, "decompress", 1, SQLITE_ANY, 0, 122 sqlcmd_decompress, 0, 0); 123 re_add_sql_func(db); 124 g.repositoryOpen = 1; 125 g.db = db; 126 return SQLITE_OK; 127 } 128
129 /* 130 ** COMMAND: sqlite3 131 ** 132 ** Usage: %fossil sqlite3 ?DATABASE? ?OPTIONS? 133 ** 134 ** Run the standalone sqlite3 command-line shell on DATABASE with OPTIONS. 135 ** If DATABASE is omitted, then the repository that serves the working 136 ** directory is opened. 137 ** 138 ** WARNING: Careless use of this command can corrupt a Fossil repository 139 ** in ways that are unrecoverable. Be sure you know what you are doing before 140 ** running any SQL commands that modifies the repository database. 141 */ 142 void cmd_sqlite3(void){ 143 extern int sqlite3_shell(int, char**); 144 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); 145 db_close(1); 146 sqlite3_shutdown(); 147 sqlite3_shell(g.argc-1, g.argv+1); 148 g.db = 0; 149 } 150 151 /* 152 ** This routine is called by the patched sqlite3 command-line shell in order 153 ** to load the name and database connection for the open Fossil database. 154 */ 155 void fossil_open(const char **pzRepoName){ 156 sqlite3_auto_extension((void(*)(void))sqlcmd_autoinit); 157 *pzRepoName = g.zRepositoryName; 158 }