Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -21,11 +21,11 @@ ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.227 2004/06/19 17:33:07 drh Exp $ +** $Id: build.c,v 1.228 2004/06/21 09:06:42 danielk1977 Exp $ */ #include "sqliteInt.h" #include /* @@ -1377,11 +1377,11 @@ } assert( pEnd!=0 ); n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1; sqlite3VdbeAddOp(v, OP_String8, 0, 0); sqlite3VdbeChangeP3(v, -1, pParse->sNameToken.z, n); - sqlite3VdbeAddOp(v, OP_Concat, 2, 0); + sqlite3VdbeAddOp(v, OP_Concat8, 2, 0); } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); if( p->iDb!=1 ){ sqlite3ChangeCookie(db, v, p->iDb); @@ -2176,11 +2176,11 @@ sqlite3VdbeChangeP3(v, -1, "CREATE UNIQUE INDEX ", P3_STATIC); } sqlite3VdbeAddOp(v, OP_String8, 0, 0); n = Addr(pEnd->z) - Addr(pName->z) + 1; sqlite3VdbeChangeP3(v, -1, pName->z, n); - sqlite3VdbeAddOp(v, OP_Concat, 2, 0); + sqlite3VdbeAddOp(v, OP_Concat8, 2, 0); } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); if( pTblName ){ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.146 2004/06/21 07:36:32 danielk1977 Exp $ +** $Id: expr.c,v 1.147 2004/06/21 09:06:42 danielk1977 Exp $ */ #include "sqliteInt.h" #include char const *sqlite3AffinityString(char affinity){ @@ -1179,11 +1179,11 @@ break; } case TK_CONCAT: { sqlite3ExprCode(pParse, pExpr->pLeft); sqlite3ExprCode(pParse, pExpr->pRight); - sqlite3VdbeAddOp(v, OP_Concat, 2, 0); + sqlite3VdbeAddOp(v, OP_Concat8, 2, 0); break; } case TK_UMINUS: { Expr *pLeft = pExpr->pLeft; assert( pLeft ); Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.51 2004/06/21 08:18:53 danielk1977 Exp $ +** $Id: pragma.c,v 1.52 2004/06/21 09:06:42 danielk1977 Exp $ */ #include "sqliteInt.h" #include #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) @@ -664,11 +664,11 @@ sqlite3VdbeAddOp(v, OP_Eq, 0, addr+6); sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName), P3_DYNAMIC); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); - sqlite3VdbeAddOp(v, OP_Concat, 2, 1); + sqlite3VdbeAddOp(v, OP_Concat8, 2, 1); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); /* Make sure all the indices are constructed correctly. */ sqlite3CodeVerifySchema(pParse, i); @@ -697,11 +697,11 @@ { OP_MemIncr, 0, 0, 0}, { OP_String8, 0, 0, "rowid "}, { OP_Recno, 1, 0, 0}, { OP_String8, 0, 0, " missing from index "}, { OP_String8, 0, 0, 0}, /* 4 */ - { OP_Concat, 4, 0, 0}, + { OP_Concat8, 4, 0, 0}, { OP_Callback, 1, 0, 0}, }; sqlite3GenerateIndexKey(v, pIdx, 1); jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0); addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); @@ -721,11 +721,11 @@ { OP_MemLoad, 2, 0, 0}, { OP_Eq, 0, 0, 0}, /* 7 */ { OP_MemIncr, 0, 0, 0}, { OP_String8, 0, 0, "wrong # of entries in index "}, { OP_String8, 0, 0, 0}, /* 10 */ - { OP_Concat, 2, 0, 0}, + { OP_Concat8, 2, 0, 0}, { OP_Callback, 1, 0, 0}, }; if( pIdx->tnum==0 ) continue; addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); sqlite3VdbeChangeP1(v, addr+2, j+2); Index: src/trigger.c ================================================================== --- src/trigger.c +++ src/trigger.c @@ -217,11 +217,11 @@ { OP_String8, 0, 0, 0 }, /* 2: trigger name */ { OP_String8, 0, 0, 0 }, /* 3: table name */ { OP_Integer, 0, 0, 0 }, { OP_String8, 0, 0, "CREATE TRIGGER "}, { OP_String8, 0, 0, 0 }, /* 6: SQL */ - { OP_Concat, 2, 0, 0 }, + { OP_Concat8, 2, 0, 0 }, { OP_MakeRecord, 5, 0, "tttit" }, { OP_PutIntKey, 0, 0, 0 }, }; int addr; Vdbe *v; Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.382 2004/06/21 06:50:29 danielk1977 Exp $ +** $Id: vdbe.c,v 1.383 2004/06/21 09:06:42 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include "vdbeInt.h" @@ -766,15 +766,15 @@ break; } /* Opcode: HexBlob * * P3 ** -** P3 is an SQL hex encoding of a blob. The blob is pushed -** onto the vdbe stack. +** P3 is an UTF-8 SQL hex encoding of a blob. The blob is pushed onto the +** vdbe stack. ** -** The first time this instruction executes, in transforms -** itself into a 'Blob' opcode with a binary blob as P3. +** The first time this instruction executes, in transforms itself into a +** 'Blob' opcode with a binary blob as P3. */ case OP_HexBlob: { pOp->opcode = OP_Blob; pOp->p1 = strlen(pOp->p3)/2; if( pOp->p1 ){ @@ -1015,10 +1015,42 @@ p->popStack = pOp->p1; p->pc = pc + 1; p->pTos = pTos; return SQLITE_ROW; } + +/* Opcode: Concat8 P1 P2 P3 +** +** P3 points to a nul terminated UTF-8 string. When it is executed for +** the first time, P3 is converted to the native database encoding and +** the opcode replaced with Concat (see Concat for details of processing). +*/ +case OP_Concat8: { + pOp->opcode = OP_Concat; + + if( db->enc!=SQLITE_UTF8 && pOp->p3 ){ + Mem tmp; + tmp.flags = MEM_Null; + sqlite3VdbeMemSetStr(&tmp, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC); + if( SQLITE_OK!=sqlite3VdbeChangeEncoding(&tmp, db->enc) || + SQLITE_OK!=sqlite3VdbeMemDynamicify(&tmp) + ){ + goto no_mem; + } + assert( tmp.flags|MEM_Dyn ); + assert( !tmp.xDel ); + pOp->p3type = P3_DYNAMIC; + pOp->p3 = tmp.z; + /* Don't call sqlite3VdbeMemRelease() on &tmp, the dynamic allocation + ** is cleaned up when the vdbe is deleted. + */ + } + + /* If it wasn't already, P3 has been converted to the database text + ** encoding. Fall through to OP_Concat to process this instruction. + */ +} /* Opcode: Concat P1 P2 P3 ** ** Look at the first P1 elements of the stack. Append them all ** together with the lowest element first. Use P3 as a separator. @@ -1036,20 +1068,19 @@ int nField; int i, j; Mem *pTerm; Mem mSep; /* Memory cell containing the seperator string, if any */ - /* FIX ME: Eventually, P3 will be in database native encoding. But for - ** now it is always UTF-8. So set up zSep to hold the native encoding of - ** P3. - */ if( pOp->p3 ){ mSep.z = pOp->p3; - mSep.n = strlen(mSep.z); + if( db->enc==SQLITE_UTF8 ){ + mSep.n = strlen(mSep.z); + }else{ + mSep.n = sqlite3utf16ByteLen(mSep.z, -1); + } mSep.flags = MEM_Str|MEM_Static|MEM_Term; - mSep.enc = SQLITE_UTF8; - sqlite3VdbeChangeEncoding(&mSep, db->enc); + mSep.enc = db->enc; }else{ mSep.flags = MEM_Null; mSep.n = 0; } @@ -3612,42 +3643,10 @@ goto abort_due_to_error; } pTos->flags = MEM_Int; pTos->i = rowid; } - -#if 0 - /* Read the final 9 bytes of the key into buf[]. If the whole key is - ** less than 9 bytes then just load the whole thing. Set len to the - ** number of bytes read. - */ - sqlite3BtreeKeySize(pCrsr, &sz); - len = ((sz>10)?10:sz); - rc = sqlite3BtreeKey(pCrsr, sz-len, len, buf); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; - } - - len--; - if( buf[len]&0x80 ){ - /* If the last byte read has the 0x80 bit set, then the key does - ** not end with a varint. Push a NULL onto the stack instead. - */ - pTos->flags = MEM_Null; - }else{ - /* Find the start of the varint by searching backwards for a 0x00 - ** byte. If one does not exists, then intepret the whole 9 bytes as a - ** varint. - */ - while( len && buf[len-1] ){ - len--; - } - sqlite3GetVarint32(&buf[len], &sz); - pTos->flags = MEM_Int; - pTos->i = sz; - } -#endif }else{ pTos->flags = MEM_Null; } break; } @@ -4037,15 +4036,10 @@ sizeof(Context) * p->contextStackDepth); if( p->contextStack==0 ) goto no_mem; p->contextStack[p->contextStackDepth - 1].lastRowid = p->db->lastRowid; p->contextStack[p->contextStackDepth - 1].nChange = p->nChange; - -#if 0 - p->contextStack[p->contextStackDepth - 1].lsChange = p->db->lsChange; - p->contextStack[p->contextStackDepth - 1].csChange = p->db->csChange; -#endif break; } /* Opcode: ContextPop * * * ** @@ -4056,14 +4050,10 @@ case OP_ContextPop: { assert(p->contextStackDepth > 0); p->contextStackDepth--; p->db->lastRowid = p->contextStack[p->contextStackDepth].lastRowid; p->nChange = p->contextStack[p->contextStackDepth].nChange; -#if 0 - p->db->lsChange = p->contextStack[p->contextStackDepth].lsChange; - p->db->csChange = p->contextStack[p->contextStackDepth].csChange; -#endif if( p->contextStackDepth == 0 ){ sqliteFree(p->contextStack); p->contextStack = 0; } break;