ErlyORM / boss_db

BossDB: a sharded, caching, pooling, evented ORM for Erlang
Other
277 stars 138 forks source link

boss_db_adapter_mysql incr and reset have logic issue #148

Closed roowe closed 10 years ago

roowe commented 10 years ago

UPDATE not exist name, it return {update, MySQLRes},not {error, }. so I alway incr error.

And, reset cann't use find(Key), because counter model not exist.

zkessin commented 10 years ago

Can you explain this a bit better, I don't understand the problem. Until then I am closing it

roowe commented 10 years ago
incr(Pid, Id, Count) ->
    Res = fetch(Pid, ["UPDATE counters SET value = value + ", pack_value(Count), 
            " WHERE name = ", pack_value(Id)]),
    case Res of
        {updated, _} ->
            counter(Pid, Id); % race condition
        {error, _Reason} -> 
            Res1 = fetch(Pid, ["INSERT INTO counters (name, value) VALUES (",
                    pack_value(Id), ", ", pack_value(Count), ")"]),
            case Res1 of
                {updated, _} -> counter(Pid, Id); % race condition
                {error, MysqlRes} -> {error, mysql:get_result_reason(MysqlRes)}
            end
    end.

if name not exist, SQL "UPDATE counters SET value=value+1 WHERE name=not_exist", Res is {updated, MysqlRes}, not {error, _Reason}, you can try it. My Fix like this.

incr(Pid, Id, Count) ->
    Res = fetch(Pid, ["UPDATE counters SET value = value + ", pack_value(Count), 
                      " WHERE name = ", pack_value(Id)]),
    case Res of
        {updated, MysqlRes} ->
            case mysql:get_result_affected_rows(MysqlRes) of
                0 ->
                    case fetch(Pid, ["INSERT INTO counters (name, value) VALUES (",
                                     pack_value(Id), ", ", pack_value(Count), ")"]) of
                        {updated, _} -> 
                            Count;
                        {error, MysqlRes} -> 
                            {error, mysql:get_result_reason(MysqlRes)}
                    end;
                1 ->
                    counter(Pid, Id) % race condition
            end;
        {error, Reason} -> 
            {error, mysql:get_result_reason(Reason)}
    end.

But, then I try reset the couter, crash boss_db:find function.

I think you can do the fuck test. and will know my mean.