I don't think this will work. xor(6,1) = 7 and xor(4,3) = 7, so you 
would fail to insert proper pairs. Or am I missing something?  (At least 
I assume that the integers are not limited to just 1 2 or 3 as in the 
examples.

David

On 02/09/2011 05:58 PM, Samuel Adam wrote:
> On Wed, 09 Feb 2011 13:12:32 -0500, Black, Michael (IS)
> <michael.bla...@ngc.com>  wrote:
>
>    
>> I have a need to create a unique bi-directional relationship.
>>
>> You can think of it as pairings of people who eat dinner together.
>>      
> Two questions come to mind:
>
>       (a) Do you trust app-level code to maintain data integrity, or do you
> need SQLite to do this?
>
>       (b) How much relational rigor do you need?  Will the values be used for
> some kind of relational algebra, or is SQLite simply serving as an ACID
> reliability layer?
>
> Since you’ve been considering the bit-math tricks suggested by Mr.
> Wilcoxson, the answers to these questions may let you consider some XOR
> cleverness.  Unfortunately, I halfway wrote this up before I realized that
> SQLite lacks a ^ operator[1]; so you will need a trivial SQL user function
> and/or app-land code.  Still, with the following, you can store any pairs
> of 63-bit integers>= 0.  In pure SQL:
>
>       CREATE TABLE "" ("k" INTEGER PRIMARY KEY, "x" INTEGER);
>       -- WRONG: INSERT INTO "" ("k", "x") VALUES (:x ^ :y, :x);
>       INSERT INTO "" ("k", "x") VALUES (xor(:x, :y), :x);
>               -- Faster on the app level; you understand.
>       SELECT "x", xor("k", "x") AS "y" FROM "";
>
> (Add NOT NULL or CHECK(typeof("x") IS 'integer') and salt to taste.  N.b.,
> I *think* the above binding scenario will work but have not tested it.)
>
> [1] 2009·12·15 thread with reference to ^ patch by Will Clark:
> Message-ID:
> <off7402127.00e0cd73-onc125768d.0045dfc4-c125768d.0049d...@gfs-hofheim.de>
> http://www.mail-archive.com/sqlite-users@sqlite.org/msg49112.html
>
> Key points:
>
>       * Pair uniqueness is enforced for free.  At least, I think it’s really
> for free because SQLite always requires a unique rowid.  Somebody please
> correct me if there is any penalty for user-selected rowids, which would
> make the performance impact nonzero.
>
>       * Order of (x, y) versus (y, x) pairings is preserved.  Sorts on y will
> be a pain, though.
>
>       * No extra indices are required.
>
>       * I don’t see a reasonable way to stop arbitrary data from being stuffed
> in from within SQLite, even with a user function; for although :y is being
> bound on INSERT, a CHECK constraint has no way to touch it.  But see below
> for a modified table with a different set of tradeoffs.
>
>       * Since two small integers XORed will be another small integer, you do
> not suffer the loss of variable-length integer storage as spoken of by
> Messrs. Vlasov and Tandetnik.
>
>       * XOR is *fast*.  And the number of integers is kept to a bare minimum
> (for keeping up to 63 bits for each), cutting cache pressure at all
> levels—from SQLite’s page-cache to the processor caches.  I am no expert
> in optimization, but the foregoing practically begs to be benchmarked.
>
>       * If for some reason you can’t use xor("k", "x") for all your SQL needs
> (foreign keys come to mind), add another explicit "y" column.  You then
> lose some of the foregoing advantages.  But then, a trivial (and probably
> quite fast) pure-SQL constraint could then be used to enforce some
> integrity:
>
>       CREATE TABLE "" (
>               "k" INTEGER PRIMARY KEY, "x" INTEGER, "y" INTEGER,
>               CHECK ("k" IS xor("x", "y")) -- NOT NULL for free!
>       );
> i
>       * If you try to use negative integers, your database will trigger a HCF
> instruction.  At the cost of some more performance, CHECK("x">= 0 AND
> xor("k", "x")>= 0) will *partially* solve that.  I say “partially”
> because per the foregoing, SQLite cannot guarantee that "y" = "k"^"x"
> unless you use the modified table, anyway.
>
> Bear in mind, this suggestion stems from a personal bias toward clever XOR
> tricks; at that, I once wrote a set of endian-swab functions with no
> (explicit) temporary variables, purely using XOR-swap and shifts.  I found
> it the most pleasant way to satisfy aliasing rules; yet I am to this day
> uncertain whether the result qualifies as abstract art.
>
> P.S.:  Consider the foregoing a real-life use case in support of adding a
> bitwise ^ operator to SQLite.
>
> Very truly,
>
> Samuel Adam ◊<http://certifound.com/>
> 763 Montgomery Road ◊ Hillsborough, NJ  08844-1304 ◊ United States
> Legal advice from a non-lawyer: “If you are sued, don’t do what the
> Supreme Court of New Jersey, its agents, and its officers did.”
> http://www.youtube.com/watch?v=iT2hEwBfU1g
>
>
>    
>> create table t(i int, j int);
>>
>> insert into t(1,2);
>>
>> insert into t(2,1);<<  should give an error because the pairing of 1-2
>> already exists.
>>
>> insert into t(3,2);<<  OK
>>
>> insert into t(3,1);<<  OK
>>
>> insert into t(1,3);<<  should be error
>>
>>
>>
>> You can't guarantee that one column is less than the other so there's no
>> win there.
>>
>>
>>
>> Speed is of the utmost concern here so fast is really important (how
>> many ways can I say that???).
>>
>>
>>
>> Is there anything clever here that can be done with indexes or such?
>>
>>
>>
>>
>>
>> Michael D. Black
>>
>> Senior Scientist
>>
>> NG Information Systems
>>
>> Advanced Analytics Directorate
>>
>>      
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
>    

_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to