On Wed, 09 Feb 2011 18:51:45 -0500, Samuel Adam <a...@certifound.com>  
wrote:

> On Wed, 09 Feb 2011 18:39:14 -0500, David Bicking <dbic...@yahoo.com>
> wrote:
>
>> 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.
>
> You are right, as xoring on my fingers would have verified.  In polite
> terms, evidently I just demonstrated publicly math as not my forté ||
> today as not my day.  Apologies for the noise.

At risk of worsening my today’s foot-in-mouth syndrome, I believe that the  
following design would keep *some* of the advantages I outlined at cost of  
the following:

        (a) It would only work for 31-bit integers (or 32-bit integers with  
additional tricks to store two 32-bit unsigneds in a 64-bit signed).

        (b) Increased computational cost.

However, it adds one advantage (in addition to being correct!):

        (c) It would collapse the full informational content of "x" and "y" 
into  
the same column "xk" (viz., the all-important INTEGER PRIMARY KEY).  And  
still, no additional indices are required.

In pseudo-C:

        int32_t x, y;
        int64_t xk;             /* k lives in the low bits of xk */
        
        if (x < 0 || y < 0) ;   /* Return an error. */
        
        xk = (int64_t)x<<32 | x^y;
        /* Weird integer concatenation; yes, precedence is right. */

If you don’t mind living dangerously, use union or pointer tricks to  
coerce uint32_t x, y into an sqlite3_int64.

Upon the foregoing, only one column ("xk" INTEGER PRIMARY KEY) is required  
to actually store the data.  With the foregoing pseudo-C placed in an SQL  
user function, however, this is also possible:

        CREATE TABLE "" (
                "xk" INTEGER PRIMARY KEY, "x" INTEGER, "y" INTEGER,
                CHECK ("xk" IS compose_xk("x", "y"))
        );

I think Shannon bit me before, but he’s on my side now.

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


> 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
>
>
>> 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

Reply via email to