From a67830d92e36a83b4ae9aa3b81918fe2287691ab Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 23 Sep 2009 23:03:34 +0100 Subject: [PATCH] 2 changes: move recognisePlayerIDs from fpdb_simple into Database, and make index on siteTourneyNo on Tourneys table unique and refine store_tourneys function to handle this --- pyfpdb/Database.py | 111 +++++++++++++++++++++++++++++-------- pyfpdb/SQL.py | 6 +- pyfpdb/fpdb_parse_logic.py | 2 +- pyfpdb/fpdb_simple.py | 62 --------------------- 4 files changed, 91 insertions(+), 90 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 341a1434..b3adde0c 100755 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -77,7 +77,7 @@ class Database: , {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} # not needed, handled by fk , {'tab':'HandsPlayers', 'col':'tourneyTypeId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} - , {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} + #, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} created elsewhere - needs to be unique ] , [ # indexes for postgres (list index 3) {'tab':'Gametypes', 'col':'siteId', 'drop':0} @@ -93,7 +93,7 @@ class Database: , {'tab':'Players', 'col':'siteId', 'drop':1} , {'tab':'Players', 'col':'name', 'drop':0} , {'tab':'Tourneys', 'col':'tourneyTypeId', 'drop':1} - , {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} + #, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} created elsewhere - needs to be unique , {'tab':'TourneysPlayers', 'col':'playerId', 'drop':0} , {'tab':'TourneysPlayers', 'col':'tourneyId', 'drop':0} , {'tab':'TourneyTypes', 'col':'siteId', 'drop':0} @@ -106,7 +106,7 @@ class Database: , {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneyTypeId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} - , {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} + #, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} created elsewhere - needs to be unique ] ] @@ -491,6 +491,69 @@ class Database: else: return None + #returns the SQL ids of the names given in an array + # TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict + # { playername: id } instead of depending on it's relation to the positions list + # then this can be reduced in complexity a bit + + #def recognisePlayerIDs(cursor, names, site_id): + # result = [] + # for i in xrange(len(names)): + # cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) + # tmp=cursor.fetchall() + # if (len(tmp)==0): #new player + # cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) + # #print "Number of players rows inserted: %d" % cursor.rowcount + # cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) + # tmp=cursor.fetchall() + # #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp + # result.append(tmp[0][0]) + # return result + + def recognisePlayerIDs(self, names, site_id): + c = self.get_cursor() + q = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" %(site_id, " OR name=".join([self.sql.query['placeholder'] for n in names])) + c.execute(q, names) # get all playerids by the names passed in + ids = dict(c.fetchall()) # convert to dict + if len(ids) != len(names): + notfound = [n for n in names if n not in ids] # make list of names not in database + if notfound: # insert them into database + q_ins = "INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")" + q_ins = q_ins.replace('%s', self.sql.query['placeholder']) + c.executemany(q_ins, [(n,) for n in notfound]) + q2 = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" % (site_id, " OR name=".join(["%s" for n in notfound])) + q2 = q2.replace('%s', self.sql.query['placeholder']) + c.execute(q2, notfound) # get their new ids + tmp = c.fetchall() + for n,id in tmp: # put them all into the same dict + ids[n] = id + # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB + return [ids[n] for n in names] + #end def recognisePlayerIDs + + # Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input + # this version could also be improved upon using list comprehensions, etc + + #def recognisePlayerIDs(cursor, names, site_id): + # result = [] + # notfound = [] + # cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names)) + # tmp = dict(cursor.fetchall()) + # for n in names: + # if n not in tmp: + # notfound.append(n) + # else: + # result.append(tmp[n]) + # if notfound: + # cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) + # cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound)) + # tmp = cursor.fetchall() + # for n in tmp: + # result.append(n[0]) + # + # return result + + def get_site_id(self, site): c = self.get_cursor() c.execute(self.sql.query['getSiteId'], (site,)) @@ -867,7 +930,7 @@ class Database: c.execute(self.sql.query['createHandsPlayersTable']) c.execute(self.sql.query['createHandsActionsTable']) c.execute(self.sql.query['createHudCacheTable']) - #c.execute(self.sql.query['addTourneyIndex']) + c.execute(self.sql.query['addTourneyIndex']) #c.execute(self.sql.query['addHandsIndex']) #c.execute(self.sql.query['addPlayersIndex']) self.fillDefaultData() @@ -1858,26 +1921,26 @@ class Database: def store_tourneys(self, tourneyTypeId, siteTourneyNo, entries, prizepool, startTime): try: - cursor = self.get_cursor() - cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s".replace('%s', self.sql.query['placeholder']) - , (siteTourneyNo, tourneyTypeId)) - tmp=cursor.fetchone() - #print "tried SELECTing tourneys.id, result:",tmp - - try: - len(tmp) - except TypeError:#means we have to create new one - cursor.execute("""INSERT INTO Tourneys - (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) - VALUES (%s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) - ,(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) - cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) - tmp=cursor.fetchone() - #print "created new tourneys.id:",tmp + # try and create tourney record, fetch id if it already exists + # avoids race condition when doing the select first + cursor.execute("""INSERT INTO Tourneys + (tourneyTypeId, siteTourneyNo, entries, prizepool, startTime) + VALUES (%s, %s, %s, %s, %s)""".replace('%s', self.sql.query['placeholder']) + ,(tourneyTypeId, siteTourneyNo, entries, prizepool, startTime)) + tmp = self.get_last_insert_id(cursor) + #cursor.execute("SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s", (siteTourneyNo, tourneyTypeId)) + #tmp=cursor.fetchone() + #print "created new tourneys.id:",tmp except: - raise FpdbError( "store_tourneys error: " + str(sys.exc_value) ) + #if str(sys.exc_value) .... not unique index error: + # raise FpdbError( "store_tourneys error: " + str(sys.exc_value) ) + #else: + cursor = self.get_cursor() + cursor.execute( "SELECT id FROM Tourneys WHERE siteTourneyNo=%s AND tourneyTypeId+0=%s".replace('%s', self.sql.query['placeholder']) + , (siteTourneyNo, tourneyTypeId) ) + tmp = cursor.fetchone()[0] - return tmp[0] + return tmp #end def store_tourneys def store_tourneys_players(self, tourney_id, player_ids, payin_amounts, ranks, winnings): @@ -2132,10 +2195,10 @@ class Database: def tStoreTourneyPlayers(self, tourney, dbTourneyId): logging.debug("Database.tStoreTourneyPlayers") # First, get playerids for the players and specifically the one for hero : - playersIds = fpdb_simple.recognisePlayerIDs(self, tourney.players, tourney.siteId) + playersIds = self.recognisePlayerIDs(tourney.players, tourney.siteId) # hero may be None for matrix tourneys summaries # hero = [ tourney.hero ] -# heroId = fpdb_simple.recognisePlayerIDs(self, hero , tourney.siteId) +# heroId = self.recognisePlayerIDs(hero , tourney.siteId) # logging.debug("hero Id = %s - playersId = %s" % (heroId , playersIds)) tourneyPlayersIds=[] diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 986f9762..af9af079 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1160,11 +1160,11 @@ class Sql: if db_server == 'mysql': - self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD INDEX siteTourneyNo(siteTourneyNo)""" + self.query['addTourneyIndex'] = """ALTER TABLE Tourneys ADD UNIQUE INDEX siteTourneyNo(siteTourneyNo)""" elif db_server == 'postgresql': - self.query['addTourneyIndex'] = """CREATE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)""" + self.query['addTourneyIndex'] = """CREATE UNIQUE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)""" elif db_server == 'sqlite': - self.query['addHandsIndex'] = """ """ + self.query['addTourneyIndex'] = """CREATE UNIQUE INDEX siteTourneyNo ON Tourneys (siteTourneyNo)""" if db_server == 'mysql': self.query['addHandsIndex'] = """ALTER TABLE Hands ADD INDEX siteHandNo(siteHandNo)""" diff --git a/pyfpdb/fpdb_parse_logic.py b/pyfpdb/fpdb_parse_logic.py index 4ce1f678..1334a8ac 100644 --- a/pyfpdb/fpdb_parse_logic.py +++ b/pyfpdb/fpdb_parse_logic.py @@ -118,7 +118,7 @@ def mainParser(settings, siteID, category, hand, config, db = None, writeq = Non seatLines.append(line) names = fpdb_simple.parseNames(seatLines) - playerIDs = fpdb_simple.recognisePlayerIDs(db, names, siteID) # inserts players as needed + playerIDs = db.recognisePlayerIDs(names, siteID) # inserts players as needed tmp = fpdb_simple.parseCashesAndSeatNos(seatLines) startCashes = tmp['startCashes'] seatNos = tmp['seatNos'] diff --git a/pyfpdb/fpdb_simple.py b/pyfpdb/fpdb_simple.py index 084949d6..40204ee9 100644 --- a/pyfpdb/fpdb_simple.py +++ b/pyfpdb/fpdb_simple.py @@ -937,68 +937,6 @@ def recogniseTourneyTypeId(db, siteId, tourneySiteId, buyin, fee, knockout, rebu return result[0] #end def recogniseTourneyTypeId -#returns the SQL ids of the names given in an array -# TODO: if someone gets industrious, they should make the parts that use the output of this function deal with a dict -# { playername: id } instead of depending on it's relation to the positions list -# then this can be reduced in complexity a bit - -#def recognisePlayerIDs(cursor, names, site_id): -# result = [] -# for i in xrange(len(names)): -# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) -# tmp=cursor.fetchall() -# if (len(tmp)==0): #new player -# cursor.execute ("INSERT INTO Players (name, siteId) VALUES (%s, %s)", (names[i], site_id)) -# #print "Number of players rows inserted: %d" % cursor.rowcount -# cursor.execute ("SELECT id FROM Players WHERE name=%s", (names[i],)) -# tmp=cursor.fetchall() -# #print "recognisePlayerIDs, names[i]:",names[i],"tmp:",tmp -# result.append(tmp[0][0]) -# return result - -def recognisePlayerIDs(db, names, site_id): - c = db.get_cursor() - q = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" %(site_id, " OR name=".join([db.sql.query['placeholder'] for n in names])) - c.execute(q, names) # get all playerids by the names passed in - ids = dict(c.fetchall()) # convert to dict - if len(ids) != len(names): - notfound = [n for n in names if n not in ids] # make list of names not in database - if notfound: # insert them into database - q_ins = "INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")" - q_ins = q_ins.replace('%s', db.sql.query['placeholder']) - c.executemany(q_ins, [(n,) for n in notfound]) - q2 = "SELECT name,id FROM Players WHERE siteid=%d and (name=%s)" % (site_id, " OR name=".join(["%s" for n in notfound])) - q2 = q2.replace('%s', db.sql.query['placeholder']) - c.execute(q2, notfound) # get their new ids - tmp = c.fetchall() - for n,id in tmp: # put them all into the same dict - ids[n] = id - # return them in the SAME ORDER that they came in in the names argument, rather than the order they came out of the DB - return [ids[n] for n in names] -#end def recognisePlayerIDs - - -# Here's a version that would work if it wasn't for the fact that it needs to have the output in the same order as input -# this version could also be improved upon using list comprehensions, etc - -#def recognisePlayerIDs(cursor, names, site_id): -# result = [] -# notfound = [] -# cursor.execute("SELECT name,id FROM Players WHERE name='%s'" % "' OR name='".join(names)) -# tmp = dict(cursor.fetchall()) -# for n in names: -# if n not in tmp: -# notfound.append(n) -# else: -# result.append(tmp[n]) -# if notfound: -# cursor.executemany("INSERT INTO Players (name, siteId) VALUES (%s, "+str(site_id)+")", (notfound)) -# cursor.execute("SELECT id FROM Players WHERE name='%s'" % "' OR name='".join(notfound)) -# tmp = cursor.fetchall() -# for n in tmp: -# result.append(n[0]) -# -# return result #recognises the name in the given line and returns its array position in the given array def recognisePlayerNo(line, names, atype):