LP#1745486: avoid retrieving user by id::numeric during auth init
authorGalen Charlton <gmc@equinoxinitiative.org>
Thu, 25 Jan 2018 21:58:33 +0000 (16:58 -0500)
committerBill Erickson <berickxx@gmail.com>
Tue, 30 Jan 2018 20:43:53 +0000 (15:43 -0500)
During open-ils.auth.authenticate.init, if looking up the user by barcode,
the actor.usr row is subsequently fetched by ID. However, the ID was
turned into a float, meaning that the query as sent to the database
was equivalent to

  SELECT * FROM actor.usr WHERE id = 123.0000;

While PostgreSQL will accept this, it ends up doing a sequential
scan of the actor.usr table rather than an index lookup, making the
retrieval up to two orders of magnitude slower than it needs to be
and adding a couple percent unecessary I/O load on large, heavily
used database. This patch fixes that.

To test
-------
[1] Turn on PostgreSQL statment logging and log in as a user
    by barcode. Note that there's a retrieval of actor.usr by
    a float form of the ID.
[2] Apply the patch and repeat step 1. This time, the query
    retrieves the row by the integer form of the ID.

Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org>
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/c-apps/oils_utils.c

index 4074d9e..5492dbf 100644 (file)
@@ -393,16 +393,16 @@ jsonObject* oilsUtilsFetchUserByBarcode(osrfMethodContext* ctx, const char* barc
        if(!card)
                return NULL;   // No such card
 
-       // Get the user's id as a double
+       // Get the user's id as a long
        char* usr = oilsFMGetString(card, "usr");
        jsonObjectFree(card);
        if(!usr)
                return NULL;   // No user id (shouldn't happen)
-       double iusr = strtod(usr, NULL);
+       long iusr = strtol(usr, NULL, 10);
        free(usr);
 
        // Look up the user in actor.usr
-       params = jsonParseFmt("[%f]", iusr);
+       params = jsonParseFmt("[%d]", iusr);
        jsonObject* user = oilsUtilsQuickReqCtx(
                ctx, "open-ils.cstore", "open-ils.cstore.direct.actor.user.retrieve", params);