Пример #1
0
    } /* End of function */

    /*
    ** Append N bytes of text from z to the StrAccum object.
    */

    static void sqlite3StrAccumAppend( StrAccum p, string z, int N )
    {
      Debug.Assert( z != null || N == 0 );
      if ( p.tooBig )//|| p.mallocFailed != 0 )
      {
        testcase( p.tooBig );
        //testcase( p.mallocFailed );
        return;
      }
      if ( N < 0 )
      {
        N = sqlite3Strlen30( z );
      }
      if ( N == 0 || NEVER( z == null ) )
      {
        return;
      }
      //if( p->nChar+N >= p->nAlloc ){
      //  char *zNew;
      //  if( !p->useMalloc ){
      //    p->tooBig = 1;
      //    N = p->nAlloc - p->nChar - 1;
      //    if( N<=0 ){
      //      return;
      //    }
      //  }else{
      //    char *zOld = (p->zText==p->zBase ? 0 : p->zText);
      //    i64 szNew = p->nChar;
      //    szNew += N + 1;
      //    if( szNew > p->mxAlloc ){
      //      sqlite3StrAccumReset(p);
      //      p->tooBig = 1;
      //      return;
      //    }else{
      //      p->nAlloc = (int)szNew;
      //    }
      //    if( p->useMalloc==1 ){
      //      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
      //    }else{
      //      zNew = sqlite3_realloc(zOld, p->nAlloc);
      //    }
      //    if( zNew ){
      //      if( zOld==0 ) memcpy(zNew, p->zText, p->nChar);
      //      p->zText = zNew;
      //    }else{
      //      p->mallocFailed = 1;
      //      sqlite3StrAccumReset(p);
      //      return;
      //    }
      //  }
      //}
      //memcpy(&p->zText[p->nChar], z, N);
      p.zText.Append( z.Substring( 0, N <= z.Length ? N : z.Length ) );
      //p.nChar += N;
    }
Пример #2
0
 /*
 ** Finish off a string by making sure it is zero-terminated.
 ** Return a pointer to the resulting string.  Return a NULL
 ** pointer if any kind of error was encountered.
 */
 static string sqlite3StrAccumFinish( StrAccum p )
 {
   //if ( p->zText )
   //{
   //  p->zText[p->nChar] = 0;
   //  if ( p->useMalloc && p->zText == p->zBase )
   //  {
   //    if ( p->useMalloc == 1 )
   //    {
   //      p->zText = sqlite3DbMallocRaw( p->db, p->nChar + 1 );
   //    }
   //    else
   //    {
   //      p->zText = sqlite3_malloc( p->nChar + 1 );
   //    }
   //    if ( p->zText )
   //    {
   //      memcpy( p->zText, p->zBase, p->nChar + 1 );
   //    }
   //    else
   //    {
   //      p->mallocFailed = 1;
   //    }
   //  }
   //}
   return p.zText.ToString();
 }
Пример #3
0
    } /* End of function */

    /*
    ** Append N bytes of text from z to the StrAccum object.
    */

    static void sqlite3StrAccumAppend( StrAccum p, string z, int N )
    {
      Debug.Assert( z != null || N == 0 );
      if ( p.tooBig != 0 )//|| p.mallocFailed != 0 )
      {
        testcase( p.tooBig );
        //testcase( p.mallocFailed );
        return;
      }
      if ( N < 0 )
      {
        N = sqlite3Strlen30( z );
      }
      if ( N == 0 || NEVER( z == null ) )
      {
        return;
      }
      //if ( p.nChar + N >= p.nAlloc )
      //{
      //  char* zNew;
      //  if ( !p.useMalloc )
      //  {
      //    p.tooBig = 1;
      //    N = p.nAlloc - p.nChar - 1;
      //    if ( N <= 0 )
      //    {
      //      return;
      //    }
      //  }
      //  else
      //  {
      //    i64 szNew = p.nChar;
      //    szNew += N + 1;
      //    if ( szNew > p.mxAlloc )
      //    {
      //      sqlite3StrAccumReset( p );
      //      p.tooBig = 1;
      //      return;
      //    }
      //    else
      //    {
      //      p.nAlloc = (int)szNew;
      //    }
      //    zNew = sqlite3DbMalloc( p.nAlloc );
      //    if ( zNew )
      //    {
      //      memcpy( zNew, p.zText, p.nChar );
      //      sqlite3StrAccumReset( p );
      //      p.zText = zNew;
      //    }
      //    else
      //    {
      //      p.mallocFailed = 1;
      //      sqlite3StrAccumReset( p );
      //      return;
      //    }
      //  }
      //}
      //memcpy( &p.zText[p.nChar], z, N );
      p.zText.Append( z.Substring( 0, N <= z.Length ? N : z.Length ) );
      p.nChar += N;
    }
Пример #4
0
    /* Make sure "isView" and other macros defined above are undefined. Otherwise
    ** thely may interfere with compilation of other functions in this file
    ** (or in another file, if this file becomes part of the amalgamation).  */
    //#if isView
    // #undef isView
    //#endif
    //#if pTrigger
    // #undef pTrigger
    //#endif
    //#if tmask
    // #undef tmask
    //#endif

    /*
    ** Generate code to do constraint checks prior to an INSERT or an UPDATE.
    **
    ** The input is a range of consecutive registers as follows:
    **
    **    1.  The rowid of the row after the update.
    **
    **    2.  The data in the first column of the entry after the update.
    **
    **    i.  Data from middle columns...
    **
    **    N.  The data in the last column of the entry after the update.
    **
    ** The regRowid parameter is the index of the register containing (1).
    **
    ** If isUpdate is true and rowidChng is non-zero, then rowidChng contains
    ** the address of a register containing the rowid before the update takes
    ** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
    ** is false, indicating an INSERT statement, then a non-zero rowidChng 
    ** indicates that the rowid was explicitly specified as part of the
    ** INSERT statement. If rowidChng is false, it means that  the rowid is
    ** computed automatically in an insert or that the rowid value is not 
    ** modified by an update.
    **
    ** The code generated by this routine store new index entries into
    ** registers identified by aRegIdx[].  No index entry is created for
    ** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is
    ** the same as the order of indices on the linked list of indices
    ** attached to the table.
    **
    ** This routine also generates code to check constraints.  NOT NULL,
    ** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
    ** then the appropriate action is performed.  There are five possible
    ** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
    **
    **  Constraint type  Action       What Happens
    **  ---------------  ----------   ----------------------------------------
    **  any              ROLLBACK     The current transaction is rolled back and
    **                                sqlite3_exec() returns immediately with a
    **                                return code of SQLITE_CONSTRAINT.
    **
    **  any              ABORT        Back out changes from the current command
    **                                only (do not do a complete rollback) then
    **                                cause sqlite3_exec() to return immediately
    **                                with SQLITE_CONSTRAINT.
    **
    **  any              FAIL         Sqlite_exec() returns immediately with a
    **                                return code of SQLITE_CONSTRAINT.  The
    **                                transaction is not rolled back and any
    **                                prior changes are retained.
    **
    **  any              IGNORE       The record number and data is popped from
    **                                the stack and there is an immediate jump
    **                                to label ignoreDest.
    **
    **  NOT NULL         REPLACE      The NULL value is replace by the default
    **                                value for that column.  If the default value
    **                                is NULL, the action is the same as ABORT.
    **
    **  UNIQUE           REPLACE      The other row that conflicts with the row
    **                                being inserted is removed.
    **
    **  CHECK            REPLACE      Illegal.  The results in an exception.
    **
    ** Which action to take is determined by the overrideError parameter.
    ** Or if overrideError==OE_Default, then the pParse.onError parameter
    ** is used.  Or if pParse.onError==OE_Default then the onError value
    ** for the constraint is used.
    **
    ** The calling routine must open a read/write cursor for pTab with
    ** cursor number "baseCur".  All indices of pTab must also have open
    ** read/write cursors with cursor number baseCur+i for the i-th cursor.
    ** Except, if there is no possibility of a REPLACE action then
    ** cursors do not need to be open for indices where aRegIdx[i]==0.
    */
    static void sqlite3GenerateConstraintChecks(
    Parse pParse,       /* The parser context */
    Table pTab,         /* the table into which we are inserting */
    int baseCur,        /* Index of a read/write cursor pointing at pTab */
    int regRowid,       /* Index of the range of input registers */
    int[] aRegIdx,      /* Register used by each index.  0 for unused indices */
    int rowidChng,      /* True if the rowid might collide with existing entry */
    bool isUpdate,      /* True for UPDATE, False for INSERT */
    int overrideError,  /* Override onError to this if not OE_Default */
    int ignoreDest,     /* Jump to this label on an OE_Ignore resolution */
    out int pbMayReplace   /* OUT: Set to true if constraint may cause a replace */
    )
    {

      int i;               /* loop counter */
      Vdbe v;              /* VDBE under constrution */
      int nCol;            /* Number of columns */
      int onError;         /* Conflict resolution strategy */
      int j1;              /* Addresss of jump instruction */
      int j2 = 0, j3;      /* Addresses of jump instructions */
      int regData;         /* Register containing first data column */
      int iCur;            /* Table cursor number */
      Index pIdx;         /* Pointer to one of the indices */
      bool seenReplace = false; /* True if REPLACE is used to resolve INT PK conflict */
      int regOldRowid = ( rowidChng != 0 && isUpdate ) ? rowidChng : regRowid;

      v = sqlite3GetVdbe( pParse );
      Debug.Assert( v != null );
      Debug.Assert( pTab.pSelect == null );  /* This table is not a VIEW */
      nCol = pTab.nCol;
      regData = regRowid + 1;


      /* Test all NOT NULL constraints.
      */
      for ( i = 0; i < nCol; i++ )
      {
        if ( i == pTab.iPKey )
        {
          continue;
        }
        onError = pTab.aCol[i].notNull;
        if ( onError == OE_None )
          continue;
        if ( overrideError != OE_Default )
        {
          onError = overrideError;
        }
        else if ( onError == OE_Default )
        {
          onError = OE_Abort;
        }
        if ( onError == OE_Replace && pTab.aCol[i].pDflt == null )
        {
          onError = OE_Abort;
        }
        Debug.Assert( onError == OE_Rollback || onError == OE_Abort || onError == OE_Fail
        || onError == OE_Ignore || onError == OE_Replace );
        switch ( onError )
        {
          case OE_Abort:
            {
              sqlite3MayAbort( pParse );
              goto case OE_Fail;
            }
          case OE_Rollback:
          case OE_Fail:
            {
              string zMsg;
              sqlite3VdbeAddOp3( v, OP_HaltIfNull,
                          SQLITE_CONSTRAINT, onError, regData + i );
              zMsg = sqlite3MPrintf( pParse.db, "%s.%s may not be NULL",
              pTab.zName, pTab.aCol[i].zName );
              sqlite3VdbeChangeP4( v, -1, zMsg, P4_DYNAMIC );
              break;
            }
          case OE_Ignore:
            {
              sqlite3VdbeAddOp2( v, OP_IsNull, regData + i, ignoreDest );
              break;
            }
          default:
            {
              Debug.Assert( onError == OE_Replace );
              j1 = sqlite3VdbeAddOp1( v, OP_NotNull, regData + i );
              sqlite3ExprCode( pParse, pTab.aCol[i].pDflt, regData + i );
              sqlite3VdbeJumpHere( v, j1 );
              break;
            }
        }
      }

      /* Test all CHECK constraints
      */
#if !SQLITE_OMIT_CHECK
      if ( pTab.pCheck != null && ( pParse.db.flags & SQLITE_IgnoreChecks ) == 0 )
      {
        int allOk = sqlite3VdbeMakeLabel( v );
        pParse.ckBase = regData;
        sqlite3ExprIfTrue( pParse, pTab.pCheck, allOk, SQLITE_JUMPIFNULL );
        onError = overrideError != OE_Default ? overrideError : OE_Abort;
        if ( onError == OE_Ignore )
        {
          sqlite3VdbeAddOp2( v, OP_Goto, 0, ignoreDest );
        }
        else
        {
          if ( onError == OE_Replace )
            onError = OE_Abort; /* IMP: R-15569-63625 */
          sqlite3HaltConstraint( pParse, onError, (string)null, 0 );
        }
        sqlite3VdbeResolveLabel( v, allOk );
      }
#endif // * !SQLITE_OMIT_CHECK) */

      /* If we have an INTEGER PRIMARY KEY, make sure the primary key
** of the new record does not previously exist.  Except, if this
** is an UPDATE and the primary key is not changing, that is OK.
*/
      if ( rowidChng != 0 )
      {
        onError = pTab.keyConf;
        if ( overrideError != OE_Default )
        {
          onError = overrideError;
        }
        else if ( onError == OE_Default )
        {
          onError = OE_Abort;
        }

        if ( isUpdate )
        {
          j2 = sqlite3VdbeAddOp3( v, OP_Eq, regRowid, 0, rowidChng );
        }
        j3 = sqlite3VdbeAddOp3( v, OP_NotExists, baseCur, 0, regRowid );
        switch ( onError )
        {
          default:
            {
              onError = OE_Abort;
              /* Fall thru into the next case */
            }
            goto case OE_Rollback;
          case OE_Rollback:
          case OE_Abort:
          case OE_Fail:
            {
              sqlite3HaltConstraint(
                pParse, onError, "PRIMARY KEY must be unique", P4_STATIC );
              break;
            }
          case OE_Replace:
            {
              /* If there are DELETE triggers on this table and the
              ** recursive-triggers flag is set, call GenerateRowDelete() to
              ** remove the conflicting row from the the table. This will fire
              ** the triggers and remove both the table and index b-tree entries.
              **
              ** Otherwise, if there are no triggers or the recursive-triggers
              ** flag is not set, but the table has one or more indexes, call 
              ** GenerateRowIndexDelete(). This removes the index b-tree entries 
              ** only. The table b-tree entry will be replaced by the new entry 
              ** when it is inserted.  
              **
              ** If either GenerateRowDelete() or GenerateRowIndexDelete() is called,
              ** also invoke MultiWrite() to indicate that this VDBE may require
              ** statement rollback (if the statement is aborted after the delete
              ** takes place). Earlier versions called sqlite3MultiWrite() regardless,
              ** but being more selective here allows statements like:
              **
              **   REPLACE INTO t(rowid) VALUES($newrowid)
              **
              ** to run without a statement journal if there are no indexes on the
              ** table.
              */
              Trigger pTrigger = null;
              if ( ( pParse.db.flags & SQLITE_RecTriggers ) != 0 )
              {
                int iDummy;
                pTrigger = sqlite3TriggersExist( pParse, pTab, TK_DELETE, null, out iDummy );
              }
              if ( pTrigger != null || sqlite3FkRequired( pParse, pTab, null, 0 ) != 0 )
              {
                sqlite3MultiWrite( pParse );
                sqlite3GenerateRowDelete(
                    pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
                );
              }
              else
                if ( pTab.pIndex != null )
                {
                  sqlite3MultiWrite( pParse );
                  sqlite3GenerateRowIndexDelete( pParse, pTab, baseCur, 0 );
                }
              seenReplace = true;
              break;
            }
          case OE_Ignore:
            {
              Debug.Assert( !seenReplace );
              sqlite3VdbeAddOp2( v, OP_Goto, 0, ignoreDest );
              break;
            }
        }
        sqlite3VdbeJumpHere( v, j3 );
        if ( isUpdate )
        {
          sqlite3VdbeJumpHere( v, j2 );
        }
      }

      /* Test all UNIQUE constraints by creating entries for each UNIQUE
      ** index and making sure that duplicate entries do not already exist.
      ** Add the new records to the indices as we go.
      */
      for ( iCur = 0, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, iCur++ )
      {
        int regIdx;
        int regR;

        if ( aRegIdx[iCur] == 0 )
          continue;  /* Skip unused indices */

        /* Create a key for accessing the index entry */
        regIdx = sqlite3GetTempRange( pParse, pIdx.nColumn + 1 );
        for ( i = 0; i < pIdx.nColumn; i++ )
        {
          int idx = pIdx.aiColumn[i];
          if ( idx == pTab.iPKey )
          {
            sqlite3VdbeAddOp2( v, OP_SCopy, regRowid, regIdx + i );
          }
          else
          {
            sqlite3VdbeAddOp2( v, OP_SCopy, regData + idx, regIdx + i );
          }
        }
        sqlite3VdbeAddOp2( v, OP_SCopy, regRowid, regIdx + i );
        sqlite3VdbeAddOp3( v, OP_MakeRecord, regIdx, pIdx.nColumn + 1, aRegIdx[iCur] );
        sqlite3VdbeChangeP4( v, -1, sqlite3IndexAffinityStr( v, pIdx ), P4_TRANSIENT );
        sqlite3ExprCacheAffinityChange( pParse, regIdx, pIdx.nColumn + 1 );

        /* Find out what action to take in case there is an indexing conflict */
        onError = pIdx.onError;
        if ( onError == OE_None )
        {
          sqlite3ReleaseTempRange( pParse, regIdx, pIdx.nColumn + 1 );
          continue;  /* pIdx is not a UNIQUE index */
        }

        if ( overrideError != OE_Default )
        {
          onError = overrideError;
        }
        else if ( onError == OE_Default )
        {
          onError = OE_Abort;
        }
        if ( seenReplace )
        {
          if ( onError == OE_Ignore )
            onError = OE_Replace;
          else if ( onError == OE_Fail )
            onError = OE_Abort;
        }


        /* Check to see if the new index entry will be unique */
        regR = sqlite3GetTempReg( pParse );
        sqlite3VdbeAddOp2( v, OP_SCopy, regOldRowid, regR );
        j3 = sqlite3VdbeAddOp4( v, OP_IsUnique, baseCur + iCur + 1, 0,
        regR, regIdx,//regR, SQLITE_INT_TO_PTR(regIdx),
        P4_INT32 );
        sqlite3ReleaseTempRange( pParse, regIdx, pIdx.nColumn + 1 );

        /* Generate code that executes if the new index entry is not unique */
        Debug.Assert( onError == OE_Rollback || onError == OE_Abort || onError == OE_Fail
        || onError == OE_Ignore || onError == OE_Replace );
        switch ( onError )
        {
          case OE_Rollback:
          case OE_Abort:
          case OE_Fail:
            {
              int j;
              StrAccum errMsg = new StrAccum( 200 );
              string zSep;
              string zErr;

              sqlite3StrAccumInit( errMsg, null, 0, 200 );
              errMsg.db = pParse.db;
              zSep = pIdx.nColumn > 1 ? "columns " : "column ";
              for ( j = 0; j < pIdx.nColumn; j++ )
              {
                string zCol = pTab.aCol[pIdx.aiColumn[j]].zName;
                sqlite3StrAccumAppend( errMsg, zSep, -1 );
                zSep = ", ";
                sqlite3StrAccumAppend( errMsg, zCol, -1 );
              }
              sqlite3StrAccumAppend( errMsg,
              pIdx.nColumn > 1 ? " are not unique" : " is not unique", -1 );
              zErr = sqlite3StrAccumFinish( errMsg );
              sqlite3HaltConstraint( pParse, onError, zErr, 0 );
              sqlite3DbFree( errMsg.db, ref zErr );
              break;
            }
          case OE_Ignore:
            {
              Debug.Assert( !seenReplace );
              sqlite3VdbeAddOp2( v, OP_Goto, 0, ignoreDest );
              break;
            }
          default:
            {
              Trigger pTrigger = null;
              Debug.Assert( onError == OE_Replace );
              sqlite3MultiWrite( pParse );
              if ( ( pParse.db.flags & SQLITE_RecTriggers ) != 0 )
              {
                int iDummy;
                pTrigger = sqlite3TriggersExist( pParse, pTab, TK_DELETE, null, out iDummy );
              }
              sqlite3GenerateRowDelete(
                  pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace
              );
              seenReplace = true;
              break;
            }
        }
        sqlite3VdbeJumpHere( v, j3 );
        sqlite3ReleaseTempReg( pParse, regR );
      }
      //if ( pbMayReplace )
      {
        pbMayReplace = seenReplace ? 1 : 0;
      }
    }
Пример #5
0
    static char[] buf = new char[etBUFSIZE];       /* Conversion buffer */
    static void sqlite3VXPrintf(
    StrAccum pAccum,             /* Accumulate results here */
    int useExtended,             /* Allow extended %-conversions */
    string fmt,                   /* Format string */
    va_list[] ap                   /* arguments */
    )
    {
      int c;                     /* Next character in the format string */
      int bufpt;                 /* Pointer to the conversion buffer */
      int precision;             /* Precision of the current field */
      int length;                /* Length of the field */
      int idx;                   /* A general purpose loop counter */
      int width;                 /* Width of the current field */
      etByte flag_leftjustify;   /* True if "-" flag is present */
      etByte flag_plussign;      /* True if "+" flag is present */
      etByte flag_blanksign;     /* True if " " flag is present */
      etByte flag_alternateform; /* True if "#" flag is present */
      etByte flag_altform2;      /* True if "!" flag is present */
      etByte flag_zeropad;       /* True if field width constant starts with zero */
      etByte flag_long;          /* True if "l" flag is present */
      etByte flag_longlong;      /* True if the "ll" flag is present */
      etByte done;               /* Loop termination flag */
      i64 longvalue;
      LONGDOUBLE_TYPE realvalue; /* Value for real types */
      et_info infop;      /* Pointer to the appropriate info structure */
      char[] buf = new char[etBUFSIZE];       /* Conversion buffer */
      char prefix;                /* Prefix character.  "+" or "-" or " " or '\0'. */
      byte xtype = 0;             /* Conversion paradigm */
      // Not used in C# -- string zExtra;              /* Extra memory used for etTCLESCAPE conversions */
#if !SQLITE_OMIT_FLOATING_POINT
      int exp, e2;                /* exponent of real numbers */
      double rounder;             /* Used for rounding floating point values */
      etByte flag_dp;             /* True if decimal point should be shown */
      etByte flag_rtz;            /* True if trailing zeros should be removed */
      etByte flag_exp;            /* True to force display of the exponent */
      int nsd;                    /* Number of significant digits returned */
#endif
      length = 0;
      bufpt = 0;
      int _fmt = 0; // Work around string pointer
      fmt += '\0';

      for ( ; _fmt <= fmt.Length && ( c = fmt[_fmt] ) != 0; ++_fmt )
      {
        if ( c != '%' )
        {
          int amt;
          bufpt = _fmt;
          amt = 1;
          while ( _fmt < fmt.Length && ( c = ( fmt[++_fmt] ) ) != '%' && c != 0 )
            amt++;
          sqlite3StrAccumAppend( pAccum, fmt.Substring( bufpt, amt ), amt );
          if ( c == 0 )
            break;
        }
        if ( _fmt < fmt.Length && ( c = ( fmt[++_fmt] ) ) == 0 )
        {
          sqlite3StrAccumAppend( pAccum, "%", 1 );
          break;
        }
        /* Find out what flags are present */
        flag_leftjustify = flag_plussign = flag_blanksign =
        flag_alternateform = flag_altform2 = flag_zeropad = false;
        done = false;
        do
        {
          switch ( c )
          {
            case '-':
              flag_leftjustify = true;
              break;
            case '+':
              flag_plussign = true;
              break;
            case ' ':
              flag_blanksign = true;
              break;
            case '#':
              flag_alternateform = true;
              break;
            case '!':
              flag_altform2 = true;
              break;
            case '0':
              flag_zeropad = true;
              break;
            default:
              done = true;
              break;
          }
        } while ( !done && _fmt < fmt.Length - 1 && ( c = ( fmt[++_fmt] ) ) != 0 );
        /* Get the field width */
        width = 0;
        if ( c == '*' )
        {
          width = (int)va_arg( ap, "int" );
          if ( width < 0 )
          {
            flag_leftjustify = true;
            width = -width;
          }
          c = fmt[++_fmt];
        }
        else
        {
          while ( c >= '0' && c <= '9' )
          {
            width = width * 10 + c - '0';
            c = fmt[++_fmt];
          }
        }
        if ( width > etBUFSIZE - 10 )
        {
          width = etBUFSIZE - 12;
        }
        /* Get the precision */
        if ( c == '.' )
        {
          precision = 0;
          c = fmt[++_fmt];
          if ( c == '*' )
          {
            precision = (int)va_arg( ap, "int" );
            if ( precision < 0 )
              precision = -precision;
            c = fmt[++_fmt];
          }
          else
          {
            while ( c >= '0' && c <= '9' )
            {
              precision = precision * 10 + c - '0';
              c = fmt[++_fmt];
            }
          }
        }
        else
        {
          precision = -1;
        }
        /* Get the conversion type modifier */
        if ( c == 'l' )
        {
          flag_long = true;
          c = fmt[++_fmt];
          if ( c == 'l' )
          {
            flag_longlong = true;
            c = fmt[++_fmt];
          }
          else
          {
            flag_longlong = false;
          }
        }
        else
        {
          flag_long = flag_longlong = false;
        }
        /* Fetch the info entry for the field */
        infop = fmtinfo[0];
        xtype = etINVALID;
        for ( idx = 0; idx < ArraySize( fmtinfo ); idx++ )
        {
          if ( c == fmtinfo[idx].fmttype )
          {
            infop = fmtinfo[idx];
            if ( useExtended != 0 || ( infop.flags & FLAG_INTERN ) == 0 )
            {
              xtype = infop.type;
            }
            else
            {
              return;
            }
            break;
          }
        }
        //zExtra = null;

        /* Limit the precision to prevent overflowing buf[] during conversion */
        if ( precision > etBUFSIZE - 40 && ( infop.flags & FLAG_STRING ) == 0 )
        {
          precision = etBUFSIZE - 40;
        }

        /*
        ** At this point, variables are initialized as follows:
        **
        **   flag_alternateform          TRUE if a '#' is present.
        **   flag_altform2               TRUE if a '!' is present.
        **   flag_plussign               TRUE if a '+' is present.
        **   flag_leftjustify            TRUE if a '-' is present or if the
        **                               field width was negative.
        **   flag_zeropad                TRUE if the width began with 0.
        **   flag_long                   TRUE if the letter 'l' (ell) prefixed
        **                               the conversion character.
        **   flag_longlong               TRUE if the letter 'll' (ell ell) prefixed
        **                               the conversion character.
        **   flag_blanksign              TRUE if a ' ' is present.
        **   width                       The specified field width.  This is
        **                               always non-negative.  Zero is the default.
        **   precision                   The specified precision.  The default
        **                               is -1.
        **   xtype                       The class of the conversion.
        **   infop                       Pointer to the appropriate info struct.
        */
        switch ( xtype )
        {
          case etPOINTER:
            flag_longlong = true;// char*.Length == sizeof(i64);
            flag_long = false;// char*.Length == sizeof(long);
            /* Fall through into the next case */
            goto case etRADIX;
          case etORDINAL:
          case etRADIX:
            if ( ( infop.flags & FLAG_SIGNED ) != 0 )
            {
              i64 v;
              if ( flag_longlong )
              {
                v = (long)va_arg( ap, "i64" );
              }
              else if ( flag_long )
              {
                v = (long)va_arg( ap, "long int" );
              }
              else
              {
                v = (int)va_arg( ap, "int" );
              }
              if ( v < 0 )
              {
                longvalue = -v;
                prefix = '-';
              }
              else
              {
                longvalue = v;
                if ( flag_plussign )
                  prefix = '+';
                else if ( flag_blanksign )
                  prefix = ' ';
                else
                  prefix = '\0';
              }
            }
            else
            {
              if ( flag_longlong )
              {
                longvalue = (i64)va_arg( ap, "longlong int" );
              }
              else if ( flag_long )
              {
                longvalue = (i64)va_arg( ap, "long int" );
              }
              else
              {
                longvalue = (i64)va_arg( ap, "long" );
              }
              prefix = '\0';
            }
            if ( longvalue == 0 )
              flag_alternateform = false;
            if ( flag_zeropad && precision < width - ( ( prefix != '\0' ) ? 1 : 0 ) )
            {
              precision = width - ( ( prefix != '\0' ) ? 1 : 0 );
            }
            bufpt = buf.Length;//[etBUFSIZE-1];
            char[] _bufOrd = null;
            if ( xtype == etORDINAL )
            {
              char[] zOrd = "thstndrd".ToCharArray();
              int x = (int)( longvalue % 10 );
              if ( x >= 4 || ( longvalue / 10 ) % 10 == 1 )
              {
                x = 0;
              }
              _bufOrd = new char[2];
              _bufOrd[0] = zOrd[x * 2];
              _bufOrd[1] = zOrd[x * 2 + 1];
              //bufpt -= 2;
            }
            {

              char[] _buf;
              switch ( infop._base )
              {
                case 16:
                  _buf = longvalue.ToString( "x" ).ToCharArray();
                  break;
                case 8:
                  _buf = Convert.ToString( (long)longvalue, 8 ).ToCharArray();
                  break;
                default:
                  {
                    if ( flag_zeropad )
                      _buf = longvalue.ToString( new string( '0', width - ( ( prefix != '\0' ) ? 1 : 0 ) ) ).ToCharArray();
                    else
                      _buf = longvalue.ToString().ToCharArray();
                  }
                  break;
              }
              bufpt = buf.Length - _buf.Length - ( _bufOrd == null ? 0 : 2 );
              Array.Copy( _buf, 0, buf, bufpt, _buf.Length );
              if ( _bufOrd != null )
              {
                buf[buf.Length - 1] = _bufOrd[1];
                buf[buf.Length - 2] = _bufOrd[0];
              }
              //char* cset;      /* Use registers for speed */
              //int _base;
              //cset = aDigits[infop.charset];
              //_base = infop._base;
              //do
              //{ /* Convert to ascii */
              //   *(--bufpt) = cset[longvalue % (ulong)_base];
              //  longvalue = longvalue / (ulong)_base;
              //} while (longvalue > 0);
            }
            length = buf.Length - bufpt;//length = (int)(&buf[etBUFSIZE-1]-bufpt);
            for ( idx = precision - length; idx > 0; idx-- )
            {
              buf[( --bufpt )] = '0';                             /* Zero pad */
            }
            if ( prefix != '\0' )
              buf[--bufpt] = prefix;   /* Add sign */
            if ( flag_alternateform && infop.prefix != 0 )
            {      /* Add "0" or "0x" */
              int pre;
              char x;
              pre = infop.prefix;
              for ( ; ( x = aPrefix[pre] ) != 0; pre++ )
                buf[--bufpt] = x;
            }
            length = buf.Length - bufpt;//length = (int)(&buf[etBUFSIZE-1]-bufpt);
            break;
          case etFLOAT:
          case etEXP:
          case etGENERIC:
            realvalue = (double)va_arg( ap, "double" );
#if SQLITE_OMIT_FLOATING_POINT
length = 0;
#else
            if ( precision < 0 )
              precision = 6;         /* Set default precision */
            if ( precision > etBUFSIZE / 2 - 10 )
              precision = etBUFSIZE / 2 - 10;
            if ( realvalue < 0.0 )
            {
              realvalue = -realvalue;
              prefix = '-';
            }
            else
            {
              if ( flag_plussign )
                prefix = '+';
              else if ( flag_blanksign )
                prefix = ' ';
              else
                prefix = '\0';
            }
            if ( xtype == etGENERIC && precision > 0 )
              precision--;
#if FALSE
/* Rounding works like BSD when the constant 0.4999 is used.  Wierd! */
for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
#else
            /* It makes more sense to use 0.5 */
            for ( idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1 )
            {
            }
#endif
            if ( xtype == etFLOAT )
              realvalue += rounder;
            /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
            exp = 0;
            double d = 0;
            if ( Double.IsNaN( realvalue ) || !( Double.TryParse( Convert.ToString( realvalue ), out d ) ) )//if( sqlite3IsNaN((double)realvalue) )
            {
              buf[0] = 'N';
              buf[1] = 'a';
              buf[2] = 'N';// "NaN"
              length = 3;
              break;
            }
            if ( realvalue > 0.0 )
            {
              while ( realvalue >= 1e32 && exp <= 350 )
              {
                realvalue *= 1e-32;
                exp += 32;
              }
              while ( realvalue >= 1e8 && exp <= 350 )
              {
                realvalue *= 1e-8;
                exp += 8;
              }
              while ( realvalue >= 10.0 && exp <= 350 )
              {
                realvalue *= 0.1;
                exp++;
              }
              while ( realvalue < 1e-8 )
              {
                realvalue *= 1e8;
                exp -= 8;
              }
              while ( realvalue < 1.0 )
              {
                realvalue *= 10.0;
                exp--;
              }
              if ( exp > 350 )
              {
                if ( prefix == '-' )
                {
                  buf[0] = '-';
                  buf[1] = 'I';
                  buf[2] = 'n';
                  buf[3] = 'f';// "-Inf"
                  bufpt = 4;
                }
                else if ( prefix == '+' )
                {
                  buf[0] = '+';
                  buf[1] = 'I';
                  buf[2] = 'n';
                  buf[3] = 'f';// "+Inf"
                  bufpt = 4;
                }
                else
                {
                  buf[0] = 'I';
                  buf[1] = 'n';
                  buf[2] = 'f';// "Inf"
                  bufpt = 3;
                }
                length = sqlite3Strlen30( bufpt );// sqlite3Strlen30(bufpt);
                bufpt = 0;
                break;
              }
            }
            bufpt = 0;
            /*
            ** If the field type is etGENERIC, then convert to either etEXP
            ** or etFLOAT, as appropriate.
            */
            flag_exp = xtype == etEXP;
            if ( xtype != etFLOAT )
            {
              realvalue += rounder;
              if ( realvalue >= 10.0 )
              {
                realvalue *= 0.1;
                exp++;
              }
            }
            if ( xtype == etGENERIC )
            {
              flag_rtz = !flag_alternateform;
              if ( exp < -4 || exp > precision )
              {
                xtype = etEXP;
              }
              else
              {
                precision = precision - exp;
                xtype = etFLOAT;
              }
            }
            else
            {
              flag_rtz = false;
            }
            if ( xtype == etEXP )
            {
              e2 = 0;
            }
            else
            {
              e2 = exp;
            }
            nsd = 0;
            flag_dp = ( precision > 0 ? true : false ) | flag_alternateform | flag_altform2;
            /* The sign in front of the number */
            if ( prefix != '\0' )
            {
              buf[bufpt++] = prefix;
            }
            /* Digits prior to the decimal point */
            if ( e2 < 0 )
            {
              buf[bufpt++] = '0';
            }
            else
            {
              for ( ; e2 >= 0; e2-- )
              {
                buf[bufpt++] = (char)( et_getdigit( ref realvalue, ref nsd ) + '0' ); // *(bufpt++) = et_getdigit(ref realvalue, ref nsd);
              }

            }
            /* The decimal point */
            if ( flag_dp )
            {
              buf[bufpt++] = '.';
            }
            /* "0" digits after the decimal point but before the first
            ** significant digit of the number */
            for ( e2++; e2 < 0; precision--, e2++ )
            {
              Debug.Assert( precision > 0 );
              buf[bufpt++] = '0';
            }
            /* Significant digits after the decimal point */
            while ( ( precision-- ) > 0 )
            {
              buf[bufpt++] = (char)( et_getdigit( ref realvalue, ref nsd ) + '0' ); // *(bufpt++) = et_getdigit(&realvalue, nsd);
            }
            /* Remove trailing zeros and the "." if no digits follow the "." */
            if ( flag_rtz && flag_dp )
            {
              while ( buf[bufpt - 1] == '0' )
                buf[--bufpt] = '\0';
              Debug.Assert( bufpt > 0 );
              if ( buf[bufpt - 1] == '.' )
              {
                if ( flag_altform2 )
                {
                  buf[( bufpt++ )] = '0';
                }
                else
                {
                  buf[( --bufpt )] = '0';
                }
              }
            }
            /* Add the "eNNN" suffix */
            if ( flag_exp || xtype == etEXP )
            {
              buf[bufpt++] = aDigits[infop.charset];
              if ( exp < 0 )
              {
                buf[bufpt++] = '-';
                exp = -exp;
              }
              else
              {
                buf[bufpt++] = '+';
              }
              if ( exp >= 100 )
              {
                buf[bufpt++] = (char)( exp / 100 + '0' );                /* 100's digit */
                exp %= 100;
              }
              buf[bufpt++] = (char)( exp / 10 + '0' );                     /* 10's digit */
              buf[bufpt++] = (char)( exp % 10 + '0' );                     /* 1's digit */
            }
            //bufpt = 0;

            /* The converted number is in buf[] and zero terminated. Output it.
            ** Note that the number is in the usual order, not reversed as with
            ** integer conversions. */
            length = bufpt;//length = (int)(bufpt-buf);
            bufpt = 0;

            /* Special case:  Add leading zeros if the flag_zeropad flag is
            ** set and we are not left justified */
            if ( flag_zeropad && !flag_leftjustify && length < width )
            {
              int i;
              int nPad = width - length;
              for ( i = width; i >= nPad; i-- )
              {
                buf[bufpt + i] = buf[bufpt + i - nPad];
              }
              i = ( prefix != '\0' ? 1 : 0 );
              while ( nPad-- != 0 )
                buf[( bufpt++ ) + i] = '0';
              length = width;
              bufpt = 0;
            }
#endif //* !defined(SQLITE_OMIT_FLOATING_POINT) */
            break;
          case etSIZE:
            ap[0] = pAccum.nChar; // *(va_arg(ap,int*)) = pAccum.nChar;
            length = width = 0;
            break;
          case etPERCENT:
            buf[0] = '%';
            bufpt = 0;
            length = 1;
            break;
          case etCHARX:
            c = (char)va_arg( ap, "char" );
            buf[0] = (char)c;
            if ( precision >= 0 )
            {
              for ( idx = 1; idx < precision; idx++ )
                buf[idx] = (char)c;
              length = precision;
            }
            else
            {
              length = 1;
            }
            bufpt = 0;
            break;
          case etSTRING:
          case etDYNSTRING:
            bufpt = 0;//
            string bufStr = (string)va_arg( ap, "string" );
            if ( bufStr.Length > buf.Length )
              buf = new char[bufStr.Length];
            bufStr.ToCharArray().CopyTo( buf, 0 );
            bufpt = bufStr.Length;
            if ( bufpt == 0 )
            {
              buf[0] = '\0';
            }
            else if ( xtype == etDYNSTRING )
            {
              //              zExtra = bufpt;
            }
            if ( precision >= 0 )
            {
              for ( length = 0; length < precision && length < bufStr.Length && buf[length] != 0; length++ )
              {
              }
              //length += precision;
            }
            else
            {
              length = sqlite3Strlen30( bufpt );
            }
            bufpt = 0;
            break;
          case etSQLESCAPE:
          case etSQLESCAPE2:
          case etSQLESCAPE3:
            {
              int i;
              int j;
              int k;
              int n;
              bool isnull;
              bool needQuote;
              char ch;
              char q = ( ( xtype == etSQLESCAPE3 ) ? '"' : '\'' );   /* Quote character */
              string escarg = (string)va_arg( ap, "char*" ) + '\0';
              isnull = ( escarg == "" || escarg == "NULL\0" );
              if ( isnull )
                escarg = ( xtype == etSQLESCAPE2 ) ? "NULL\0" : "(NULL)\0";
              k = precision;
              for ( i = n = 0; k != 0 && ( ch = escarg[i] ) != 0; i++, k-- )
              {
                if ( ch == q )
                  n++;
              }
              needQuote = !isnull && ( xtype == etSQLESCAPE2 );
              n += i + 1 + ( needQuote ? 2 : 0 );
              if ( n > etBUFSIZE )
              {
                buf = new char[n];//bufpt = zExtra = sqlite3Malloc(n);
                //if ( bufpt == 0 )
                //{
                //  pAccum->mallocFailed = 1;
                //  return;
                //}
                bufpt = 0; //Start of Buffer
              }
              else
              {
                //bufpt = buf;
                bufpt = 0; //Start of Buffer
              }
              j = 0;
              if ( needQuote )
                buf[bufpt + j++] = q;
              k = i;
              for ( i = 0; i < k; i++ )
              {
                buf[bufpt + j++] = ch = escarg[i];
                if ( ch == q )
                  buf[bufpt + j++] = ch;
              }
              if ( needQuote )
                buf[bufpt + j++] = q;
              buf[bufpt + j] = '\0';
              length = j;
              /* The precision in %q and %Q means how many input characters to
              ** consume, not the length of the output...
              ** if( precision>=0 && precision<length ) length = precision; */
              break;
            }
          case etTOKEN:
            {
              Token pToken = (Token)va_arg( ap, "Token" );
              if ( pToken != null )
              {
                sqlite3StrAccumAppend( pAccum, pToken.z.ToString(), (int)pToken.n );
              }
              length = width = 0;
              break;
            }
          case etSRCLIST:
            {
              SrcList pSrc = (SrcList)va_arg( ap, "SrcList" );
              int k = (int)va_arg( ap, "int" );
              SrcList_item pItem = pSrc.a[k];
              Debug.Assert( k >= 0 && k < pSrc.nSrc );
              if ( pItem.zDatabase != null )
              {
                sqlite3StrAccumAppend( pAccum, pItem.zDatabase, -1 );
                sqlite3StrAccumAppend( pAccum, ".", 1 );
              }
              sqlite3StrAccumAppend( pAccum, pItem.zName, -1 );
              length = width = 0;
              break;
            }
          default:
            {
              Debug.Assert( xtype == etINVALID );
              return;
            }
        }/* End switch over the format type */
        /*
        ** The text of the conversion is pointed to by "bufpt" and is
        ** "length" characters long.  The field width is "width".  Do
        ** the output.
        */
        if ( !flag_leftjustify )
        {
          int nspace;
          nspace = width - length;// -2;
          if ( nspace > 0 )
          {
            appendSpace( pAccum, nspace );
          }
        }
        if ( length > 0 )
        {
          sqlite3StrAccumAppend( pAccum, new string( buf, bufpt, length ), length );
        }
        if ( flag_leftjustify )
        {
          int nspace;
          nspace = width - length;
          if ( nspace > 0 )
          {
            appendSpace( pAccum, nspace );
          }
        }
        //if( zExtra ){
        //  sqlite3DbFree(db,ref  zExtra);
        //}
      }/* End for loop over the format string */
    } /* End of function */
Пример #6
0
 /*
 ** Initialize a string accumulator
 */
 static void sqlite3StrAccumInit( StrAccum p, StringBuilder zBase, int n, int mx )
 {
   p.zText = p.zBase = zBase;
   p.db = null;
   p.nChar = 0;
   p.nAlloc = n;
   p.mxAlloc = mx;
   p.useMalloc = 1;
   p.tooBig = 0;
   //p.mallocFailed = 0;
 }
Пример #7
0
    /*
    ** Generate code to do constraint checks prior to an INSERT or an UPDATE.
    **
    ** The input is a range of consecutive registers as follows:
    **
    **    1.  The rowid of the row to be updated before the update.  This
    **        value is omitted unless we are doing an UPDATE that involves a
    **        change to the record number or writing to a virtual table.
    **
    **    2.  The rowid of the row after the update.
    **
    **    3.  The data in the first column of the entry after the update.
    **
    **    i.  Data from middle columns...
    **
    **    N.  The data in the last column of the entry after the update.
    **
    ** The regRowid parameter is the index of the register containing (2).
    **
    ** The old rowid shown as entry (1) above is omitted unless both isUpdate
    ** and rowidChng are 1.  isUpdate is true for UPDATEs and false for
    ** INSERTs.  RowidChng means that the new rowid is explicitly specified by
    ** the update or insert statement.  If rowidChng is false, it means that
    ** the rowid is computed automatically in an insert or that the rowid value
    ** is not modified by the update.
    **
    ** The code generated by this routine store new index entries into
    ** registers identified by aRegIdx[].  No index entry is created for
    ** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is
    ** the same as the order of indices on the linked list of indices
    ** attached to the table.
    **
    ** This routine also generates code to check constraints.  NOT NULL,
    ** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
    ** then the appropriate action is performed.  There are five possible
    ** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
    **
    **  Constraint type  Action       What Happens
    **  ---------------  ----------   ----------------------------------------
    **  any              ROLLBACK     The current transaction is rolled back and
    **                                sqlite3_exec() returns immediately with a
    **                                return code of SQLITE_CONSTRAINT.
    **
    **  any              ABORT        Back out changes from the current command
    **                                only (do not do a complete rollback) then
    **                                cause sqlite3_exec() to return immediately
    **                                with SQLITE_CONSTRAINT.
    **
    **  any              FAIL         Sqlite_exec() returns immediately with a
    **                                return code of SQLITE_CONSTRAINT.  The
    **                                transaction is not rolled back and any
    **                                prior changes are retained.
    **
    **  any              IGNORE       The record number and data is popped from
    **                                the stack and there is an immediate jump
    **                                to label ignoreDest.
    **
    **  NOT NULL         REPLACE      The NULL value is replace by the default
    **                                value for that column.  If the default value
    **                                is NULL, the action is the same as ABORT.
    **
    **  UNIQUE           REPLACE      The other row that conflicts with the row
    **                                being inserted is removed.
    **
    **  CHECK            REPLACE      Illegal.  The results in an exception.
    **
    ** Which action to take is determined by the overrideError parameter.
    ** Or if overrideError==OE_Default, then the pParse.onError parameter
    ** is used.  Or if pParse.onError==OE_Default then the onError value
    ** for the constraint is used.
    **
    ** The calling routine must open a read/write cursor for pTab with
    ** cursor number "baseCur".  All indices of pTab must also have open
    ** read/write cursors with cursor number baseCur+i for the i-th cursor.
    ** Except, if there is no possibility of a REPLACE action then
    ** cursors do not need to be open for indices where aRegIdx[i]==0.
    */
    static void sqlite3GenerateConstraintChecks(
    Parse pParse,       /* The parser context */
    Table pTab,         /* the table into which we are inserting */
    int baseCur,        /* Index of a read/write cursor pointing at pTab */
    int regRowid,       /* Index of the range of input registers */
    int[] aRegIdx,      /* Register used by each index.  0 for unused indices */
    bool rowidChng,     /* True if the rowid might collide with existing entry */
    bool isUpdate,      /* True for UPDATE, False for INSERT */
    int overrideError,  /* Override onError to this if not OE_Default */
    int ignoreDest,     /* Jump to this label on an OE_Ignore resolution */
    ref int pbMayReplace   /* OUT: Set to true if constraint may cause a replace */
    )
    {

      int i;               /* loop counter */
      Vdbe v;              /* VDBE under constrution */
      int nCol;            /* Number of columns */
      int onError;         /* Conflict resolution strategy */
      int j1;              /* Addresss of jump instruction */
      int j2 = 0, j3;      /* Addresses of jump instructions */
      int regData;         /* Register containing first data column */
      int iCur;            /* Table cursor number */
      Index pIdx;         /* Pointer to one of the indices */
      bool seenReplace = false; /* True if REPLACE is used to resolve INT PK conflict */
      bool hasTwoRowids = ( isUpdate && rowidChng );

      v = sqlite3GetVdbe( pParse );
      Debug.Assert( v != null );
      Debug.Assert( pTab.pSelect == null );  /* This table is not a VIEW */
      nCol = pTab.nCol;
      regData = regRowid + 1;


      /* Test all NOT NULL constraints.
      */
      for ( i = 0 ; i < nCol ; i++ )
      {
        if ( i == pTab.iPKey )
        {
          continue;
        }
        onError = pTab.aCol[i].notNull;
        if ( onError == OE_None ) continue;
        if ( overrideError != OE_Default )
        {
          onError = overrideError;
        }
        else if ( onError == OE_Default )
        {
          onError = OE_Abort;
        }
        if ( onError == OE_Replace && pTab.aCol[i].pDflt == null )
        {
          onError = OE_Abort;
        }
        Debug.Assert( onError == OE_Rollback || onError == OE_Abort || onError == OE_Fail
        || onError == OE_Ignore || onError == OE_Replace );
        switch ( onError )
        {
          case OE_Rollback:
          case OE_Abort:
          case OE_Fail:
            {
              string zMsg;
              j1 = sqlite3VdbeAddOp3( v, OP_HaltIfNull,
                          SQLITE_CONSTRAINT, onError, regData + i );
              zMsg = sqlite3MPrintf( pParse.db, "%s.%s may not be NULL",
              pTab.zName, pTab.aCol[i].zName );
              sqlite3VdbeChangeP4( v, -1, zMsg, P4_DYNAMIC );
              break;
            }
          case OE_Ignore:
            {
              sqlite3VdbeAddOp2( v, OP_IsNull, regData + i, ignoreDest );
              break;
            }
          default:
            {
              Debug.Assert( onError == OE_Replace );
              j1 = sqlite3VdbeAddOp1( v, OP_NotNull, regData + i );
              sqlite3ExprCode( pParse, pTab.aCol[i].pDflt, regData + i );
              sqlite3VdbeJumpHere( v, j1 );
              break;
            }
        }
      }

      /* Test all CHECK constraints
      */
#if !SQLITE_OMIT_CHECK
      if ( pTab.pCheck != null && ( pParse.db.flags & SQLITE_IgnoreChecks ) == 0 )
      {
        int allOk = sqlite3VdbeMakeLabel( v );
        pParse.ckBase = regData;
        sqlite3ExprIfTrue( pParse, pTab.pCheck, allOk, SQLITE_JUMPIFNULL );
        onError = overrideError != OE_Default ? overrideError : OE_Abort;
        if ( onError == OE_Ignore )
        {
          sqlite3VdbeAddOp2( v, OP_Goto, 0, ignoreDest );
        }
        else
        {
          sqlite3VdbeAddOp2( v, OP_Halt, SQLITE_CONSTRAINT, onError );
        }
        sqlite3VdbeResolveLabel( v, allOk );
      }
#endif // * !SQLITE_OMIT_CHECK) */

      /* If we have an INTEGER PRIMARY KEY, make sure the primary key
** of the new record does not previously exist.  Except, if this
** is an UPDATE and the primary key is not changing, that is OK.
*/
      if ( rowidChng )
      {
        onError = pTab.keyConf;
        if ( overrideError != OE_Default )
        {
          onError = overrideError;
        }
        else if ( onError == OE_Default )
        {
          onError = OE_Abort;
        }

        if ( onError != OE_Replace || pTab.pIndex != null )
        {
          if ( isUpdate )
          {
            j2 = sqlite3VdbeAddOp3( v, OP_Eq, regRowid, 0, regRowid - 1 );
          }
          j3 = sqlite3VdbeAddOp3( v, OP_NotExists, baseCur, 0, regRowid );
          switch ( onError )
          {
            default:
              {
                onError = OE_Abort;
                /* Fall thru into the next case */
              }
              goto case OE_Rollback;
            case OE_Rollback:
            case OE_Abort:
            case OE_Fail:
              {
                sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
                   "PRIMARY KEY must be unique", P4_STATIC );
                break;
              }
            case OE_Replace:
              {
                sqlite3GenerateRowIndexDelete( pParse, pTab, baseCur, 0 );
                seenReplace = true;
                break;
              }
            case OE_Ignore:
              {
                Debug.Assert( !seenReplace );
                sqlite3VdbeAddOp2( v, OP_Goto, 0, ignoreDest );
                break;
              }
          }
          sqlite3VdbeJumpHere( v, j3 );
          if ( isUpdate )
          {
            sqlite3VdbeJumpHere( v, j2 );
          }
        }
      }

      /* Test all UNIQUE constraints by creating entries for each UNIQUE
      ** index and making sure that duplicate entries do not already exist.
      ** Add the new records to the indices as we go.
      */
      for ( iCur = 0, pIdx = pTab.pIndex ; pIdx != null ; pIdx = pIdx.pNext, iCur++ )
      {
        int regIdx;
        int regR;

        if ( aRegIdx[iCur] == 0 ) continue;  /* Skip unused indices */

        /* Create a key for accessing the index entry */
        regIdx = sqlite3GetTempRange( pParse, pIdx.nColumn + 1 );
        for ( i = 0 ; i < pIdx.nColumn ; i++ )
        {
          int idx = pIdx.aiColumn[i];
          if ( idx == pTab.iPKey )
          {
            sqlite3VdbeAddOp2( v, OP_SCopy, regRowid, regIdx + i );
          }
          else
          {
            sqlite3VdbeAddOp2( v, OP_SCopy, regData + idx, regIdx + i );
          }
        }
        sqlite3VdbeAddOp2( v, OP_SCopy, regRowid, regIdx + i );
        sqlite3VdbeAddOp3( v, OP_MakeRecord, regIdx, pIdx.nColumn + 1, aRegIdx[iCur] );
        sqlite3IndexAffinityStr( v, pIdx );
        sqlite3ExprCacheAffinityChange( pParse, regIdx, pIdx.nColumn + 1 );

        /* Find out what action to take in case there is an indexing conflict */
        onError = pIdx.onError;
        if ( onError == OE_None )
        {
          sqlite3ReleaseTempRange( pParse, regIdx, pIdx.nColumn + 1 );
          continue;  /* pIdx is not a UNIQUE index */
        }

        if ( overrideError != OE_Default )
        {
          onError = overrideError;
        }
        else if ( onError == OE_Default )
        {
          onError = OE_Abort;
        }
        if ( seenReplace )
        {
          if ( onError == OE_Ignore ) onError = OE_Replace;
          else if ( onError == OE_Fail ) onError = OE_Abort;
        }


        /* Check to see if the new index entry will be unique */
        regR = sqlite3GetTempReg( pParse );
        sqlite3VdbeAddOp2( v, OP_SCopy, regRowid - ( hasTwoRowids ? 1 : 0 ), regR );
        j3 = sqlite3VdbeAddOp4( v, OP_IsUnique, baseCur + iCur + 1, 0,
        regR, regIdx,//regR, SQLITE_INT_TO_PTR(regIdx),
        P4_INT32 );
        sqlite3ReleaseTempRange( pParse, regIdx, pIdx.nColumn + 1 );

        /* Generate code that executes if the new index entry is not unique */
        Debug.Assert( onError == OE_Rollback || onError == OE_Abort || onError == OE_Fail
        || onError == OE_Ignore || onError == OE_Replace );
        switch ( onError )
        {
          case OE_Rollback:
          case OE_Abort:
          case OE_Fail:
            {
              int j;
              StrAccum errMsg = new StrAccum();
              string zSep;
              string zErr;

              sqlite3StrAccumInit( errMsg, new StringBuilder( 200 ), 0, 200 );
              errMsg.db = pParse.db;
              zSep = pIdx.nColumn > 1 ? "columns " : "column ";
              for ( j = 0 ; j < pIdx.nColumn ; j++ )
              {
                string zCol = pTab.aCol[pIdx.aiColumn[j]].zName;
                sqlite3StrAccumAppend( errMsg, zSep, -1 );
                zSep = ", ";
                sqlite3StrAccumAppend( errMsg, zCol, -1 );
              }
              sqlite3StrAccumAppend( errMsg,
              pIdx.nColumn > 1 ? " are not unique" : " is not unique", -1 );
              zErr = sqlite3StrAccumFinish( errMsg );
              sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErr, 0 );
              //sqlite3DbFree( errMsg.db, zErr );
              break;
            }
          case OE_Ignore:
            {
              Debug.Assert( !seenReplace );
              sqlite3VdbeAddOp2( v, OP_Goto, 0, ignoreDest );
              break;
            }
          default:
            {
              Debug.Assert( onError == OE_Replace );
              sqlite3GenerateRowDelete( pParse, pTab, baseCur, regR, 0 );
              seenReplace = true;
              break;
            }
        }
        sqlite3VdbeJumpHere( v, j3 );
        sqlite3ReleaseTempReg( pParse, regR );
      }
      //if ( pbMayReplace )
      {
        pbMayReplace = seenReplace ? 1 : 0;
      }
    }
Пример #8
0
    /*
** variable-argument wrapper around sqlite3VXPrintf().
*/
    static void sqlite3XPrintf( StrAccum p, string zFormat, params object[] ap )
    {
      //va_list ap;
      lock ( lock_va_list )
      {
        va_start( ap, zFormat );
        sqlite3VXPrintf( p, 1, zFormat, ap );
        va_end( ref ap );
      }
    }
Пример #9
0
    static public string sqlite3_snprintf( int n, ref string zBuf, string zFormat, params va_list[] ap )
    {
      string z;
      StringBuilder zBase = new StringBuilder( SQLITE_PRINT_BUF_SIZE );
      //va_list ap;
      StrAccum acc = new StrAccum();

      if ( n <= 0 )
      {
        return zBuf;
      }
      sqlite3StrAccumInit( acc, zBase, n, 0 );
      acc.useMalloc = 0;
      va_start( ap, zFormat );
      sqlite3VXPrintf( acc, 0, zFormat, ap );
      va_end( ap );
      z = sqlite3StrAccumFinish( acc );
      return ( zBuf = z );
    }
Пример #10
0
    /*
** A version of printf() that understands %lld.  Used for debugging.
** The printf() built into some versions of windows does not understand %lld
** and segfaults if you give it a long long int.
*/
    static void sqlite3DebugPrintf( string zFormat, params va_list[] ap )
    {
      //va_list ap;
      StrAccum acc = new StrAccum();
      StringBuilder zBuf = new StringBuilder( SQLITE_PRINT_BUF_SIZE );
      sqlite3StrAccumInit( acc, zBuf, zBuf.Capacity, 0 );
      acc.useMalloc = 0;
      va_start( ap, zFormat );
      sqlite3VXPrintf( acc, 0, zFormat, ap );
      va_end( ap );
      sqlite3StrAccumFinish( acc );
      Console.Write( zBuf.ToString() );
      //fflush(stdout);
    }
Пример #11
0
    /*
    ** sqlite3_snprintf() works like snprintf() except that it ignores the
    ** current locale settings.  This is important for SQLite because we
    ** are not able to use a "," as the decimal point in place of "." as
    ** specified by some locales.
    */
    static public string sqlite3_snprintf( int n, ref StringBuilder zBuf, string zFormat, params va_list[] ap )
    {
      StringBuilder zBase = new StringBuilder( SQLITE_PRINT_BUF_SIZE );
      //va_list ap;
      StrAccum acc = new StrAccum();

      if ( n <= 0 )
      {
        return zBuf.ToString();
      }
      sqlite3StrAccumInit( acc, zBase, n, 0 );
      acc.useMalloc = 0;
      va_start( ap, zFormat );
      sqlite3VXPrintf( acc, 0, zFormat, ap );
      va_end( ap );
      zBuf.Length = 0;
      zBuf.Append( sqlite3StrAccumFinish( acc ) );
      if ( n - 1 < zBuf.Length ) zBuf.Length = n - 1;
      return zBuf.ToString();
    }
Пример #12
0
    /*
    ** Print into memory obtained from sqlite3Malloc().  Omit the internal
    ** %-conversion extensions.
    */
    static string sqlite3_vmprintf( string zFormat, params  va_list[] ap )
    {
      string z;
      StringBuilder zBase = new StringBuilder( SQLITE_PRINT_BUF_SIZE );
      StrAccum acc = new StrAccum();
#if !SQLITE_OMIT_AUTOINIT
      if ( sqlite3_initialize() != 0 ) return "";
#endif
      sqlite3StrAccumInit( acc, zBase, zBase.Length, SQLITE_PRINT_BUF_SIZE );//zBase).Length;
      sqlite3VXPrintf( acc, 0, zFormat, ap );
      z = sqlite3StrAccumFinish( acc );
      return z;
    }
Пример #13
0
    /*
    ** Print into memory obtained from sqliteMalloc().  Use the internal
    ** %-conversion extensions.
    */
    static string sqlite3VMPrintf( sqlite3 db, string zFormat, params va_list[] ap )
    {
      if ( zFormat == null ) return null;
      if ( ap.Length == 0 ) return zFormat;
      string z;
      StringBuilder zBase = new StringBuilder( SQLITE_PRINT_BUF_SIZE );
      StrAccum acc = new StrAccum();
      Debug.Assert( db != null );
      sqlite3StrAccumInit( acc, zBase, zBase.Capacity, //zBase).Length;
      db.aLimit[SQLITE_LIMIT_LENGTH] );
      acc.db = db;
      sqlite3VXPrintf( acc, 1, zFormat, ap );
      z = sqlite3StrAccumFinish( acc );
//      if ( acc.mallocFailed != 0 )
//      {
//////        db.mallocFailed = 1;
//      }
      return z;
    }
Пример #14
0
 /*
 ** Reset an StrAccum string.  Reclaim all malloced memory.
 */
 static void sqlite3StrAccumReset( StrAccum p )
 {
   //if ( p.zText.ToString() != p.zBase.ToString() )
   //{
   //  if ( p.useMalloc == 1 )
   //  {
   //    sqlite3DbFree( p.db, ref p.zText );
   //  }
   //  else
   //  {
   //    sqlite3_free( ref p.zText );
   //  }
   //}
   p.zText.Length = 0;
 }
Пример #15
0
		/*
		** This function returns a pointer to a nul-terminated string in memory
		** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
		** string contains a copy of zRawSql but with host parameters expanded to 
		** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, 
		** then the returned string holds a copy of zRawSql with "-- " prepended
		** to each line of text.
		**
		** The calling function is responsible for making sure the memory returned
		** is eventually freed.
		**
		** ALGORITHM:  Scan the input string looking for host parameters in any of
		** these forms:  ?, ?N, $A, @A, :A.  Take care to avoid text within
		** string literals, quoted identifier names, and comments.  For text forms,
		** the host parameter index is found by scanning the perpared
		** statement for the corresponding OP_Variable opcode.  Once the host
		** parameter index is known, locate the value in p->aVar[].  Then render
		** the value as a literal in place of the host parameter name.
		*/
		static string sqlite3VdbeExpandSql(
		Vdbe p,                  /* The prepared statement being evaluated */
		string zRawSql           /* Raw text of the SQL statement */
		)
		{
			sqlite3 db;              /* The database connection */
			int idx = 0;             /* Index of a host parameter */
			int nextIndex = 1;       /* Index of next ? host parameter */
			int n;                   /* Length of a token prefix */
			int nToken = 0;          /* Length of the parameter token */
			int i;                   /* Loop counter */
			Mem pVar;                /* Value of a host parameter */
			StrAccum _out = new StrAccum(1000);               /* Accumulate the _output here */
			StringBuilder zBase = new StringBuilder(100); /* Initial working space */
			int izRawSql = 0;

			db = p.db;
			sqlite3StrAccumInit(_out, null, 100,
				  db.aLimit[SQLITE_LIMIT_LENGTH]);
			_out.db = db;
			if (db.vdbeExecCnt > 1)
			{
				while (izRawSql < zRawSql.Length)
				{
					//string zStart = zRawSql;
					while (zRawSql[izRawSql++] != '\n' && izRawSql < zRawSql.Length)
						;
					sqlite3StrAccumAppend(_out, "-- ", 3);
					sqlite3StrAccumAppend(_out, zRawSql, (int)izRawSql);//zRawSql - zStart );
				}
			}
			else
			{
				while (izRawSql < zRawSql.Length)
				{
					n = findNextHostParameter(zRawSql, izRawSql, ref nToken);
					Debug.Assert(n > 0);
					sqlite3StrAccumAppend(_out, zRawSql.Substring(izRawSql, n), n);
					izRawSql += n;
					Debug.Assert(izRawSql < zRawSql.Length || nToken == 0);
					if (nToken == 0)
						break;
					if (zRawSql[izRawSql] == '?')
					{
						if (nToken > 1)
						{
							Debug.Assert(sqlite3Isdigit(zRawSql[izRawSql + 1]));
							sqlite3GetInt32(zRawSql, izRawSql + 1, ref idx);
						}
						else
						{
							idx = nextIndex;
						}
					}
					else
					{
						Debug.Assert(zRawSql[izRawSql] == ':' || zRawSql[izRawSql] == '$' || zRawSql[izRawSql] == '@');
						testcase(zRawSql[izRawSql] == ':');
						testcase(zRawSql[izRawSql] == '$');
						testcase(zRawSql[izRawSql] == '@');
						idx = sqlite3VdbeParameterIndex(p, zRawSql.Substring(izRawSql, nToken), nToken);
						Debug.Assert(idx > 0);
					}
					izRawSql += nToken;
					nextIndex = idx + 1;
					Debug.Assert(idx > 0 && idx <= p.nVar);
					pVar = p.aVar[idx - 1];
					if ((pVar.flags & MEM_Null) != 0)
					{
						sqlite3StrAccumAppend(_out, "NULL", 4);
					}
					else if ((pVar.flags & MEM_Int) != 0)
					{
						sqlite3XPrintf(_out, "%lld", pVar.u.i);
					}
					else if ((pVar.flags & MEM_Real) != 0)
					{
						sqlite3XPrintf(_out, "%!.15g", pVar.r);
					}
					else if ((pVar.flags & MEM_Str) != 0)
					{
#if !SQLITE_OMIT_UTF16
u8 enc = ENC(db);
if( enc!=SQLITE_UTF8 ){
Mem utf8;
memset(&utf8, 0, sizeof(utf8));
utf8.db = db;
sqlite3VdbeMemSetStr(&utf8, pVar.z, pVar.n, enc, SQLITE_STATIC);
sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
sqlite3XPrintf(_out, "'%.*q'", utf8.n, utf8.z);
sqlite3VdbeMemRelease(&utf8);
}else
#endif
						{
							sqlite3XPrintf(_out, "'%.*q'", pVar.n, pVar.z);
						}
					}
					else if ((pVar.flags & MEM_Zero) != 0)
					{
						sqlite3XPrintf(_out, "zeroblob(%d)", pVar.u.nZero);
					}
					else
					{
						Debug.Assert((pVar.flags & MEM_Blob) != 0);
						sqlite3StrAccumAppend(_out, "x'", 2);
						for (i = 0; i < pVar.n; i++)
						{
							sqlite3XPrintf(_out, "%02x", pVar.zBLOB[i] & 0xff);
						}
						sqlite3StrAccumAppend(_out, "'", 1);
					}
				}
			}
			return sqlite3StrAccumFinish(_out);
		}
Пример #16
0
 /*
 ** Initialize a string accumulator
 */
 static void sqlite3StrAccumInit( StrAccum p, StringBuilder zBase, int n, int mx )
 {
   //p.zBase.Length = 0;
   //if ( p.zBase.Capacity < n )
   //  p.zBase.Capacity = n;
   p.zText.Length = 0;
   if ( p.zText.Capacity < n )
     p.zText.Capacity = n;
   p.db = null;
   //p.nChar = 0;
   //p.nAlloc = n;
   p.mxAlloc = mx;
   //p.useMalloc = 1;
   //p.tooBig = 0;
   //p.mallocFailed = 0;
 }
Пример #17
0
 /*
 ** Finish off a string by making sure it is zero-terminated.
 ** Return a pointer to the resulting string.  Return a NULL
 ** pointer if any kind of error was encountered.
 */
 static string sqlite3StrAccumFinish( StrAccum p )
 {
   //if (p.zText.Length > 0)
   //{
   //  p.zText[p.nChar] = 0;
   //  if (p.useMalloc && p.zText == p.zBase)
   //  {
   //    p.zText = sqlite3DbMalloc(p.nChar + 1);
   //    if (p.zText)
   //    {
   //      memcpy(p.zText, p.zBase, p.nChar + 1);
   //    }
   //    else
   //    {
   //      p.mallocFailed = 1;
   //    }
   //  }
   //}
   return p.zText.ToString();
 }
Пример #18
0
    /*
** Append N space characters to the given string buffer.
*/
    static void appendSpace( StrAccum pAccum, int N )
    {
      //static const char zSpaces[] = "                             ";
      //while( N>=zSpaces.Length-1 ){
      //  sqlite3StrAccumAppend(pAccum, zSpaces, zSpaces.Length-1);
      //  N -= zSpaces.Length-1;
      //}
      //if( N>0 ){
      //  sqlite3StrAccumAppend(pAccum, zSpaces, N);
      //}
      pAccum.zText.AppendFormat( "{0," + N + "}", "" );
    }
Пример #19
0
 /*
 ** Reset an StrAccum string.  Reclaim all malloced memory.
 */
 static void sqlite3StrAccumReset( StrAccum p )
 {
   if ( p.zText.ToString() != p.zBase.ToString() )
   {
     sqlite3DbFree( p.db, ref p.zText );
   }
   p.zText.Length = 0;
 }
Пример #20
0
        /*
        ** This function returns a pointer to a nul-terminated string in memory
        ** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
        ** string contains a copy of zRawSql but with host parameters expanded to
        ** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1,
        ** then the returned string holds a copy of zRawSql with "-- " prepended
        ** to each line of text.
        **
        ** The calling function is responsible for making sure the memory returned
        ** is eventually freed.
        **
        ** ALGORITHM:  Scan the input string looking for host parameters in any of
        ** these forms:  ?, ?N, $A, @A, :A.  Take care to avoid text within
        ** string literals, quoted identifier names, and comments.  For text forms,
        ** the host parameter index is found by scanning the perpared
        ** statement for the corresponding OP_Variable opcode.  Once the host
        ** parameter index is known, locate the value in p->aVar[].  Then render
        ** the value as a literal in place of the host parameter name.
        */
        static string sqlite3VdbeExpandSql(
            Vdbe p,          /* The prepared statement being evaluated */
            string zRawSql   /* Raw text of the SQL statement */
            )
        {
            sqlite3  db;                            /* The database connection */
            int      idx       = 0;                 /* Index of a host parameter */
            int      nextIndex = 1;                 /* Index of next ? host parameter */
            int      n;                             /* Length of a token prefix */
            int      nToken = 0;                    /* Length of the parameter token */
            int      i;                             /* Loop counter */
            Mem      pVar;                          /* Value of a host parameter */
            StrAccum _out     = new StrAccum(1000); /* Accumulate the _output here */
            int      izRawSql = 0;

            db = p.db;
            sqlite3StrAccumInit(_out, null, 100,
                                db.aLimit[SQLITE_LIMIT_LENGTH]);
            _out.db = db;
            if (db.vdbeExecCnt > 1)
            {
                while (izRawSql < zRawSql.Length)
                {
                    //string zStart = zRawSql;
                    while (zRawSql[izRawSql++] != '\n' && izRawSql < zRawSql.Length)
                    {
                        ;
                    }
                    sqlite3StrAccumAppend(_out, "-- ", 3);
                    sqlite3StrAccumAppend(_out, zRawSql, (int)izRawSql);//zRawSql - zStart );
                }
            }
            else
            {
                while (izRawSql < zRawSql.Length)
                {
                    n = findNextHostParameter(zRawSql, izRawSql, ref nToken);
                    Debug.Assert(n > 0);
                    sqlite3StrAccumAppend(_out, zRawSql.Substring(izRawSql, n), n);
                    izRawSql += n;
                    Debug.Assert(izRawSql < zRawSql.Length || nToken == 0);
                    if (nToken == 0)
                    {
                        break;
                    }
                    if (zRawSql[izRawSql] == '?')
                    {
                        if (nToken > 1)
                        {
                            Debug.Assert(sqlite3Isdigit(zRawSql[izRawSql + 1]));
                            sqlite3GetInt32(zRawSql, izRawSql + 1, ref idx);
                        }
                        else
                        {
                            idx = nextIndex;
                        }
                    }
                    else
                    {
                        Debug.Assert(zRawSql[izRawSql] == ':' || zRawSql[izRawSql] == '$' || zRawSql[izRawSql] == '@');
                        testcase(zRawSql[izRawSql] == ':');
                        testcase(zRawSql[izRawSql] == '$');
                        testcase(zRawSql[izRawSql] == '@');
                        idx = sqlite3VdbeParameterIndex(p, zRawSql.Substring(izRawSql, nToken), nToken);
                        Debug.Assert(idx > 0);
                    }
                    izRawSql += nToken;
                    nextIndex = idx + 1;
                    Debug.Assert(idx > 0 && idx <= p.nVar);
                    pVar = p.aVar[idx - 1];
                    if ((pVar.flags & MEM_Null) != 0)
                    {
                        sqlite3StrAccumAppend(_out, "NULL", 4);
                    }
                    else if ((pVar.flags & MEM_Int) != 0)
                    {
                        sqlite3XPrintf(_out, "%lld", pVar.u.i);
                    }
                    else if ((pVar.flags & MEM_Real) != 0)
                    {
                        sqlite3XPrintf(_out, "%!.15g", pVar.r);
                    }
                    else if ((pVar.flags & MEM_Str) != 0)
                    {
#if !SQLITE_OMIT_UTF16
                        u8 enc = ENC(db);
                        if (enc != SQLITE_UTF8)
                        {
                            Mem utf8;
                            memset(&utf8, 0, sizeof(utf8));
                            utf8.db = db;
                            sqlite3VdbeMemSetStr(&utf8, pVar.z, pVar.n, enc, SQLITE_STATIC);
                            sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
                            sqlite3XPrintf(_out, "'%.*q'", utf8.n, utf8.z);
                            sqlite3VdbeMemRelease(&utf8);
                        }
                        else
#endif
                        {
                            sqlite3XPrintf(_out, "'%.*q'", pVar.n, pVar.z);
                        }
                    }
                    else if ((pVar.flags & MEM_Zero) != 0)
                    {
                        sqlite3XPrintf(_out, "zeroblob(%d)", pVar.u.nZero);
                    }
                    else
                    {
                        Debug.Assert((pVar.flags & MEM_Blob) != 0);
                        sqlite3StrAccumAppend(_out, "x'", 2);
                        for (i = 0; i < pVar.n; i++)
                        {
                            sqlite3XPrintf(_out, "%02x", pVar.zBLOB[i] & 0xff);
                        }
                        sqlite3StrAccumAppend(_out, "'", 1);
                    }
                }
            }
            return(sqlite3StrAccumFinish(_out));
        }
Пример #21
0
 /*
 ** Reset an StrAccum string.  Reclaim all malloced memory.
 */
 static void sqlite3StrAccumReset( StrAccum p )
 {
   if ( p.zText.ToString() != p.zBase.ToString() )
   {
     //sqlite3DbFree( p.db, ref p.zText );
   }
   p.zText = new StringBuilder();
 }