stmtrand.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. ** 2024-05-24
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. ******************************************************************************
  12. **
  13. ** An SQL function that return pseudo-random non-negative integers.
  14. **
  15. ** SELECT stmtrand(123);
  16. **
  17. ** A special feature of this function is that the same sequence of random
  18. ** integers is returned for each invocation of the statement. This makes
  19. ** the results repeatable, and hence useful for testing. The argument is
  20. ** an integer which is the seed for the random number sequence. The seed
  21. ** is used by the first invocation of this function only and is ignored
  22. ** for all subsequent calls within the same statement.
  23. **
  24. ** Resetting a statement (sqlite3_reset()) also resets the random number
  25. ** sequence.
  26. */
  27. #include "sqlite3ext.h"
  28. SQLITE_EXTENSION_INIT1
  29. #include <assert.h>
  30. #include <string.h>
  31. /* State of the pseudo-random number generator */
  32. typedef struct Stmtrand {
  33. unsigned int x, y;
  34. } Stmtrand;
  35. /* auxdata key */
  36. #define STMTRAND_KEY (-4418371)
  37. /*
  38. ** Function: stmtrand(SEED)
  39. **
  40. ** Return a pseudo-random number.
  41. */
  42. static void stmtrandFunc(
  43. sqlite3_context *context,
  44. int argc,
  45. sqlite3_value **argv
  46. ){
  47. Stmtrand *p;
  48. p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
  49. if( p==0 ){
  50. unsigned int seed;
  51. p = sqlite3_malloc( sizeof(*p) );
  52. if( p==0 ){
  53. sqlite3_result_error_nomem(context);
  54. return;
  55. }
  56. if( argc>=1 ){
  57. seed = (unsigned int)sqlite3_value_int(argv[0]);
  58. }else{
  59. seed = 0;
  60. }
  61. p->x = seed | 1;
  62. p->y = seed;
  63. sqlite3_set_auxdata(context, STMTRAND_KEY, p, sqlite3_free);
  64. p = (Stmtrand*)sqlite3_get_auxdata(context, STMTRAND_KEY);
  65. if( p==0 ){
  66. sqlite3_result_error_nomem(context);
  67. return;
  68. }
  69. }
  70. p->x = (p->x>>1) ^ ((1+~(p->x&1)) & 0xd0000001);
  71. p->y = p->y*1103515245 + 12345;
  72. sqlite3_result_int(context, (int)((p->x ^ p->y)&0x7fffffff));
  73. }
  74. #ifdef _WIN32
  75. __declspec(dllexport)
  76. #endif
  77. int sqlite3_stmtrand_init(
  78. sqlite3 *db,
  79. char **pzErrMsg,
  80. const sqlite3_api_routines *pApi
  81. ){
  82. int rc = SQLITE_OK;
  83. SQLITE_EXTENSION_INIT2(pApi);
  84. (void)pzErrMsg; /* Unused parameter */
  85. rc = sqlite3_create_function(db, "stmtrand", 1, SQLITE_UTF8, 0,
  86. stmtrandFunc, 0, 0);
  87. if( rc==SQLITE_OK ){
  88. rc = sqlite3_create_function(db, "stmtrand", 0, SQLITE_UTF8, 0,
  89. stmtrandFunc, 0, 0);
  90. }
  91. return rc;
  92. }