[ 
https://issues.apache.org/jira/browse/TRAFODION-3042?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16451392#comment-16451392
 ] 

ASF GitHub Bot commented on TRAFODION-3042:
-------------------------------------------

Github user zellerh commented on a diff in the pull request:

    https://github.com/apache/trafodion/pull/1539#discussion_r183907638
  
    --- Diff: core/sql/exp/exp_function.cpp ---
    @@ -5937,45 +5938,22 @@ void ExFunctionRandomNum::initSeed(char *op_data[])
     
           // Pick an initial seed.  According to the reference given below
           // (in the eval function), all initial seeds between 1 and
    -      // 2147483646 are equally valid.  So, we just need to pick one
    +      // 2147483647 are equally valid.  So, we just need to pick one
           // in this range.  Do this based on a timestamp.
    +      struct timespec seedTime;
     
    -      // Use ex_function_current to get timestamp.
    -      //
    -      char currBuff[32];
    -      char *opData[1];
    -      opData[0] = currBuff;
    -      ex_function_current currentFun;
    -      currentFun.eval(&opData[0], 0, 0);
    +      clock_gettime(CLOCK_REALTIME, &seedTime);
     
    -      // Extract year, month, etc.
    -      //
    -      char *p = currBuff;
    -      short year = *((short*) p);
    -      p += sizeof(short);
    -      char month = *p++;
    -      char day = *p++;
    -      char hour = *p++;
    -      char minute = *p++;
    -      char second = *p++;
    -      Lng32 fraction = *((Lng32*) p);
    -
    -      // Local variables year, ..., fraction are now initialized.
    -      // From the values of these variables, generate a seed in the
    -      // desired range.
    -
    -      Lng32 x = year * month * day;
    -      if (hour) x *= hour;
    -      p = (char*) &x;
    -
    -      assert(sizeof(Lng32)==4);
    -
    -      p[0] |= (second<<1);
    -      p[1] |= (minute<<1);
    -      p[2] |= (minute<<2);
    -      p[3] |= second;
    -
    -      seed_ = x + fraction;
    +      seed_  = (Int32) (seedTime.tv_sec  % 2147483648);
    +      seed_ ^= (Int32) (seedTime.tv_nsec % 2147483648L);
    +
    +      // Go through one step of a linear congruential random generator.
    +      // (https://en.wikipedia.org/wiki/Linear_congruential_generator).
    +      // This is to avoid seed values that are close to each other when
    +      // we call this method again within a short time. The eval() method
    +      // below doesn't handle seed values that are close to each other
    +      // very well.
    +      seed_ = (((Int64) seed_) * 1664525L + 1664525L) % 2147483648;
    --- End diff --
    
    Thanks, yes, good catch! Looks like a copy & paste error.


> RAND() function is not always random
> ------------------------------------
>
>                 Key: TRAFODION-3042
>                 URL: https://issues.apache.org/jira/browse/TRAFODION-3042
>             Project: Apache Trafodion
>          Issue Type: Bug
>          Components: sql-exe
>    Affects Versions: 2.2.0
>            Reporter: Hans Zeller
>            Assignee: Hans Zeller
>            Priority: Major
>
> When trying the RAND() function, I found that it does not always behave as I 
> would expect. I tried this example:
> {noformat}
> >>select rand(), rand(), rand() from dual;
> (EXPR)      (EXPR)      (EXPR)    
> ----------  ----------  ----------
>   78242471    78511383    78612225
> --- 1 row(s) selected.
> >>select rand(), rand(), rand() from dual;
> (EXPR)      (EXPR)      (EXPR)    
> ----------  ----------  ----------
> 1589208276  1589460381  1589561223
> --- 1 row(s) selected.
> >>select rand(), rand(), rand() from dual;
> (EXPR)      (EXPR)      (EXPR)    
> ----------  ----------  ----------
> 134371215   134724162   134858618
> --- 1 row(s) selected.
> >>
> {noformat}
> So, it seems that if we call rand() within a very short time, the value will 
> be non-random.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to