Ability to make id column unsigned. #49

wants to merge 1 commit into


None yet

3 participants


The field type changes for PostgreSQL doesn't seem valid - it should be something like integer check (val > 0). Same for Oracle (add check) and for SQLite if there is support for checks (likely yes).

Otherwise quick cursory glance of the patch doesn't raise any blocker issues.


I am familiar only with MySQL, but I did little research.

PostgreSQL: serial and bigserial are equivalent, except last creates bigint column. Also bigserial suggested by russelm in ticket comments.

SQLite: "Every row of every table has an 64-bit signed integer ROWID. ... If a table contains a column of type INTEGER PRIMARY KEY, then that column becomes an alias for the ROWID.". Looks good for me.

Oracle: Sequence and trigger used to fill in auto field. Existing type (INTEGER (11)) looks big enough.


I would take an approach where unsigned means "constrained to positive values" not anything regarding 2 billion vs 4 billion limits... That is, the important part is using an unsigned datatype if that is available, and restricting the values to positive values if possible. I just can't see how unsigned=True should change the datatype to bigserial.

Also, this pull request does not contain docs or tests - so this is not ready to be pulled in.


You definitely should read related ticket. Whole point is not unsigned int itself, but "twice the integer space".


My take is that the issue is that MySQL allows for unsigned int fields - and you get thus 2x the integer space for free. On PostgreSQL unsigned integer fields are not supported, and thus you will not get the space for free. Now, if you want to specify the field as "guaranteed to hold 32bit unsigned integer values" then yes, bigserial is needed. You do get 2**32 space instead of 2x the space however.

I still stand by my point: it does not make sense to make signed=True to change the datatype from 4-byte signed integer to 8-byte signed integer on PostgreSQL. unsigned should mean negative values are not allowed.


I see you point. Name of parameter was suggested in ticket comments. And I agree - it may not be clear.
About PostgreSQL bigserial - it's values range restricted to to this range according with docs: 1 to 9223372036854775807
I don't know if it works when you try to set value of field with sql.

How about to name parameter 'bigint=True' and set for mysql bigint as type. So for PostgreSQL and MySQL values range and price of storage will be equal (8 bytes, 1-9223372036854775807).


Interestingly enough the bigserial does accept negative values (tested on 9.1), despite the documentation.

So, I suggest this:

  • document the field as taking at least 32-bit unsigned integer values (up to 2**32 -1).
  • use bigserial on PostgreSQL, number(11) on Oracle, check SQLite for correct type
  • add check(col > 0) to the DB

There's no reason why serial and bigserial wouldn't accept negative values. They're simply syntactical sugar around integer and bigint column types respectively, which create a sequence with an initial nextval() of 1. If you wanted to you, could reset the sequence's values to a negative value, and nextval() would count down (up?) to zero, then into positive numbers. I can't think of an immediate use case for this though ;-)

@pzinovkin pzinovkin closed this May 13, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment