Thread: Using Random Sequence as Key

Using Random Sequence as Key

From
"Bernardo de Barros Franco"
Date:
Hello, I was wondering if noone can help me maybe someone could at least
give me some directions where to look for info or where to ask:
I wanted to index a table by a random key. Exemplifying, when a insert is
made, the id value is automatically filled with a random number between
10000 and 99999. I'm pretty new in pgsql so I could use a howto or
something, and I repeat, if you don't know how, directions to where I can
find info on that or where I can ask someone that might know would be
enough.

Thank you





Re: Using Random Sequence as Key

From
Peter Eisentraut
Date:
Bernardo de Barros Franco writes:

> I wanted to index a table by a random key. Exemplifying, when a insert is
> made, the id value is automatically filled with a random number between
> 10000 and 99999.

=> create table test (id int default random() * 89999 + 10000, content text);
CREATE
=> insert into test (content) values ('hi');
INSERT 36163 1
=> insert into test (content) values ('there');
INSERT 36164 1
=> insert into test (content) values ('blah');
INSERT 36165 1
=> select * from test; id   | content
-------+---------61616 | hi72605 | there83469 | blah
(3 rows)

Verifying the default expression for correct boundaries is left as an
exercise.  ;-)

-- 
Peter Eisentraut   peter_e@gmx.net   http://funkturm.homeip.net/~peter



Re: Using Random Sequence as Key

From
Peter Eisentraut
Date:
Bernardo de Barros Franco writes:

> But my only question would be, in the example quoted would id be really the
> table index and is it unique?

Making unique *and* random numbers is a pretty complex (and slow) thing to
do in general.  Consider redesigning your application.

>
> Thank you
>
> Quoting:
> >Bernardo de Barros Franco writes:
> >
> > > I wanted to index a table by a random key. Exemplifying, when a insert
> >is
> > > made, the id value is automatically filled with a random number between
> > > 10000 and 99999.
> >
> >=> create table test (id int default random() * 89999 + 10000, content
> >text);
> >CREATE
> >=> insert into test (content) values ('hi');
> >INSERT 36163 1
> >=> insert into test (content) values ('there');
> >INSERT 36164 1
> >=> insert into test (content) values ('blah');
> >INSERT 36165 1
> >=> select * from test;
> >   id   | content
> >-------+---------
> >  61616 | hi
> >  72605 | there
> >  83469 | blah
> >(3 rows)
> _________________________________________________________________________
> Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com.
>
>

-- 
Peter Eisentraut   peter_e@gmx.net   http://funkturm.homeip.net/~peter



Re: Using Random Sequence as Key

From
Roberto Mello
Date:
On Sun, Apr 15, 2001 at 10:58:40PM -0300, Bernardo de Barros Franco wrote:

> I wanted to index a table by a random key. Exemplifying, when a insert is
> made, the id value is automatically filled with a random number between
> 10000 and 99999. I'm pretty new in pgsql so I could use a howto or
Bernardo,
Do you really need the keys to be random numbers? Can't the keys be
sequential numbers, like 1,2,3,4...? That'd be a lot easier to make
unique, and as far as the user is concerned, it'll be random for him/her.-Roberto
-- 
+----| http://fslc.usu.edu USU Free Software & GNU/Linux Club |------+ Roberto Mello - Computer Science, USU -
http://www.brasileiro.net      http://www.sdl.usu.edu - Space Dynamics Lab, Developer    
 
Oh my GOSH! A Prompt!!! HELP!!!! A PROMPT !!!!! HEEEEELP !!!!!!!!!!!!!


Using Random Sequence as Key

From
Dan Lyke
Date:
Bernardo de Barros Franco writes:
> Hello, I was wondering if noone can help me maybe someone could at least
> give me some directions where to look for info or where to ask:
> I wanted to index a table by a random key.

As others have pointed out, making a unique random primary key is
tough. What I do for my cookie on my web based login system is have
two fields in my database, one's the "id SERIAL", the other is a
"magiccookie CHAR(16)" which I populate with 16 random characters on
the initial insert.

My cookie is then of the format "id/magiccookie". In my login
verification code I split on the "/" character and query on "WHERE
id=$id AND magiccookie=$magiccooke". Even though the "id" field is
encoded in the cookie in plain text a cracker can't just guess at the
user id number because that 16 character magiccookie needs to match as
well.

This also lets me be pretty loose about the id information, I can use
it in other public places, because only the magiccookie needs to be
restricted to being known by the logged in user.

Dan


Re: Using Random Sequence as Key

From
"Bernardo de Barros Franco"
Date:
Since I can't really redesign my application, I could index the table using
a serial but still would need a field with the random and unique number. I
tried using including a unique in : create table test (id int UNIQUE default
random() * 89999 + 10000, content text); and it didn't return any errors,
I'm just not sure if it actually worked.
I needed the random field because if I use serial and the user gets a 34203
he's sure that 34202 exists, and that (probably, there where 34202 inserts
before him (or at least an offset + some)). Using a random just makes the
user totally blind.
As I said I could use a serial for indexing the table but I NEED the random
field and I need to to be unique since all the queries will be using it as a
search parameter.
If inserting this way is slow it's not such a big deal since it's a small db
and inserts are seldom made.
Thanks in advance for any help.

Quoting:
> On Sun, Apr 15, 2001 at 10:58:40PM -0300, Bernardo de Barros Franco wrote:
>
> > I wanted to index a table by a random key. Exemplifying, when a insert
is
> > made, the id value is automatically filled with a random number between
> > 10000 and 99999. I'm pretty new in pgsql so I could use a howto or
>
> Bernardo,
>
> Do you really need the keys to be random numbers? Can't the keys be
> sequential numbers, like 1,2,3,4...? That'd be a lot easier to make
> unique, and as far as the user is concerned, it'll be random for him/her.
>




Re: Using Random Sequence as Key

From
"Bernardo de Barros Franco"
Date:
It is a good way to solve it but since I don't want/can't use cookies in my
application I could use only the random key but it would have to be unique
or the where key=$key could refer to multiple lines or I would have to ask
for the user to input both the random and the serial number wich wouldn't be
very good either. That's the reason I've being trying to make a random key
wich would be unique so I could ask for the user to type his order code and
then select info from orders where ordercode=$ordercode and not have the
risk of getting multiple answers (more then one line with that ordercode) or
someone typing his ordercode-1 and accessing someone elses form.
Ok, if I don't use a password or other protection even with random users can
keep trying to guess but I don't have much of a problem with someone
accessing someone else's form, I just don't want the user to let's say type
his ordercode and by mistake type the last char say 1 less then his own and
access someone else form and be completely lost. With random that still can
happen but it is so less likely that will do.

Thank you

Quoting:
> Bernardo de Barros Franco writes:
> > Hello, I was wondering if noone can help me maybe someone could at least
> > give me some directions where to look for info or where to ask:
> > I wanted to index a table by a random key.
>
> As others have pointed out, making a unique random primary key is
> tough. What I do for my cookie on my web based login system is have
> two fields in my database, one's the "id SERIAL", the other is a
> "magiccookie CHAR(16)" which I populate with 16 random characters on
> the initial insert.
>
> My cookie is then of the format "id/magiccookie". In my login
> verification code I split on the "/" character and query on "WHERE
> id=$id AND magiccookie=$magiccooke". Even though the "id" field is
> encoded in the cookie in plain text a cracker can't just guess at the
> user id number because that 16 character magiccookie needs to match as
> well.
>
> This also lets me be pretty loose about the id information, I can use
> it in other public places, because only the magiccookie needs to be
> restricted to being known by the logged in user.




Re: Re: Using Random Sequence as Key

From
"Josh Berkus"
Date:
Bernardo,

> I needed the random field because if I use serial and the user gets a
> 34203
> he's sure that 34202 exists, and that (probably, there where 34202
> inserts
> before him (or at least an offset + some)). Using a random just makes
> the
> user totally blind.
> As I said I could use a serial for indexing the table but I NEED the
> random
> field and I need to to be unique since all the queries will be using
> it as a
> search parameter.
> If inserting this way is slow it's not such a big deal since it's a
> small db
> and inserts are seldom made.
> Thanks in advance for any help.

Here's another suggestion for you then:

1. Add a sequence "Sales_sq"

1. write a custom function for new id numbers:
CREATE FUNCTION new_sales_id() RETURNS INT4 AS '
DECLAREtimeportion VARCHAR;serialportion INT4;
BEGINtimeportion := to_char(current_timestamp, ''ms'');
-- (or whatever the abbreviation for 2-digit milliseconds is)serialportion := 100*(nextval(''sales_seq''));RETURN
CAST(to_number(timeportion)AS INT4) + serialportion;
 
END;

3. Then set the id column to default to this new function.

This would give you (after you correct my mistakes) a number, the first
X digits of are Serial, and the last 2 digits based on the server's
internal clock.  Thus, the numbers would *not* be sequential, and would
appear fairly random, but would be unique *without* and expensive check
for that value anywhere in the table for each insert.

-Josh Berkus






______AGLIO DATABASE SOLUTIONS___________________________                                      Josh Berkus Complete
informationtechnology      josh@agliodbs.com  and data management solutions       (415) 565-7293 for law firms, small
businesses       fax 621-2533   and non-profit organizations.      San Francisco
 


Re: Re: Using Random Sequence as Key

From
Brook Milligan
Date:
It is a good way to solve it but since I don't want/can't use cookies in my  application I could use only the random
keybut it would have to be unique  or the where key=$key could refer to multiple lines or I would have to ask  for the
userto input both the random and the serial number wich wouldn't be  very good either. That's the reason I've being
tryingto make a random key  wich would be unique so I could ask for the user to type his order code and  then select
infofrom orders where ordercode=$ordercode and not have the  risk of getting multiple answers (more then one line with
thatordercode) or  someone typing his ordercode-1 and accessing someone elses form.
 

Do you have users logging in so that you know who is requesting the
data?  If so, just make a view that includes WHERE name = current_user
to filter out all irrelevant (i.e., other people's) rows (inserts
should set name to the appropriate user, of course).  In that case a
SERIAL will work fine, since there is no chance of seeing anyone
else's information and the SERIAL is unique.  More secure, also.

Cheers,
Brook


Re: Using Random Sequence as Key

From
Vasilis Samoladas
Date:
Hello Bernardo,

there is a somewhat mathematical solution to your problem.
You can use a unique key, say 0<= k < MAX for each record,
and a second key which is computed from the first, say
f(k), which will give you a unique permutation of the
numbers 0,...,MAX-1. It will not be random, but it will
be hard for someone to figure out the original unique
key k, without knowning your method.

Here is one way to compute f(k): (math follows, beware!)

The Fibonacci numbers are a sequence defined as follows:
F(0) = 0, F(1) = 1,  F(n+2) = F(n+1)+F(n) (for n>=0).

Now, for every fixed number N>=2, you can define
a permutation f(k) of the numbers 0,...,F(N)-1
as follows:
f(k) =  (k*F(N-1)) mod F(N)

For example, if N=6, we have F(6)=8 and F(5)=5, so
for 0<= k <8,  f(k) = 5*k mod 8 is a permutation.
In particular,
k    =  0 1 2 3 4 5 6 7
f(k) =  0 5 2 7 4 1 6 3

So, since you need approximately 90000 numbers (10000 to 99999),
you can use N=25, which will give you F(25)=75025 and F(24)=46368.
Thus, you can have 75025 (slightly fewer than 90000) unique values,
by translating k into
f(k) = 46368*k mod 75025

Unless your users know number theory, this should work for you.

Vasilis


Bernardo de Barros Franco <electric_csf@hotmail.com> wrote:
: Hello, I was wondering if noone can help me maybe someone could at least
: give me some directions where to look for info or where to ask:
: I wanted to index a table by a random key. Exemplifying, when a insert is
: made, the id value is automatically filled with a random number between
: 10000 and 99999. I'm pretty new in pgsql so I could use a howto or
: something, and I repeat, if you don't know how, directions to where I can
: find info on that or where I can ask someone that might know would be
: enough.

: Thank you





Re: Re: Using Random Sequence as Key

From
Ken Corey
Date:
First of all, let me apologise for stepping so far back into the archives, 
but I wanted to get this in the archives in case anyone else wanted to use 
this.

There's a slight addendum here...as written, it's fairly likely that people 
will get duplicate ID's using this system.

A small change gets rid of the problem: multiply the serialportion by the 
number of digits you'll have in timeportion.  So, if timeportion is three 
digits, you'd multiply serialportion by 1000 and *then* add the timeportion. 
Below, I use the mod operator '%' to make sure it's 3 digits or less.

Caveat: this will only work as long as you have less than 40 million users.  
;^)

-Ken

create FUNCTION new_request_id()
RETURNS INT4
as' DECLARE        timeportion INT4;        serialportion INT4; BEGIN        timeportion := cast 
(date_part(''milliseconds'',timeofday()::timestamp) as integer);        serialportion :=
nextval(''request_idfake_seq'')*1000;        RETURN (timeportion % 1000) + serialportion; END;'
 
LANGUAGE 'plpgsql'
;


On Tuesday 17 April 2001  3:08 pm, Josh Berkus wrote:
> Bernardo,
>
> > I needed the random field because if I use serial and the user gets a
> > 34203
> > he's sure that 34202 exists, and that (probably, there where 34202
> > inserts
> > before him (or at least an offset + some)). Using a random just makes
> > the
> > user totally blind.
> > As I said I could use a serial for indexing the table but I NEED the
> > random
> > field and I need to to be unique since all the queries will be using
> > it as a
> > search parameter.
> > If inserting this way is slow it's not such a big deal since it's a
> > small db
> > and inserts are seldom made.
> > Thanks in advance for any help.
>
> Here's another suggestion for you then:
>
> 1. Add a sequence "Sales_sq"
>
> 1. write a custom function for new id numbers:
> CREATE FUNCTION new_sales_id() RETURNS INT4 AS '
> DECLARE
>     timeportion VARCHAR;
>     serialportion INT4;
> BEGIN
>     timeportion := to_char(current_timestamp, ''ms'');
> -- (or whatever the abbreviation for 2-digit milliseconds is)
>     serialportion := 100*(nextval(''sales_seq''));
>     RETURN CAST(to_number(timeportion) AS INT4) + serialportion;
> END;
>
> 3. Then set the id column to default to this new function.
>
> This would give you (after you correct my mistakes) a number, the first
> X digits of are Serial, and the last 2 digits based on the server's
> internal clock.  Thus, the numbers would *not* be sequential, and would
> appear fairly random, but would be unique *without* and expensive check
> for that value anywhere in the table for each insert.
>
> -Josh Berkus
>
>
>
>
>
>
> ______AGLIO DATABASE SOLUTIONS___________________________
>                                        Josh Berkus
>   Complete information technology      josh@agliodbs.com
>    and data management solutions       (415) 565-7293
>   for law firms, small businesses        fax 621-2533
>     and non-profit organizations.      San Francisco
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

-- 
Ken Corey, CTO    Atomic Interactive, Ltd.   ken.corey@atomic-interactive.com