aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2002-07-05 21:42:36 +0000
committerdrh <drh@noemail.net>2002-07-05 21:42:36 +0000
commit38640e15af4c00270c20bdf980225e2a6f7423b5 (patch)
tree1b9058300f5925b8c907d679b9c9a23e4e6b5943 /src
parent2f2c01e51d09713efafb1e600e0136595acb77c4 (diff)
downloadsqlite-38640e15af4c00270c20bdf980225e2a6f7423b5.tar.gz
sqlite-38640e15af4c00270c20bdf980225e2a6f7423b5.zip
All the code is now in place for SQLite to distinguish between NUMERIC and
TEXT datatypes. Still need to turn on the new code and test it. (CVS 659) FossilOrigin-Name: b4737a16c997a6c139d616211fb6bc4b0fae181c
Diffstat (limited to 'src')
-rw-r--r--src/build.c44
-rw-r--r--src/delete.c9
-rw-r--r--src/insert.c5
-rw-r--r--src/parse.y6
-rw-r--r--src/select.c73
-rw-r--r--src/sqliteInt.h8
-rw-r--r--src/update.c4
-rw-r--r--src/util.c78
-rw-r--r--src/vdbe.c6
9 files changed, 170 insertions, 63 deletions
diff --git a/src/build.c b/src/build.c
index 47bdf12d9..9f1aa9cd2 100644
--- a/src/build.c
+++ b/src/build.c
@@ -25,7 +25,7 @@
** ROLLBACK
** PRAGMA
**
-** $Id: build.c,v 1.100 2002/06/28 12:18:47 drh Exp $
+** $Id: build.c,v 1.101 2002/07/05 21:42:36 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -463,6 +463,14 @@ void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
pCol->sortOrder = SQLITE_SO_NUM;
for(i=0; z[i]; i++){
switch( z[i] ){
+ case 'b':
+ case 'B': {
+ if( sqliteStrNICmp(&z[i],"blob",4)==0 ){
+ pCol->sortOrder = SQLITE_SO_TEXT;
+ return;
+ }
+ break;
+ }
case 'c':
case 'C': {
if( sqliteStrNICmp(&z[i],"char",4)==0 ||
@@ -1093,6 +1101,39 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){
}
/*
+** This routine constructs a P3 string suitable for an OP_MakeIdxKey
+** opcode and adds that P3 string to the most recently inserted instruction
+** in the virtual machine. The P3 string consists of a single character
+** for each column in the index pIdx of table pTab. If the column uses
+** a numeric sort order, then the P3 string character corresponding to
+** that column is 'n'. If the column uses a text sort order, then the
+** P3 string is 't'. See the OP_MakeIdxKey opcode documentation for
+** additional information. See also the sqliteAddKeyType() routine.
+*/
+void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){
+ char *zType;
+ Table *pTab;
+ int i, n;
+ assert( pIdx!=0 && pIdx->pTable!=0 );
+ pTab = pIdx->pTable;
+ n = pIdx->nColumn;
+ zType = sqliteMalloc( n+1 );
+ if( zType==0 ) return;
+ for(i=0; i<n; i++){
+ int iCol = pIdx->aiColumn[i];
+ assert( iCol>=0 && iCol<pTab->nCol );
+ if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
+ zType[i] = 't';
+ }else{
+ zType[i] = 'n';
+ }
+ }
+ zType[n] = 0;
+ sqliteVdbeChangeP3(v, -1, zType, n);
+ sqliteFree(zType);
+}
+
+/*
** Create a new index for an SQL table. pIndex is the name of the index
** and pTable is the name of the table that is to be indexed. Both will
** be NULL for a primary key or an index that is created to satisfy a
@@ -1355,6 +1396,7 @@ void sqliteCreateIndex(
sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i]);
}
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
+ if( db->file_format>=3 ) sqliteAddIdxKeyType(v, pIndex);
sqliteVdbeAddOp(v, OP_IdxPut, 1, pIndex->onError!=OE_None);
sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
sqliteVdbeResolveLabel(v, lbl2);
diff --git a/src/delete.c b/src/delete.c
index 1dfc7f244..8e91e25ee 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
-** $Id: delete.c,v 1.38 2002/06/19 14:27:05 drh Exp $
+** $Id: delete.c,v 1.39 2002/07/05 21:42:37 drh Exp $
*/
#include "sqliteInt.h"
@@ -261,7 +261,7 @@ void sqliteDeleteFrom(
}
/* Delete the row */
- sqliteGenerateRowDelete(v, pTab, base, pParse->trigStack==0);
+ sqliteGenerateRowDelete(db, v, pTab, base, pParse->trigStack==0);
/* If there are row triggers, close all cursors then invoke
** the AFTER triggers
@@ -329,6 +329,7 @@ delete_from_cleanup:
** entries that point to that record.
*/
void sqliteGenerateRowDelete(
+ sqlite *db, /* The database containing the index */
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int base, /* Cursor number for the table */
@@ -336,7 +337,7 @@ void sqliteGenerateRowDelete(
){
int addr;
addr = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
- sqliteGenerateRowIndexDelete(v, pTab, base, 0);
+ sqliteGenerateRowIndexDelete(db, v, pTab, base, 0);
sqliteVdbeAddOp(v, OP_Delete, base, count);
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
}
@@ -358,6 +359,7 @@ void sqliteGenerateRowDelete(
** deleted.
*/
void sqliteGenerateRowIndexDelete(
+ sqlite *db, /* The database containing the index */
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int base, /* Cursor number for the table */
@@ -379,6 +381,7 @@ void sqliteGenerateRowIndexDelete(
}
}
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
+ if( db->file_format>=3 ) sqliteAddIdxKeyType(v, pIdx);
sqliteVdbeAddOp(v, OP_IdxDelete, base+i, 0);
}
}
diff --git a/src/insert.c b/src/insert.c
index ee5b31f92..a6b2e858e 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.62 2002/06/19 20:32:44 drh Exp $
+** $Id: insert.c,v 1.63 2002/07/05 21:42:37 drh Exp $
*/
#include "sqliteInt.h"
@@ -616,6 +616,7 @@ void sqliteGenerateConstraintChecks(
}
}
jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
+ if( pParse->db->file_format>=3 ) sqliteAddIdxKeyType(v, pIdx);
onError = pIdx->onError;
if( onError==OE_None ) continue;
if( overrideError!=OE_Default ){
@@ -640,7 +641,7 @@ void sqliteGenerateConstraintChecks(
break;
}
case OE_Replace: {
- sqliteGenerateRowDelete(v, pTab, base, 0);
+ sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0);
if( isUpdate ){
sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
diff --git a/src/parse.y b/src/parse.y
index 0eadf3570..6a2e3dc86 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -14,7 +14,7 @@
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.76 2002/07/01 12:27:09 drh Exp $
+** @(#) $Id: parse.y,v 1.77 2002/07/05 21:42:37 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@@ -394,9 +394,9 @@ sortlist(A) ::= sortlist(X) COMMA sortitem(Y) collate(C) sortorder(Z). {
A = sqliteExprListAppend(X,Y,0);
if( A ) A->a[A->nExpr-1].sortOrder = C+Z;
}
-sortlist(A) ::= sortitem(Y) sortorder(Z). {
+sortlist(A) ::= sortitem(Y) collate(C) sortorder(Z). {
A = sqliteExprListAppend(0,Y,0);
- if( A ) A->a[0].sortOrder = Z;
+ if( A ) A->a[0].sortOrder = C+Z;
}
sortitem(A) ::= expr(X). {A = X;}
diff --git a/src/select.c b/src/select.c
index 92fa302a5..882e8885c 100644
--- a/src/select.c
+++ b/src/select.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.102 2002/06/29 02:20:08 drh Exp $
+** $Id: select.c,v 1.103 2002/07/05 21:42:37 drh Exp $
*/
#include "sqliteInt.h"
@@ -315,7 +315,24 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 );
if( zSortOrder==0 ) return;
for(i=0; i<pOrderBy->nExpr; i++){
- zSortOrder[i] = pOrderBy->a[i].sortOrder ? '-' : '+';
+ int order = pOrderBy->a[i].sortOrder;
+ int type;
+ int c;
+ if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
+ type = SQLITE_SO_TEXT;
+ }else if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_NUM ){
+ type = SQLITE_SO_NUM;
+ }else if( pParse->db->file_format>=3 ){
+ type = sqliteExprType(pOrderBy->a[i].pExpr);
+ }else{
+ type = SQLITE_SO_NUM;
+ }
+ if( (order & SQLITE_SO_DIRMASK)==SQLITE_SO_ASC ){
+ c = type==SQLITE_SO_TEXT ? 'A' : '+';
+ }else{
+ c = type==SQLITE_SO_TEXT ? 'D' : '-';
+ }
+ zSortOrder[i] = c;
sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
}
zSortOrder[pOrderBy->nExpr] = 0;
@@ -326,12 +343,36 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
}
/*
+** This routine adds a P3 argument to the last VDBE opcode that was
+** inserted. The P3 argument added is a string suitable for the
+** OP_MakeKey or OP_MakeIdxKey opcodes. The string consists of
+** characters 't' or 'n' depending on whether or not the various
+** fields of the key to be generated should be treated as numeric
+** or as text. See the OP_MakeKey and OP_MakeIdxKey opcode
+** documentation for additional information about the P3 string.
+** See also the sqliteAddIdxKeyType() routine.
+*/
+void sqliteAddKeyType(Vdbe *v, ExprList *pEList){
+ int nColumn = pEList->nExpr;
+ char *zType = sqliteMalloc( nColumn+1 );
+ int i;
+ if( zType==0 ) return;
+ for(i=0; i<nColumn; i++){
+ zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';
+ }
+ zType[i] = 0;
+ sqliteVdbeChangeP3(v, -1, zType, nColumn);
+ sqliteFree(zType);
+}
+
+/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
-** The pEList is used to determine the values for each column in the
-** result row. Except if pEList==NULL, then we just read nColumn
-** elements from the srcTab table.
+** If srcTab and nColumn are both zero, then the pEList expressions
+** are evaluated in order to get the data for this row. If nColumn>0
+** then data is pulled from srcTab and pEList is used only to get the
+** datatypes for each column.
*/
static int selectInnerLoop(
Parse *pParse, /* The parser context */
@@ -348,7 +389,9 @@ static int selectInnerLoop(
){
Vdbe *v = pParse->pVdbe;
int i;
+
if( v==0 ) return 0;
+ assert( pEList!=0 );
/* If there was a LIMIT clause on the SELECT statement, then do the check
** to see if this row should be output.
@@ -366,15 +409,15 @@ static int selectInnerLoop(
/* Pull the requested columns.
*/
- if( pEList ){
- for(i=0; i<pEList->nExpr; i++){
- sqliteExprCode(pParse, pEList->a[i].pExpr);
- }
- nColumn = pEList->nExpr;
- }else{
+ if( nColumn>0 ){
for(i=0; i<nColumn; i++){
sqliteVdbeAddOp(v, OP_Column, srcTab, i);
}
+ }else{
+ nColumn = pEList->nExpr;
+ for(i=0; i<pEList->nExpr; i++){
+ sqliteExprCode(pParse, pEList->a[i].pExpr);
+ }
}
/* If the DISTINCT keyword was present on the SELECT statement
@@ -386,6 +429,7 @@ static int selectInnerLoop(
sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
#endif
sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);
+ if( pParse->db->file_format>=3 ) sqliteAddKeyType(v, pEList);
sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3);
sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
@@ -1119,7 +1163,7 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
iCont = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak);
iStart = sqliteVdbeCurrentAddr(v);
- rc = selectInnerLoop(pParse, p, 0, unionTab, p->pEList->nExpr,
+ rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm,
iCont, iBreak);
if( rc ) return 1;
@@ -1175,7 +1219,7 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak);
iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0);
sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont);
- rc = selectInnerLoop(pParse, p, 0, tab1, p->pEList->nExpr,
+ rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
p->pOrderBy, -1, eDest, iParm,
iCont, iBreak);
if( rc ) return 1;
@@ -1547,7 +1591,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
eList.a = &eListItem;
eList.a[0].pExpr = pExpr;
cont = sqliteVdbeMakeLabel(v);
- selectInnerLoop(pParse, p, &eList, base, 1, 0, -1, eDest, iParm, cont, cont);
+ selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);
sqliteVdbeResolveLabel(v, cont);
sqliteVdbeAddOp(v, OP_Close, base, 0);
return 1;
@@ -1914,6 +1958,7 @@ int sqliteSelect(
sqliteExprCode(pParse, pGroupBy->a[i].pExpr);
}
sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0);
+ if( pParse->db->file_format>=3 ) sqliteAddKeyType(v, pGroupBy);
lbl1 = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1);
for(i=0; i<pParse->nAgg; i++){
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 5f842e0c0..7b7e14232 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.133 2002/06/29 02:20:09 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.134 2002/07/05 21:42:37 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
@@ -871,6 +871,8 @@ void sqliteIdListDelete(IdList*);
void sqliteSrcListDelete(SrcList*);
void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*);
void sqliteDropIndex(Parse*, Token*);
+void sqliteAddKeyType(Vdbe*, ExprList*);
+void sqliteAddIdxKeyType(Vdbe*, Index*);
int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*);
Select *sqliteSelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
int,int,int);
@@ -909,8 +911,8 @@ char *sqlite_mprintf(const char *, ...);
int sqliteExprIsConstant(Expr*);
int sqliteExprIsInteger(Expr*, int*);
int sqliteIsRowid(const char*);
-void sqliteGenerateRowDelete(Vdbe*, Table*, int, int);
-void sqliteGenerateRowIndexDelete(Vdbe*, Table*, int, char*);
+void sqliteGenerateRowDelete(sqlite*, Vdbe*, Table*, int, int);
+void sqliteGenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*);
void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int);
void sqliteBeginWriteOperation(Parse*, int);
diff --git a/src/update.c b/src/update.c
index 0a6f6db20..656b8edfd 100644
--- a/src/update.c
+++ b/src/update.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.46 2002/06/29 02:20:09 drh Exp $
+** $Id: update.c,v 1.47 2002/07/05 21:42:37 drh Exp $
*/
#include "sqliteInt.h"
@@ -319,7 +319,7 @@ void sqliteUpdate(
/* Delete the old indices for the current record.
*/
- sqliteGenerateRowIndexDelete(v, pTab, base, aIdxUsed);
+ sqliteGenerateRowIndexDelete(db, v, pTab, base, aIdxUsed);
/* If changing the record number, delete the old record.
*/
diff --git a/src/util.c b/src/util.c
index 007dd5aa1..21736e9ea 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.46 2002/06/14 20:58:45 drh Exp $
+** $Id: util.c,v 1.47 2002/07/05 21:42:37 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@@ -705,11 +705,15 @@ int sqliteCompare(const char *atext, const char *btext){
** returns negative, zero, or positive if the first argument is less
** than, equal to, or greater than the first. (Result is a-b).
**
-** Every string begins with either a "+" or "-" character. If the
-** character is "-" then the return value is negated. This is done
-** to implement a sort in descending order.
+** Each string begins with one of the characters "+", "-", "A", "D".
+** This character determines the sort order and collating sequence:
**
-** For sorting purposes, pur numeric strings (strings for which the
+** + Sort numerically in ascending order
+** - Sort numerically in descending order
+** A Sort as strings in ascending order
+** D Sort as strings in descending order.
+**
+** For the "+" and "-" sorting, pure numeric strings (strings for which the
** isNum() function above returns TRUE) always compare less than strings
** that are not pure numerics. Within non-numeric strings, substrings
** of digits compare in numerical order. Finally, case is used only
@@ -721,6 +725,10 @@ int sqliteCompare(const char *atext, const char *btext){
** lexigraphical order. This routine does the additional processing
** to sort substrings of digits into numerical order and to use case
** only as a tie-breaker.
+**
+** The special rules above apply only to numeric sorting, when the
+** prefix is "+" or "-". If the prefix is "A" or "D" then plain old
+** "strcmp()" is used for the comparison.
*/
int sqliteSortCompare(const char *a, const char *b){
int len;
@@ -728,6 +736,7 @@ int sqliteSortCompare(const char *a, const char *b){
int isNumA, isNumB;
while( res==0 && *a && *b ){
+ assert( a[0]==b[0] );
if( a[1]==0 ){
res = -1;
break;
@@ -735,41 +744,46 @@ int sqliteSortCompare(const char *a, const char *b){
res = +1;
break;
}
- isNumA = sqliteIsNumber(&a[1]);
- isNumB = sqliteIsNumber(&b[1]);
- if( isNumA ){
- double rA, rB;
- if( !isNumB ){
- res = -1;
- break;
- }
- rA = atof(&a[1]);
- rB = atof(&b[1]);
- if( rA<rB ){
- res = -1;
- break;
- }
- if( rA>rB ){
- res = +1;
- break;
- }
- }else if( isNumB ){
- res = +1;
- break;
+ if( a[0]=='A' || a[0]=='D' ){
+ res = strcmp(&a[1],&b[1]);
+ if( res ) break;
}else{
- res = sortStrCmp(&a[1],&b[1],0);
- if( res==0 ){
- res = sortStrCmp(&a[1],&b[1],1);
- }
- if( res!=0 ){
+ isNumA = sqliteIsNumber(&a[1]);
+ isNumB = sqliteIsNumber(&b[1]);
+ if( isNumA ){
+ double rA, rB;
+ if( !isNumB ){
+ res = -1;
+ break;
+ }
+ rA = atof(&a[1]);
+ rB = atof(&b[1]);
+ if( rA<rB ){
+ res = -1;
+ break;
+ }
+ if( rA>rB ){
+ res = +1;
+ break;
+ }
+ }else if( isNumB ){
+ res = +1;
break;
+ }else{
+ res = sortStrCmp(&a[1],&b[1],0);
+ if( res==0 ){
+ res = sortStrCmp(&a[1],&b[1],1);
+ }
+ if( res!=0 ){
+ break;
+ }
}
}
len = strlen(&a[1]) + 2;
a += len;
b += len;
}
- if( *a=='-' ) res = -res;
+ if( *a=='-' || *a=='D' ) res = -res;
return res;
}
diff --git a/src/vdbe.c b/src/vdbe.c
index 83b36d90c..3700a4baa 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -30,7 +30,7 @@
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
-** $Id: vdbe.c,v 1.163 2002/06/29 02:20:09 drh Exp $
+** $Id: vdbe.c,v 1.164 2002/07/05 21:42:37 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -2632,7 +2632,7 @@ case OP_MakeRecord: {
** P3 is a string that is P1 characters long. Each character is either
** an 'n' or a 't' to indicates if the argument should be numeric or
** text. The first character corresponds to the lowest element on the
-** stack.
+** stack. If P3 is NULL then all arguments are assumed to be numeric.
**
** See also: MakeIdxKey, SortMakeKey
*/
@@ -2661,7 +2661,7 @@ case OP_MakeRecord: {
** P3 is a string that is P1 characters long. Each character is either
** an 'n' or a 't' to indicates if the argument should be numeric or
** text. The first character corresponds to the lowest element on the
-** stack.
+** stack. If P3 is null then all arguments are assumed to be numeric.
**
** See also: MakeKey, SortMakeKey
*/