-C Change\ssome\scode\sthat\sassumes\sthe\sroot-page\sof\ssqlite_master\sis\s2\s(it\sis\nnow\s1)\s(CVS\s1333)
-D 2004-05-10T01:17:37
+C Add\sversions\sof\sOP_MakeRecord\sand\sOP_Column\sthat\suse\smanifest\styping\s(not\nactivated\syet).\s(CVS\s1334)
+D 2004-05-10T07:17:31
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F src/select.c d3868613e70ac09cf2fb4ddd211f088351d1fe51
F src/shell.c 9a242ad03c8726823f182bff81c5e12ef2882f93
F src/sqlite.h.in 532e08163a8df8b71faf7be4e69ba208938eb312
-F src/sqliteInt.h 92fb41170e75e1ce9ad8aea591fd55e7cf49b815
+F src/sqliteInt.h 987dd79044a37a37f1c386d5e3bcd702c62e27ab
F src/table.c 882b0ae9524c67758157540dd6467c9a5de52335
F src/tclsqlite.c 21147148e7b57a0bb7409cff5878c60470df9acc
F src/test1.c 67a72fa1f5f6d41c838fa97f324f8dbfb4051413
F src/trigger.c 8b07ff87b39f24997e5f737340ebbb5ce09ca481
F src/update.c 475465fc0582160dadf5455b05235cb13c9e21f9
F src/utf.c fc799748d43fe1982d157b871e3e420a19c85d4f
-F src/util.c 0c31a53b848648271d0910c2604b4d8ae516ebb1
+F src/util.c da3b43129c8912eeee1ef0599e740331ed5b8c39
F src/vacuum.c 91ba5a23eca2d9a8a11191cef577d417f9318976
-F src/vdbe.c bf7d4826cbf18c49b7ac1a5ddbc70db65ac35487
+F src/vdbe.c 3d90858d784c4353a6e5ee45a0e4d82b9ba2aa5c
F src/vdbe.h 2dc4d1161b64f5684faa6a2d292e318a185ecb2e
-F src/vdbeInt.h 19926d40956eea309f58bc569f9ae02f62350db2
-F src/vdbeaux.c 2789bdd1f9b510b35b0102174a5b73b8267c4f71
+F src/vdbeInt.h e4ab46c223bac43754335cdd14c9c6a95885b9a8
+F src/vdbeaux.c 4dac7718b04e6773aba8586221faadd62aa742a7
F src/where.c 6db0291280f2c642bae2c69a70750325b53717a4
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/attach.test ba8261d38da6b6a7d4f78ec543c548c4418582ef
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P d8d1c91e55f24d17233414facaa03136b3b320d5
-R d45fafcad74fbf012530271bdce1ade4
+P 37ae528fb85799007f4ddfc56a7d9493dbb29cbf
+R c990744bdc97fc1baad79ce9e836f1a6
U danielk1977
-Z c59557a5034f7f7676ea623232f2d759
+Z e5f755ccd557a6659426f0557b9e2215
** 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.271 2004/05/09 23:23:58 danielk1977 Exp $
+** $Id: vdbe.c,v 1.272 2004/05/10 07:17:32 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
break;
}
+/* Opcode: Column3 P1 P2 *
+**
+** This opcode (not yet in use) is a replacement for the current
+** OP_Column3 that supports the SQLite3 manifest typing feature.
+**
+** Interpret the data that cursor P1 points to as
+** a structure built using the MakeRecord instruction.
+** (See the MakeRecord opcode for additional information about
+** the format of the data.)
+** Push onto the stack the value of the P2-th column contained
+** in the data.
+**
+** If the KeyAsData opcode has previously executed on this cursor,
+** then the field might be extracted from the key rather than the
+** data.
+**
+** If P1 is negative, then the record is stored on the stack rather
+** than in a table. For P1==-1, the top of the stack is used.
+** For P1==-2, the next on the stack is used. And so forth. The
+** value pushed is always just a pointer into the record which is
+** stored further down on the stack. The column value is not copied.
+*/
+case OP_Column3: {
+ int payloadSize;
+ int i = pOp->p1;
+ int p2 = pOp->p2;
+ Cursor *pC;
+ char *zRec;
+ BtCursor *pCrsr;
+
+ char *zHdr = 0;
+ int freeZHdr = 0;
+ int dataOffsetLen;
+ u64 dataOffset;
+ char *zIdx = 0;
+ int cnt;
+ u64 idxN;
+ u64 idxN1;
+
+ assert( i<p->nCursor );
+ pTos++;
+ if( i<0 ){
+ assert( &pTos[i]>=p->aStack );
+ assert( pTos[i].flags & MEM_Str );
+ zRec = pTos[i].z;
+ payloadSize = pTos[i].n;
+ }else if( (pC = &p->aCsr[i])->pCursor!=0 ){
+ sqlite3VdbeCursorMoveto(pC);
+ zRec = 0;
+ pCrsr = pC->pCursor;
+ if( pC->nullRow ){
+ payloadSize = 0;
+ }else if( pC->keyAsData ){
+ u64 payloadSize64;
+ sqlite3BtreeKeySize(pCrsr, &payloadSize64);
+ payloadSize = payloadSize64;
+ }else{
+ sqlite3BtreeDataSize(pCrsr, &payloadSize);
+ }
+ }else if( pC->pseudoTable ){
+ payloadSize = pC->nData;
+ zRec = pC->pData;
+ assert( payloadSize==0 || zRec!=0 );
+ }else{
+ payloadSize = 0;
+ }
+
+ /* If payloadSize is 0, then just push a NULL onto the stack. */
+ if( payloadSize==0 ){
+ pTos->flags = MEM_Null;
+ break;
+ }
+
+ /* Read the data-offset for this record */
+ if( zRec ){
+ dataOffsetLen = sqlite3GetVarint(zRec, &dataOffset);
+ }else{
+ unsigned char zDataOffset[9];
+ if( pC->keyAsData ){
+ sqlite3BtreeKey(pCrsr, 0, 9, zDataOffset);
+ }else{
+ sqlite3BtreeData(pCrsr, 0, 9, zDataOffset);
+ }
+ dataOffsetLen = sqlite3GetVarint(zDataOffset, &dataOffset);
+ }
+
+ /* Set zHdr to point at the start of the Idx() fields of the
+ ** record. Set freeZHdr to 1 if we need to sqliteFree(zHdr) later.
+ */
+ if( zRec ){
+ zHdr = zRec + dataOffsetLen;
+ }else{
+ zHdr = sqliteMalloc(dataOffset);
+ if( !zHdr ){
+ rc = SQLITE_NOMEM;
+ goto abort_due_to_error;
+ }
+ freeZHdr = 1;
+ if( pC->keyAsData ){
+ sqlite3BtreeKey(pCrsr, dataOffsetLen, dataOffset, zHdr);
+ }else{
+ sqlite3BtreeData(pCrsr, dataOffsetLen, dataOffset, zHdr);
+ }
+ }
+
+ /* Find the Nth byte of zHdr that does not have the 0x80
+ ** bit set. The byte after this one is the start of the Idx(N)
+ ** varint. Then read Idx(N) and Idx(N+1)
+ */
+ cnt = p2;
+ zIdx = zHdr;
+ while( cnt>0 ){
+ assert( (zIdx-zHdr)<dataOffset );
+ if( !(*zIdx & 0x80) ) cnt--;
+ zIdx++;
+ }
+ zIdx += sqlite3GetVarint(zIdx, &idxN);
+ sqlite3GetVarint(zIdx, &idxN1);
+
+ /* Set zHdr to point at the field data */
+ if( freeZHdr ){
+ sqliteFree(zHdr);
+ freeZHdr = 0;
+ }
+ if( zRec ){
+ zHdr = zRec + (dataOffsetLen + dataOffset + idxN);
+ }else{
+ cnt = idxN1 - idxN;
+ assert( cnt>0 );
+ zHdr = sqliteMalloc(cnt);
+ if( !zHdr ){
+ rc = SQLITE_NOMEM;
+ goto abort_due_to_error;
+ }
+ freeZHdr = 1;
+ if( pC->keyAsData ){
+ sqlite3BtreeKey(pCrsr, dataOffsetLen+dataOffset+idxN, cnt, zHdr);
+ }else{
+ sqlite3BtreeData(pCrsr, dataOffsetLen+dataOffset+idxN, cnt, zHdr);
+ }
+ }
+
+ /* Deserialize the field value directory into the top of the
+ ** stack. If the deserialized length does not match the expected
+ ** length, this indicates corruption.
+ */
+ if( (idxN1-idxN)!=sqlite3VdbeDeserialize(pTos, zHdr) ){
+ if( freeZHdr ){
+ sqliteFree(zHdr);
+ }
+ rc = SQLITE_CORRUPT;
+ goto abort_due_to_error;
+ }
+
+ if( freeZHdr ){
+ sqliteFree(zHdr);
+ }
+ break;
+}
+
+/* Opcode MakeRecord3 P1 * *
+**
+** This opcode (not yet in use) is a replacement for the current
+** OP_MakeRecord that supports the SQLite3 manifest typing feature.
+** It drops the (P2==1) option that was never use.
+**
+** Convert the top P1 entries of the stack into a single entry
+** suitable for use as a data record in a database table. The
+** details of the format are irrelavant as long as the OP_Column
+** opcode can decode the record later. Refer to source code
+** comments for the details of the record format.
+*/
+case OP_MakeRecord3: {
+ /* Assuming the record contains N fields, the record format looks
+ ** like this:
+ **
+ ** --------------------------------------------------------------------------
+ ** | data-offset | idx1 | ... | idx(N-1) | idx(N) | data0 | ... | data(N-1) |
+ ** --------------------------------------------------------------------------
+ **
+ ** Data(0) is taken from the lowest element of the stack and data(N-1) is
+ ** the top of the stack.
+ **
+ ** The data-offset and each of the idx() entries is stored as a 1-9
+ ** byte variable-length integer (see comments in btree.c). The
+ ** data-offset contains the offset from the end of itself to the start
+ ** of data(0).
+ **
+ ** Idx(k) contains the offset from the start of data(0) to the first
+ ** byte of data(k). Idx(0) is implicitly 0. Hence:
+ **
+ ** sizeof(data-offset) + data-offset + Idx(N)
+ **
+ ** is the number of bytes in the record. The offset to start of data(X)
+ ** is sizeof(data-offset) + data-offset + Idx(X
+ **
+ ** TODO: Even when the record is short enough for Mem::zShort, this opcode
+ ** allocates it dynamically.
+ */
+ int nDataLen = 0;
+ int nHdrLen = 0;
+ int data_offset = 0;
+ int nField = pOp->p1;
+ unsigned char *zNewRecord;
+ unsigned char *zHdr;
+ Mem *pRec;
+
+ Mem *pData0 = &pTos[1-nField];
+ assert( pData0>=p->aStack );
+
+ /* Loop through the elements that will make up the record, determining
+ ** the aggregate length of the Data() segments and the data_offset.
+ */
+ for(pRec=pData0; pRec!=pTos; pRec++){
+ nDataLen += sqlite3VdbeSerialLen(pRec);
+ data_offset += sqlite3VarintLen(nDataLen);
+ }
+
+ /* The size of the header is the data-offset + the size of the
+ ** data-offset as a varint. If the size of the header combined with
+ ** the size of the Data() segments is greater than MAX_BYTES_PER_ROW,
+ ** report an error.
+ */
+ nHdrLen = data_offset + sqlite3VarintLen(data_offset);
+ if( (nHdrLen+nDataLen)>MAX_BYTES_PER_ROW ){
+ rc = SQLITE_TOOBIG;
+ goto abort_due_to_error;
+ }
+
+ /* Allocate space for the new row. */
+ zNewRecord = sqliteMalloc(nHdrLen+nDataLen);
+ if( !zNewRecord ){
+ rc = SQLITE_NOMEM;
+ goto abort_due_to_error;
+ }
+
+ /* Write the data offset */
+ zHdr = zNewRecord;
+ zHdr += sqlite3PutVarint(zHdr, data_offset);
+
+ /* Loop through the values on the stack writing both the serialized value
+ ** and the the Idx() offset for each.
+ */
+ nDataLen = 0;
+ for(pRec=pData0; pRec!=pTos; pRec++){
+ nDataLen += sqlite3VdbeSerialize(pRec, &zNewRecord[nDataLen]);
+ zHdr += sqlite3PutVarint(zHdr, nDataLen);
+ }
+
+ /* Pop nField entries from the stack and push the new entry on */
+ popStack(&pTos, nField);
+ pTos++;
+ pTos->n = nDataLen+nHdrLen;
+ pTos->z = zNewRecord;
+ pTos->flags = MEM_Str | MEM_Dyn;
+
+ break;
+}
+
/* Opcode: MakeRecord P1 P2 *
**
** Convert the top P1 entries of the stack into a single entry