SQLite

Check-in [b77c268ebe]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add manifest type aware versions of the min() and max() aggregates. (CVS 1452)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b77c268ebebd5401c3f519a72cfb81438207368c
User & Date: danielk1977 2004-05-25 01:13:21.000
Context
2004-05-25
11:47
Use the new API for returning values and errors from user functions. (CVS 1453) (check-in: 4eccae03b4 user: danielk1977 tags: trunk)
01:13
Add manifest type aware versions of the min() and max() aggregates. (CVS 1452) (check-in: b77c268ebe user: danielk1977 tags: trunk)
2004-05-24
23:48
Aggregate functions also use sqlite_value* instead of const char * for arguments. (CVS 1451) (check-in: 5c28ed5e9b user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/func.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
** 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.52 2004/05/24 23:48:26 danielk1977 Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"

#include "os.h"

/*
** Implementation of the non-aggregate min() and max() functions
*/
static void minmaxFunc(sqlite_func *context, int argc, sqlite3_value **argv){
  const char *zBest; 







|






>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
** 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.53 2004/05/25 01:13:21 danielk1977 Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "os.h"

/*
** Implementation of the non-aggregate min() and max() functions
*/
static void minmaxFunc(sqlite_func *context, int argc, sqlite3_value **argv){
  const char *zBest; 
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
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
  char zBuf[28];   /* Space that can be used for storage */
};

/*
** Routines to implement min() and max() aggregate functions.
*/
static void minmaxStep(sqlite_func *context, int argc, sqlite3_value **argv){
  MinMaxCtx *p;
  int (*xCompare)(const char*, const char*);
  int mask;    /* 0 for min() or 0xffffffff for max() */
  const char *zArg0 = sqlite3_value_data(argv[0]);
  const char *zArg1 = sqlite3_value_data(argv[1]);

  assert( argc==2 );
  if( zArg1[0]=='n' ){
    xCompare = sqlite3Compare;
  }else{
    xCompare = strcmp;
  }

  mask = (int)sqlite3_user_data(context);
  p = sqlite3_aggregate_context(context, sizeof(*p));
  if( p==0 || argc<1 || zArg0==0 ) return;
  if( p->z==0 || (xCompare(zArg0,p->z)^mask)<0 ){
    int len;
    if( !p->zBuf[0] ){
      sqliteFree(p->z);
    }
    len = strlen(zArg0);
    if( len < sizeof(p->zBuf)-1 ){
      p->z = &p->zBuf[1];
      p->zBuf[0] = 1;
    }else{
      p->z = sqliteMalloc( len+1 );
      p->zBuf[0] = 0;
      if( p->z==0 ) return;
    }
    strcpy(p->z, zArg0);
  }
}
static void minMaxFinalize(sqlite_func *context){
  MinMaxCtx *p;
  p = sqlite3_aggregate_context(context, sizeof(*p));
  if( p && p->z ){









    sqlite3_set_result_string(context, p->z, strlen(p->z));






  }
  if( p && !p->zBuf[0] ){
    sqliteFree(p->z);
  }
}

/*
** This function registered all of the above C functions as SQL
** functions.  This should be the only routine in this file with
** external linkage.







|
|
<
|
|

<
<
|
<
<
|
>
|
|
<
<
<
|
|

<
<
<
<
|
|
<
<
<
<



|
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
<
<







540
541
542
543
544
545
546
547
548

549
550
551


552


553
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
  char zBuf[28];   /* Space that can be used for storage */
};

/*
** Routines to implement min() and max() aggregate functions.
*/
static void minmaxStep(sqlite_func *context, int argc, sqlite3_value **argv){
  int max = 0;
  int cmp = 0;

  Mem *pArg  = (Mem *)argv[0];
  Mem *pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));



  if( SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return;



  if( pBest->flags ){
    max = ((sqlite3_user_data(context)==(void *)-1)?1:0);
    cmp = sqlite3MemCompare(pBest, pArg, 0);



    if( (max && cmp<0) || (!max && cmp>0) ){
      sqlite3MemCopy(pBest, pArg);
    }




  }else{
    sqlite3MemCopy(pBest, pArg);




  }
}
static void minMaxFinalize(sqlite_func *context){
  sqlite3_value *pRes;
  pRes = (sqlite3_value *)sqlite3_aggregate_context(context, sizeof(Mem));
  
  if( pRes->flags ){
    switch( sqlite3_value_type(pRes) ){
      case SQLITE3_INTEGER: 
        sqlite3_set_result_int(context, sqlite3_value_int(pRes));
        break;
      case SQLITE3_FLOAT: 
        sqlite3_set_result_double(context, sqlite3_value_float(pRes));
      case SQLITE3_TEXT: 
      case SQLITE3_BLOB: 
        sqlite3_set_result_string(context,
            sqlite3_value_data(pRes),
            sqlite3_value_bytes(pRes));
        break;
      case SQLITE3_NULL: 
      default:
        assert(0);
    }


  }
}

/*
** This function registered all of the above C functions as SQL
** functions.  This should be the only routine in this file with
** external linkage.
Changes to src/vdbeInt.h.
357
358
359
360
361
362
363

364
365
366
367
368
int sqlite3VdbeSerialPut(unsigned char *, Mem *);
int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *, u8 enc);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);

int sqlite3VdbeKeyCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeRowCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeSetEncoding(Mem *, u8);







>





357
358
359
360
361
362
363
364
365
366
367
368
369
int sqlite3VdbeSerialPut(unsigned char *, Mem *);
int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *, u8 enc);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3MemCopy(Mem*, const Mem*);
int sqlite3VdbeKeyCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeRowCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeSetEncoding(Mem *, u8);
Changes to src/vdbeaux.c.
1456
1457
1458
1459
1460
1461
1462



























1463
1464
1465
1466
1467
1468
1469
  */
  rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
  if( rc==0 ){
    rc = pMem1->n - pMem2->n;
  }
  return rc;
}




























/*
** The following is the comparison function for (non-integer)
** keys in the btrees.  This function returns negative, zero, or
** positive if the first key is less than, equal to, or greater than
** the second.
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
  */
  rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
  if( rc==0 ){
    rc = pMem1->n - pMem2->n;
  }
  return rc;
}

/*
** Copy the contents of memory cell pFrom into pTo.
*/
int sqlite3MemCopy(Mem *pTo, const Mem *pFrom){
  if( pTo->flags&MEM_Dyn ){
    sqliteFree(pTo->z);
  }

  memcpy(pTo, pFrom, sizeof(*pFrom));
  if( pTo->flags&MEM_Short ){
    pTo->z = pTo->zShort;
  }
  else if( pTo->flags&(MEM_Ephem|MEM_Dyn) ){
    pTo->flags = pTo->flags&(~(MEM_Static|MEM_Ephem|MEM_Short|MEM_Dyn));
    if( pTo->n>NBFS ){
      pTo->z = sqliteMalloc(pTo->n);
      if( !pTo->z ) return SQLITE_NOMEM;
      pTo->flags |= MEM_Dyn;
    }else{
      pTo->z = pTo->zShort;
      pTo->flags |= MEM_Short;
    }
    memcpy(pTo->z, pFrom->z, pTo->n);
  }
  return SQLITE_OK;
}

/*
** The following is the comparison function for (non-integer)
** keys in the btrees.  This function returns negative, zero, or
** positive if the first key is less than, equal to, or greater than
** the second.
**