We started seeing the error message below recently on a site running 6.x-1.x-dev (2011-Feb-25) version of User Karma:
Warning: mysqli_query() [function.mysqli-query]: (21000/1242): Subquery returns more than 1 row in _db_query() (line 120 of /includes/database.mysqli.inc).
After investigating, we tracked this down to the user_karma_user_rank function in user_karma.module. We found that the $extra_bit query on line 792 was returning more than one value:
$extra_bit = "(SELECT value FROM {votingapi_cache} vc2 WHERE vc2.content_type = '%s' AND vc2.value_type = '%s' AND vc2.tag = '%s' AND vc2.function = '%s' AND vc2.content_id = %d)";
And this is what the query produced (I replaced "value" with "*" to get the full data rows):
| vote_cache_id | content_type | content_id | value | value_type | tag | function | timestamp |
| 436883 | user | 2061 | 0 | karma_points | karma | sum | 1312666569 |
| 436884 | user | 2061 | 127 | karma_points | karma | sum | 1312666569 |
So the user was able to somehow record two entries in the votingapi_cache table... maybe through a double click that recorded two "sum" votes at the exact same moment? Obviously this is a problem because the user_karma code expects the results of $extra_bit to be a single value, not multiple rows.
This could ultimately be an issue with the votingapi module, since the actual calculation is done via the votingapi_set_votes function which is called in the user_karma_calculate_karma function. Is there a reason why user_karma should record "0" values to the votingapi_cache table? Is there a need for them? We have a few other users in our DB that have multiple votingapi_cache records for user_karma.
I don't have time right now to investigate this further, but my guess is there needs to be a conditional somewhere that ensures a second record is not inserted into votingapi_cache if one already exists for the current uid, and to ensure records are not inserted with "0" as the sum value.
For right now I am going to add a quick-fix patch to the query on line 792 to only return results that are greater than zero:
$extra_bit = "(SELECT value FROM {votingapi_cache} vc2 WHERE vc2.content_type = '%s' AND vc2.value_type = '%s' AND vc2.tag = '%s' AND vc2.function = '%s' AND vc2.content_id = %d AND vc2.value > 0)";
Also as some additional data, we are running Pressflow and Varnish. Might there be some conflicts with caching that allow users to have two entries recorded? The safe approach would be to just add conditionals to not allow multiple uid sum records and "0" value records to be inserted into the table.