Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | This patch contains the beginnings of the data-typing infrastructure. The new build-in TypeOf() function is added. New opcodes for doing pure text comparisons are added. Most changes are disabled pending the 2.6.0 release. (CVS 632) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
cbbc858d973c2d515c6a246498131654 |
User & Date: | drh 2002-06-20 11:36:49.000 |
Context
2002-06-20
| ||
11:41 | Update the file-format change document to describes the changes between versions 2.4.12 and 2.5.0. (CVS 633) (check-in: d28a2ecc91 user: drh tags: trunk) | |
11:36 | This patch contains the beginnings of the data-typing infrastructure. The new build-in TypeOf() function is added. New opcodes for doing pure text comparisons are added. Most changes are disabled pending the 2.6.0 release. (CVS 632) (check-in: cbbc858d97 user: drh tags: trunk) | |
03:38 | Fix for ticket #73: The ORDER BY clause is significant for subqueries. This passes all regression tests, but more testing is needed to exercise all paths through the new code. (CVS 631) (check-in: 43c5aff5d0 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.97 2002/06/20 11:36:49 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called after a single SQL statement has been ** parsed and we want to execute the VDBE code to implement |
︙ | ︙ | |||
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 | ** first to get things going. Then this routine is called for each ** column. */ void sqliteAddColumn(Parse *pParse, Token *pName){ Table *p; int i; char *z = 0; if( (p = pParse->pNewTable)==0 ) return; sqliteSetNString(&z, pName->z, pName->n, 0); if( z==0 ) return; sqliteDequote(z); for(i=0; i<p->nCol; i++){ if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){ sqliteSetString(&pParse->zErrMsg, "duplicate column name: ", z, 0); pParse->nErr++; sqliteFree(z); return; } } if( (p->nCol & 0x7)==0 ){ Column *aNew; aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); if( aNew==0 ) return; p->aCol = aNew; } | > > | > > | | 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 | ** first to get things going. Then this routine is called for each ** column. */ void sqliteAddColumn(Parse *pParse, Token *pName){ Table *p; int i; char *z = 0; Column *pCol; if( (p = pParse->pNewTable)==0 ) return; sqliteSetNString(&z, pName->z, pName->n, 0); if( z==0 ) return; sqliteDequote(z); for(i=0; i<p->nCol; i++){ if( sqliteStrICmp(z, p->aCol[i].zName)==0 ){ sqliteSetString(&pParse->zErrMsg, "duplicate column name: ", z, 0); pParse->nErr++; sqliteFree(z); return; } } if( (p->nCol & 0x7)==0 ){ Column *aNew; aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); if( aNew==0 ) return; p->aCol = aNew; } pCol = &p->aCol[p->nCol]; memset(pCol, 0, sizeof(p->aCol[0])); pCol->zName = z; pCol->sortOrder = SQLITE_SO_NUM; p->nCol++; } /* ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has ** been seen on a column. This routine sets the notNull flag on ** the column currently under construction. |
︙ | ︙ | |||
550 551 552 553 554 555 556 557 558 559 | ** in zType. */ void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ Table *p; int i, j; int n; char *z, **pz; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( i<0 ) return; | > | > > > > > > > > > > > > > > > > > > > > > > > > > > | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | ** in zType. */ void sqliteAddColumnType(Parse *pParse, Token *pFirst, Token *pLast){ Table *p; int i, j; int n; char *z, **pz; Column *pCol; if( (p = pParse->pNewTable)==0 ) return; i = p->nCol-1; if( i<0 ) return; pCol = &p->aCol[i]; pz = &pCol->zType; n = pLast->n + Addr(pLast->z) - Addr(pFirst->z); sqliteSetNString(pz, pFirst->z, n, 0); z = *pz; if( z==0 ) return; for(i=j=0; z[i]; i++){ int c = z[i]; if( isspace(c) ) continue; z[j++] = c; } z[j] = 0; pCol->sortOrder = SQLITE_SO_NUM; for(i=0; z[i]; i++){ switch( z[i] ){ case 'c': case 'C': { if( sqliteStrNICmp(&z[i],"char",4)==0 || sqliteStrNICmp(&z[i],"clob",4)==0 ){ pCol->sortOrder = SQLITE_SO_TEXT; return; } break; } case 'x': case 'X': { if( i>=2 && sqliteStrNICmp(&z[i-2],"text",4)==0 ){ pCol->sortOrder = SQLITE_SO_TEXT; return; } break; } default: { break; } } } } /* ** The given token is the default value for the last column added to ** the table currently under construction. If "minusFlag" is true, it ** means the value token was preceded by a minus sign. ** |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.73 2002/06/20 11:36:49 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Construct a new expression node and return a pointer to it. Memory ** for this node is obtained from sqliteMalloc(). The calling function |
︙ | ︙ | |||
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 | for(j=0; j<pTab->nCol; j++){ if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){ cnt++; pExpr->iTable = i + base; if( j==pTab->iPKey ){ /* Substitute the record number for the INTEGER PRIMARY KEY */ pExpr->iColumn = -1; }else{ pExpr->iColumn = j; } pExpr->op = TK_COLUMN; } } } if( cnt==0 && pEList!=0 ){ int j; | > > | 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | for(j=0; j<pTab->nCol; j++){ if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){ cnt++; pExpr->iTable = i + base; if( j==pTab->iPKey ){ /* Substitute the record number for the INTEGER PRIMARY KEY */ pExpr->iColumn = -1; pExpr->dataType = SQLITE_SO_NUM; }else{ pExpr->iColumn = j; pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK; } pExpr->op = TK_COLUMN; } } } if( cnt==0 && pEList!=0 ){ int j; |
︙ | ︙ | |||
481 482 483 484 485 486 487 488 489 490 491 492 493 494 | } } if( cnt==0 && sqliteIsRowid(z) ){ pExpr->iColumn = -1; pExpr->iTable = base; cnt = 1 + (pTabList->nSrc>1); pExpr->op = TK_COLUMN; } sqliteFree(z); if( cnt==0 && pExpr->token.z[0]!='"' ){ sqliteSetNString(&pParse->zErrMsg, "no such column: ", -1, pExpr->token.z, pExpr->token.n, 0); pParse->nErr++; return 1; | > | 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 | } } if( cnt==0 && sqliteIsRowid(z) ){ pExpr->iColumn = -1; pExpr->iTable = base; cnt = 1 + (pTabList->nSrc>1); pExpr->op = TK_COLUMN; pExpr->dataType = SQLITE_SO_NUM; } sqliteFree(z); if( cnt==0 && pExpr->token.z[0]!='"' ){ sqliteSetNString(&pParse->zErrMsg, "no such column: ", -1, pExpr->token.z, pExpr->token.n, 0); pParse->nErr++; return 1; |
︙ | ︙ | |||
542 543 544 545 546 547 548 549 550 551 552 553 554 555 | pExpr->iTable = i + base; if( j==pTab->iPKey ){ /* Substitute the record number for the INTEGER PRIMARY KEY */ pExpr->iColumn = -1; }else{ pExpr->iColumn = j; } } } } /* If we have not already resolved this *.* expression, then maybe * it is a new.* or old.* trigger argument reference */ if( cnt == 0 && pParse->trigStack != 0 ){ | > | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 | pExpr->iTable = i + base; if( j==pTab->iPKey ){ /* Substitute the record number for the INTEGER PRIMARY KEY */ pExpr->iColumn = -1; }else{ pExpr->iColumn = j; } pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK; } } } /* If we have not already resolved this *.* expression, then maybe * it is a new.* or old.* trigger argument reference */ if( cnt == 0 && pParse->trigStack != 0 ){ |
︙ | ︙ | |||
564 565 566 567 568 569 570 | pExpr->iTable = pTriggerStack->oldIdx; cntTab++; t = 1; } if( t ){ int j; | | > | > > | 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | pExpr->iTable = pTriggerStack->oldIdx; cntTab++; t = 1; } if( t ){ int j; Table *pTab = pTriggerStack->pTab; for(j=0; j < pTab->nCol; j++) { if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){ cnt++; pExpr->iColumn = j; pExpr->dataType = pTab->aCol[j].sortOrder & SQLITE_SO_TYPEMASK; } } } } if( cnt==0 && cntTab==1 && sqliteIsRowid(zRight) ){ cnt = 1; pExpr->iColumn = -1; pExpr->dataType = SQLITE_SO_NUM; } sqliteFree(zLeft); sqliteFree(zRight); if( cnt==0 ){ sqliteSetNString(&pParse->zErrMsg, "no such column: ", -1, pLeft->token.z, pLeft->token.n, ".", 1, pRight->token.z, pRight->token.n, 0); |
︙ | ︙ | |||
710 711 712 713 714 715 716 | ** (like count(*) or max(value)) then write a 1 into *pIsAgg. */ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){ int nErr = 0; if( pExpr==0 ) return 0; switch( pExpr->op ){ case TK_FUNCTION: { | | | > | | > > > > | > | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | ** (like count(*) or max(value)) then write a 1 into *pIsAgg. */ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){ int nErr = 0; if( pExpr==0 ) return 0; switch( pExpr->op ){ case TK_FUNCTION: { int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */ int no_such_func = 0; /* True if no such function exists */ int is_type_of = 0; /* True if is the special TypeOf() function */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ int i; FuncDef *pDef; pDef = sqliteFindFunction(pParse->db, pExpr->token.z, pExpr->token.n, n, 0); if( pDef==0 ){ pDef = sqliteFindFunction(pParse->db, pExpr->token.z, pExpr->token.n, -1, 0); if( pDef==0 ){ if( n==1 && pExpr->token.n==6 && sqliteStrNICmp(pExpr->token.z, "typeof", 6)==0 ){ is_type_of = 1; }else { no_such_func = 1; } }else{ wrong_num_args = 1; } }else{ is_agg = pDef->xFunc==0; } if( is_agg && !allowAgg ){ |
︙ | ︙ | |||
754 755 756 757 758 759 760 761 762 763 764 765 766 767 | } if( is_agg ) pExpr->op = TK_AGG_FUNCTION; if( is_agg && pIsAgg ) *pIsAgg = 1; for(i=0; nErr==0 && i<n; i++){ nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr, allowAgg && !is_agg, pIsAgg); } } default: { if( pExpr->pLeft ){ nErr = sqliteExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg); } if( nErr==0 && pExpr->pRight ){ nErr = sqliteExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 | } if( is_agg ) pExpr->op = TK_AGG_FUNCTION; if( is_agg && pIsAgg ) *pIsAgg = 1; for(i=0; nErr==0 && i<n; i++){ nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr, allowAgg && !is_agg, pIsAgg); } if( pDef==0 ){ if( is_type_of ){ pExpr->op = TK_STRING; if( sqliteExprType(pExpr->pList->a[0].pExpr)==SQLITE_SO_NUM ){ pExpr->token.z = "numeric"; pExpr->token.n = 7; }else{ pExpr->token.z = "text"; pExpr->token.n = 4; } } }else if( pDef->dataType>=0 ){ if( pDef->dataType<n ){ pExpr->dataType = sqliteExprType(pExpr->pList->a[pDef->dataType].pExpr); }else{ pExpr->dataType = SQLITE_SO_NUM; } }else if( pDef->dataType==SQLITE_ARGS ){ pDef->dataType = SQLITE_SO_TEXT; for(i=0; i<n; i++){ if( sqliteExprType(pExpr->pList->a[i].pExpr)==SQLITE_SO_NUM ){ pExpr->dataType = SQLITE_SO_NUM; break; } } }else if( pDef->dataType==SQLITE_NUMERIC ){ pExpr->dataType = SQLITE_SO_NUM; }else{ pExpr->dataType = SQLITE_SO_TEXT; } } default: { if( pExpr->pLeft ){ nErr = sqliteExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg); } if( nErr==0 && pExpr->pRight ){ nErr = sqliteExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg); |
︙ | ︙ | |||
775 776 777 778 779 780 781 782 783 784 785 786 787 788 | } } break; } } return nErr; } /* ** Generate code into the current Vdbe to evaluate the given ** expression and leave the result on the top of stack. */ void sqliteExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 | } } break; } } return nErr; } /* ** Return either SQLITE_SO_NUM or SQLITE_SO_TEXT to indicate whether the ** given expression should sort as numeric values or as text. ** ** The sqliteExprResolveIds() and sqliteExprCheck() routines must have ** both been called on the expression before it is passed to this routine. */ int sqliteExprType(Expr *p){ if( p==0 ) return SQLITE_SO_NUM; while( p ) switch( p->op ){ case TK_PLUS: case TK_MINUS: case TK_STAR: case TK_SLASH: case TK_AND: case TK_OR: case TK_ISNULL: case TK_NOTNULL: case TK_NOT: case TK_UMINUS: case TK_BITAND: case TK_BITOR: case TK_BITNOT: case TK_LSHIFT: case TK_RSHIFT: case TK_REM: case TK_INTEGER: case TK_FLOAT: case TK_IN: case TK_BETWEEN: return SQLITE_SO_NUM; case TK_STRING: case TK_NULL: case TK_CONCAT: return SQLITE_SO_TEXT; case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: if( sqliteExprType(p->pLeft)==SQLITE_SO_NUM ){ return SQLITE_SO_NUM; } p = p->pRight; break; case TK_AS: p = p->pLeft; break; case TK_COLUMN: case TK_FUNCTION: case TK_AGG_FUNCTION: return p->dataType; case TK_SELECT: assert( p->pSelect ); assert( p->pSelect->pEList ); assert( p->pSelect->pEList->nExpr>0 ); p = p->pSelect->pEList->a[0].pExpr; break; default: assert( p->op==TK_ABORT ); /* Can't Happen */ break; } return SQLITE_SO_NUM; } /* ** Generate code into the current Vdbe to evaluate the given ** expression and leave the result on the top of stack. */ void sqliteExprCode(Parse *pParse, Expr *pExpr){ Vdbe *v = pParse->pVdbe; |
︙ | ︙ | |||
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 | sqliteVdbeDequoteP3(v, addr); break; } case TK_NULL: { sqliteVdbeAddOp(v, OP_String, 0, 0); break; } case TK_AND: case TK_OR: case TK_PLUS: case TK_STAR: case TK_MINUS: case TK_REM: case TK_BITAND: case TK_BITOR: | > > > > > > > > > > > | < < < < < < | 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 | sqliteVdbeDequoteP3(v, addr); break; } case TK_NULL: { sqliteVdbeAddOp(v, OP_String, 0, 0); break; } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { if( pParse->db->file_format>=3 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ op += 6; /* Convert numeric opcodes to text opcodes */ } /* Fall through into the next case */ } case TK_AND: case TK_OR: case TK_PLUS: case TK_STAR: case TK_MINUS: case TK_REM: case TK_BITAND: case TK_BITOR: case TK_SLASH: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, 0, 0); break; } case TK_LSHIFT: case TK_RSHIFT: { |
︙ | ︙ | |||
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 | case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 1, dest); | > > > | 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 | case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); if( pParse->db->file_format>=3 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ op += 6; /* Convert numeric opcodes to text opcodes */ } sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { sqliteExprCode(pParse, pExpr->pLeft); sqliteVdbeAddOp(v, op, 1, dest); |
︙ | ︙ | |||
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 | } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { | > > > | 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 | } case TK_LT: case TK_LE: case TK_GT: case TK_GE: case TK_NE: case TK_EQ: { if( pParse->db->file_format>=3 && sqliteExprType(pExpr)==SQLITE_SO_TEXT ){ op += 6; /* Convert numeric opcodes to text opcodes */ } sqliteExprCode(pParse, pExpr->pLeft); sqliteExprCode(pParse, pExpr->pRight); sqliteVdbeAddOp(v, op, jumpIfNull, dest); break; } case TK_ISNULL: case TK_NOTNULL: { |
︙ | ︙ | |||
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 | if( p==0 && pMaybe ){ assert( createFlag==0 ); return pMaybe; } if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){ p->nArg = nArg; p->pNext = pFirst; sqliteHashInsert(&db->aFunc, zName, nName, (void*)p); } return p; } | > | 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | if( p==0 && pMaybe ){ assert( createFlag==0 ); return pMaybe; } if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){ p->nArg = nArg; p->pNext = pFirst; p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC; sqliteHashInsert(&db->aFunc, zName, nName, (void*)p); } return p; } |
Changes to src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.21 2002/06/20 11:36:49 drh Exp $ */ #include <ctype.h> #include <math.h> #include <stdlib.h> #include <assert.h> #include "sqliteInt.h" |
︙ | ︙ | |||
412 413 414 415 416 417 418 419 420 | ** functions. This should be the only routine in this file with ** external linkage. */ void sqliteRegisterBuiltinFunctions(sqlite *db){ static struct { char *zName; int nArg; void (*xFunc)(sqlite_func*,int,const char**); } aFuncs[] = { | > | | | | | | | | | | | | | | | | | | | > | | | | | | | > > > > > | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | ** functions. This should be the only routine in this file with ** external linkage. */ void sqliteRegisterBuiltinFunctions(sqlite *db){ static struct { char *zName; int nArg; int dataType; void (*xFunc)(sqlite_func*,int,const char**); } aFuncs[] = { { "min", -1, SQLITE_ARGS, minFunc }, { "min", 0, 0, 0 }, { "max", -1, SQLITE_ARGS, maxFunc }, { "max", 0, 0, 0 }, { "length", 1, SQLITE_NUMERIC, lengthFunc }, { "substr", 3, SQLITE_TEXT, substrFunc }, { "abs", 1, SQLITE_NUMERIC, absFunc }, { "round", 1, SQLITE_NUMERIC, roundFunc }, { "round", 2, SQLITE_NUMERIC, roundFunc }, { "upper", 1, SQLITE_TEXT, upperFunc }, { "lower", 1, SQLITE_TEXT, lowerFunc }, { "coalesce", -1, SQLITE_ARGS, ifnullFunc }, { "coalesce", 0, 0, 0 }, { "coalesce", 1, 0, 0 }, { "ifnull", 2, SQLITE_ARGS, ifnullFunc }, { "random", -1, SQLITE_NUMERIC, randomFunc }, { "like", 2, SQLITE_NUMERIC, likeFunc }, { "glob", 2, SQLITE_NUMERIC, globFunc }, { "nullif", 2, SQLITE_ARGS, nullifFunc }, }; static struct { char *zName; int nArg; int dataType; void (*xStep)(sqlite_func*,int,const char**); void (*xFinalize)(sqlite_func*); } aAggs[] = { { "min", 1, 0, minStep, minMaxFinalize }, { "max", 1, 0, maxStep, minMaxFinalize }, { "sum", 1, SQLITE_NUMERIC, sumStep, sumFinalize }, { "avg", 1, SQLITE_NUMERIC, sumStep, avgFinalize }, { "count", 0, SQLITE_NUMERIC, countStep, countFinalize }, { "count", 1, SQLITE_NUMERIC, countStep, countFinalize }, #if 0 { "stddev", 1, SQLITE_NUMERIC, stdDevStep, stdDevFinalize }, #endif }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].xFunc, 0); if( aFuncs[i].xFunc ){ sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType); } } sqlite_create_function(db, "last_insert_rowid", 0, last_insert_rowid, db); sqlite_function_type(db, "last_insert_rowid", SQLITE_NUMERIC); for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ sqlite_create_aggregate(db, aAggs[i].zName, aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, 0); sqlite_function_type(db, aAggs[i].zName, aAggs[i].dataType); } } |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.81 2002/06/20 11:36:49 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** This is the callback routine for the code that initializes the |
︙ | ︙ | |||
47 48 49 50 51 52 53 54 55 56 57 58 59 60 | int size = atoi(argv[3]); if( size==0 ){ size = MAX_PAGES; } db->cache_size = size; sqliteBtreeSetCacheSize(db->pBe, size); break; } case 'f': { /* File format */ db->file_format = atoi(argv[3]); break; } case 's': { /* Schema cookie */ db->schema_cookie = atoi(argv[3]); db->next_cookie = db->schema_cookie; break; | > > > > > | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | int size = atoi(argv[3]); if( size==0 ){ size = MAX_PAGES; } db->cache_size = size; sqliteBtreeSetCacheSize(db->pBe, size); break; } case 'f': { /* File format */ /* ** file_format==1 Version 2.1.0. ** file_format==2 Version 2.2.0. Integer primary key. ** file_format==3 Version 2.6.0. Separate text and numeric datatypes. */ db->file_format = atoi(argv[3]); break; } case 's': { /* Schema cookie */ db->schema_cookie = atoi(argv[3]); db->next_cookie = db->schema_cookie; break; |
︙ | ︙ | |||
823 824 825 826 827 828 829 | if( p==0 ) return 1; p->xFunc = 0; p->xStep = xStep; p->xFinalize = xFinalize; p->pUserData = pUserData; return 0; } | > > > > > > > > > > > | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 | if( p==0 ) return 1; p->xFunc = 0; p->xStep = xStep; p->xFinalize = xFinalize; p->pUserData = pUserData; return 0; } /* ** Change the datatype for all functions with a given name. */ int sqlite_function_type(sqlite *db, const char *zName, int dataType){ FuncDef *p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, strlen(zName)); while( p ){ p->dataType = dataType; p = p->pNext; } } |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite.h.in,v 1.32 2002/06/20 11:36:50 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** The version of the SQLite library. |
︙ | ︙ | |||
422 423 424 425 426 427 428 429 430 431 432 433 434 435 | const char *zName, /* Name of the function */ int nArg, /* Number of arguments */ void (*xStep)(sqlite_func*,int,const char**), /* Called for each row */ void (*xFinalize)(sqlite_func*), /* Called once to get final result */ void *pUserData /* Available via the sqlite_user_data() call */ ); /* ** The user function implementations call one of the following four routines ** in order to return their results. The first parameter to each of these ** routines is a copy of the first argument to xFunc() or xFinialize(). ** The second parameter to these routines is the result to be returned. ** A NULL can be passed as the second parameter to sqlite_set_result_string() ** in order to return a NULL result. | > > > > > > > > > > > > > > > > > > > > > | 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | const char *zName, /* Name of the function */ int nArg, /* Number of arguments */ void (*xStep)(sqlite_func*,int,const char**), /* Called for each row */ void (*xFinalize)(sqlite_func*), /* Called once to get final result */ void *pUserData /* Available via the sqlite_user_data() call */ ); /* ** Use the following routine to define the datatype returned by a ** user-defined function. The second argument can be one of the ** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it ** can be an integer greater than or equal to zero. The datatype ** will be numeric or text (the only two types supported) if the ** argument is SQLITE_NUMERIC or SQLITE_TEXT. If the argument is ** SQLITE_ARGS, then the datatype is numeric if any argument to the ** function is numeric and is text otherwise. If the second argument ** is an integer, then the datatype of the result is the same as the ** parameter to the function that corresponds to that integer. */ int sqlite_function_type( sqlite *db, /* The database there the function is registered */ const char *zName, /* Name of the function */ int datatype /* The datatype for this function */ ); #define SQLITE_NUMERIC (-1) #define SQLITE_TEXT (-2) #define SQLITE_ARGS (-3) /* ** The user function implementations call one of the following four routines ** in order to return their results. The first parameter to each of these ** routines is a copy of the first argument to xFunc() or xFinialize(). ** The second parameter to these routines is the result to be returned. ** A NULL can be passed as the second parameter to sqlite_set_result_string() ** in order to return a NULL result. |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.127 2002/06/20 11:36:50 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
172 173 174 175 176 177 178 | typedef struct AggExpr AggExpr; typedef struct FuncDef FuncDef; typedef struct Trigger Trigger; typedef struct TriggerStep TriggerStep; typedef struct TriggerStack TriggerStack; /* | | > > > > > > > > > > > | 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | typedef struct AggExpr AggExpr; typedef struct FuncDef FuncDef; typedef struct Trigger Trigger; typedef struct TriggerStep TriggerStep; typedef struct TriggerStack TriggerStack; /* ** Each database is an instance of the following structure. ** ** The sqlite.file_format is initialized by the database file ** and helps determines how the data in the database file is ** represented. This field allows newer versions of the library ** to read and write older databases. The various file formats ** are as follows: ** ** file_format==1 Version 2.1.0. ** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. ** file_format==3 Version 2.6.0. Add support for separate numeric and ** text datatypes. */ struct sqlite { Btree *pBe; /* The B*Tree backend */ Btree *pBeTemp; /* Backend for session temporary tables */ int flags; /* Miscellanous flags. See below */ int file_format; /* What file format version is this database? */ int schema_cookie; /* Magic number that changes with the schema */ |
︙ | ︙ | |||
240 241 242 243 244 245 246 247 248 249 250 251 252 253 | ** points to a linked list of these structures. */ struct FuncDef { void (*xFunc)(sqlite_func*,int,const char**); /* Regular function */ void (*xStep)(sqlite_func*,int,const char**); /* Aggregate function step */ void (*xFinalize)(sqlite_func*); /* Aggregate function finializer */ int nArg; /* Number of arguments */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ }; /* ** information about each column of an SQL table is held in an instance ** of this structure. | > | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | ** points to a linked list of these structures. */ struct FuncDef { void (*xFunc)(sqlite_func*,int,const char**); /* Regular function */ void (*xStep)(sqlite_func*,int,const char**); /* Aggregate function step */ void (*xFinalize)(sqlite_func*); /* Aggregate function finializer */ int nArg; /* Number of arguments */ int dataType; /* Datatype of the result */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ }; /* ** information about each column of an SQL table is held in an instance ** of this structure. |
︙ | ︙ | |||
872 873 874 875 876 877 878 879 880 881 882 883 884 885 | void sqliteUnlinkAndDeleteIndex(sqlite*,Index*); void sqliteCopy(Parse*, Token*, Token*, Token*, int); void sqliteVacuum(Parse*, Token*); int sqliteGlobCompare(const unsigned char*,const unsigned char*); int sqliteLikeCompare(const unsigned char*,const unsigned char*); char *sqliteTableNameFromToken(Token*); int sqliteExprCheck(Parse*, Expr*, int, int*); int sqliteExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqliteExprResolveIds(Parse*, int, SrcList*, ExprList*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(void); int sqliteRandomInteger(void); | > | 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 | void sqliteUnlinkAndDeleteIndex(sqlite*,Index*); void sqliteCopy(Parse*, Token*, Token*, Token*, int); void sqliteVacuum(Parse*, Token*); int sqliteGlobCompare(const unsigned char*,const unsigned char*); int sqliteLikeCompare(const unsigned char*,const unsigned char*); char *sqliteTableNameFromToken(Token*); int sqliteExprCheck(Parse*, Expr*, int, int*); int sqliteExprType(Expr*); int sqliteExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqliteExprResolveIds(Parse*, int, SrcList*, ExprList*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(void); int sqliteRandomInteger(void); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.157 2002/06/20 11:36:50 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
1073 1074 1075 1076 1077 1078 1079 | "Halt", "ColumnCount", "ColumnName", "Callback", "NullCallback", "Integer", "String", "Pop", "Dup", "Pull", "Push", "MustBeInt", "Add", "AddImm", "Subtract", "Multiply", "Divide", "Remainder", "BitAnd", "BitOr", "BitNot", "ShiftLeft", "ShiftRight", "AbsValue", "Eq", "Ne", "Lt", "Le", | | > | | | | 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 | "Halt", "ColumnCount", "ColumnName", "Callback", "NullCallback", "Integer", "String", "Pop", "Dup", "Pull", "Push", "MustBeInt", "Add", "AddImm", "Subtract", "Multiply", "Divide", "Remainder", "BitAnd", "BitOr", "BitNot", "ShiftLeft", "ShiftRight", "AbsValue", "Eq", "Ne", "Lt", "Le", "Gt", "Ge", "StrEq", "StrNe", "StrLt", "StrLe", "StrGt", "StrGe", "IsNull", "NotNull", "Negative", "And", "Or", "Not", "Concat", "Noop", "Function", "Limit", "LimitCk", }; /* ** Given the name of an opcode, return its number. Return 0 if ** there is no match. ** ** This routine is used for testing and debugging. |
︙ | ︙ | |||
1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 | /* Opcode: Eq P1 P2 * ** ** Pop the top two elements from the stack. If they are equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Ne P1 P2 * ** ** Pop the top two elements from the stack. If they are not equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Lt P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is less than the first (the top of stack), then ** jump to instruction P2. Otherwise, continue to the next instruction. ** In other words, jump if NOS<TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Le P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is less than or equal to the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS<=TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Gt P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is greater than the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS>TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Ge P1 P2 * ** ** Pop the top two elements from the stack. If second element (the next ** on stack) is greater than or equal to the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS>=TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ case OP_Eq: case OP_Ne: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 | /* Opcode: Eq P1 P2 * ** ** Pop the top two elements from the stack. If they are equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If both values are numeric, they are converted to doubles using atof() ** and compared for equality that way. Otherwise the strcmp() library ** routine is used for the comparison. For a pure text comparison ** use OP_StrEq. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Ne P1 P2 * ** ** Pop the top two elements from the stack. If they are not equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If both values are numeric, they are converted to doubles using atof() ** and compared in that format. Otherwise the strcmp() library ** routine is used for the comparison. For a pure text comparison ** use OP_StrNe. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Lt P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is less than the first (the top of stack), then ** jump to instruction P2. Otherwise, continue to the next instruction. ** In other words, jump if NOS<TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If both values are numeric, they are converted to doubles using atof() ** and compared in that format. Numeric values are always less than ** non-numeric values. If both operands are non-numeric, the strcmp() library ** routine is used for the comparison. For a pure text comparison ** use OP_StrLt. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Le P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is less than or equal to the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS<=TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If both values are numeric, they are converted to doubles using atof() ** and compared in that format. Numeric values are always less than ** non-numeric values. If both operands are non-numeric, the strcmp() library ** routine is used for the comparison. For a pure text comparison ** use OP_StrLe. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Gt P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is greater than the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS>TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If both values are numeric, they are converted to doubles using atof() ** and compared in that format. Numeric values are always less than ** non-numeric values. If both operands are non-numeric, the strcmp() library ** routine is used for the comparison. For a pure text comparison ** use OP_StrGt. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: Ge P1 P2 * ** ** Pop the top two elements from the stack. If second element (the next ** on stack) is greater than or equal to the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS>=TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** If both values are numeric, they are converted to doubles using atof() ** and compared in that format. Numeric values are always less than ** non-numeric values. If both operands are non-numeric, the strcmp() library ** routine is used for the comparison. For a pure text comparison ** use OP_StrGe. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ case OP_Eq: case OP_Ne: |
︙ | ︙ | |||
2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 | }else if( (fn & STK_Int)!=0 && (ft & STK_Str)!=0 && isInteger(zStack[tos]) ){ Integerify(p, tos); c = aStack[nos].i - aStack[tos].i; }else{ if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem; c = sqliteCompare(zStack[nos], zStack[tos]); } switch( pOp->opcode ){ case OP_Eq: c = c==0; break; case OP_Ne: c = c!=0; break; case OP_Lt: c = c<0; break; case OP_Le: c = c<=0; break; case OP_Gt: c = c>0; break; default: c = c>=0; break; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 | }else if( (fn & STK_Int)!=0 && (ft & STK_Str)!=0 && isInteger(zStack[tos]) ){ Integerify(p, tos); c = aStack[nos].i - aStack[tos].i; }else{ if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem; c = sqliteCompare(zStack[nos], zStack[tos]); } switch( pOp->opcode ){ case OP_Eq: c = c==0; break; case OP_Ne: c = c!=0; break; case OP_Lt: c = c<0; break; case OP_Le: c = c<=0; break; case OP_Gt: c = c>0; break; default: c = c>=0; break; } POPSTACK; POPSTACK; if( pOp->p2 ){ if( c ) pc = pOp->p2-1; }else{ p->tos++; aStack[nos].flags = STK_Int; aStack[nos].i = c; } break; } /* Opcode: StrEq P1 P2 * ** ** Pop the top two elements from the stack. If they are equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** The strcmp() library routine is used for the comparison. For a ** numeric comparison, use OP_Eq. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: StrNe P1 P2 * ** ** Pop the top two elements from the stack. If they are not equal, then ** jump to instruction P2. Otherwise, continue to the next instruction. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** The strcmp() library routine is used for the comparison. For a ** numeric comparison, use OP_Ne. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: StrLt P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is less than the first (the top of stack), then ** jump to instruction P2. Otherwise, continue to the next instruction. ** In other words, jump if NOS<TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** The strcmp() library routine is used for the comparison. For a ** numeric comparison, use OP_Lt. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: StrLe P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is less than or equal to the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS<=TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** The strcmp() library routine is used for the comparison. For a ** numeric comparison, use OP_Le. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: StrGt P1 P2 * ** ** Pop the top two elements from the stack. If second element (the ** next on stack) is greater than the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS>TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** The strcmp() library routine is used for the comparison. For a ** numeric comparison, use OP_Gt. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ /* Opcode: StrGe P1 P2 * ** ** Pop the top two elements from the stack. If second element (the next ** on stack) is greater than or equal to the first (the top of stack), ** then jump to instruction P2. In other words, jump if NOS>=TOS. ** ** If either operand is NULL (and thus if the result is unknown) then ** take the jump if P1 is true. ** ** The strcmp() library routine is used for the comparison. For a ** numeric comparison, use OP_Ge. ** ** If P2 is zero, do not jump. Instead, push an integer 1 onto the ** stack if the jump would have been taken, or a 0 if not. Push a ** NULL if either operand was NULL. */ case OP_StrEq: case OP_StrNe: case OP_StrLt: case OP_StrLe: case OP_StrGt: case OP_StrGe: { int tos = p->tos; int nos = tos - 1; int c; VERIFY( if( nos<0 ) goto not_enough_stack; ) if( (aStack[nos].flags | aStack[tos].flags) & STK_Null ){ POPSTACK; POPSTACK; if( pOp->p2 ){ if( pOp->p1 ) pc = pOp->p2-1; }else{ p->tos++; aStack[nos].flags = STK_Null; } break; }else{ if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem; c = strcmp(zStack[nos], zStack[tos]); } switch( pOp->opcode ){ case OP_Eq: c = c==0; break; case OP_Ne: c = c!=0; break; case OP_Lt: c = c<0; break; case OP_Le: c = c<=0; break; case OP_Gt: c = c>0; break; default: c = c>=0; break; |
︙ | ︙ | |||
2431 2432 2433 2434 2435 2436 2437 | p->tos++; aStack[p->tos].n = nByte; aStack[p->tos].flags = STK_Str | STK_Dyn; zStack[p->tos] = zNewRecord; break; } | | > > > > > | > > > > > | > > | 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 | p->tos++; aStack[p->tos].n = nByte; aStack[p->tos].flags = STK_Str | STK_Dyn; zStack[p->tos] = zNewRecord; break; } /* Opcode: MakeKey P1 P2 P3 ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index. The top P1 records are ** converted to strings and merged. The null-terminators ** are retained and used as separators. ** The lowest entry in the stack is the first field and the top of the ** stack becomes the last. ** ** If P2 is not zero, then the original entries remain on the stack ** and the new key is pushed on top. If P2 is zero, the original ** data is popped off the stack first then the new key is pushed ** back in its place. ** ** 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. ** ** See also: MakeIdxKey, SortMakeKey */ /* Opcode: MakeIdxKey P1 P2 P3 ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index. In addition, take one additional integer ** off of the stack, treat that integer as a four-byte record number, and ** append the four bytes to the key. Thus a total of P1+1 entries are ** popped from the stack for this instruction and a single entry is pushed ** back. The first P1 entries that are popped are strings and the last ** entry (the lowest on the stack) is an integer record number. ** ** The converstion of the first P1 string entries occurs just like in ** MakeKey. Each entry is separated from the others by a null. ** The entire concatenation is null-terminated. The lowest entry ** in the stack is the first field and the top of the stack becomes the ** last. ** ** If P2 is not zero and one or more of the P1 entries that go into the ** generated key is NULL, then jump to P2 after the new key has been ** pushed on the stack. In other words, jump to P2 if the key is ** guaranteed to be unique. This jump can be used to skip a subsequent ** uniqueness test. ** ** 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. ** ** See also: MakeKey, SortMakeKey */ case OP_MakeIdxKey: case OP_MakeKey: { char *zNewKey; int nByte; int nField; int addRowid; int i, j; int containsNull = 0; addRowid = pOp->opcode==OP_MakeIdxKey; nField = pOp->p1; VERIFY( if( p->tos+1+addRowid<nField ) goto not_enough_stack; ) nByte = 0; for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){ int flags = aStack[i].flags; int len; char *z; if( flags & STK_Null ){ nByte += 2; containsNull = 1; }else if( pOp->p3 && pOp->p3[j]=='t' ){ Stringify(p, i); }else if( flags & STK_Real ){ z = aStack[i].z; sqliteRealToSortable(aStack[i].r, &z[1]); z[0] = 0; Release(p, i); len = strlen(&z[1]); zStack[i] = 0; |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.56 2002/06/20 11:36:50 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
183 184 185 186 187 188 189 190 191 192 193 194 195 | #define OP_Remainder 98 #define OP_BitAnd 99 #define OP_BitOr 100 #define OP_BitNot 101 #define OP_ShiftLeft 102 #define OP_ShiftRight 103 #define OP_AbsValue 104 #define OP_Eq 105 #define OP_Ne 106 #define OP_Lt 107 #define OP_Le 108 #define OP_Gt 109 #define OP_Ge 110 | > > > > > > > > > > | | | | | | | | | | | | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | #define OP_Remainder 98 #define OP_BitAnd 99 #define OP_BitOr 100 #define OP_BitNot 101 #define OP_ShiftLeft 102 #define OP_ShiftRight 103 #define OP_AbsValue 104 /* Note: The code generator assumes that OP_XX+6==OP_StrXX */ #define OP_Eq 105 #define OP_Ne 106 #define OP_Lt 107 #define OP_Le 108 #define OP_Gt 109 #define OP_Ge 110 #define OP_StrEq 111 #define OP_StrNe 112 #define OP_StrLt 113 #define OP_StrLe 114 #define OP_StrGt 115 #define OP_StrGe 116 /* Note: the code generator assumes that OP_XX+6==OP_StrXX */ #define OP_IsNull 117 #define OP_NotNull 118 #define OP_Negative 119 #define OP_And 120 #define OP_Or 121 #define OP_Not 122 #define OP_Concat 123 #define OP_Noop 124 #define OP_Function 125 #define OP_Limit 126 #define OP_LimitCk 127 #define OP_MAX 127 /* ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ Vdbe *sqliteVdbeCreate(sqlite*); void sqliteVdbeCreateCallback(Vdbe*, int*); |
︙ | ︙ |