From 141b88ecfd9f045d2c108ba684e5032e868e932b Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 20 Feb 2010 17:49:03 +0000 Subject: [PATCH 01/10] stop hudcache updating again when importing duplicate hands --- pyfpdb/Hand.py | 3 +++ pyfpdb/fpdb_import.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Hand.py b/pyfpdb/Hand.py index 73dd7600..e54354e8 100644 --- a/pyfpdb/Hand.py +++ b/pyfpdb/Hand.py @@ -125,6 +125,7 @@ class Hand(object): # currency symbol for this hand self.sym = self.SYMBOL[self.gametype['currency']] # save typing! delete this attr when done self.pot.setSym(self.sym) + self.is_duplicate = False # i.e. don't update hudcache if true def __str__(self): vars = ( ("BB", self.bb), @@ -236,6 +237,7 @@ db: a connected Database object""" # TourneysPlayers else: log.info("Hand.insert(): hid #: %s is a duplicate" % hh['siteHandNo']) + self.is_duplicate = True # i.e. don't update hudcache raise FpdbHandDuplicate(hh['siteHandNo']) def updateHudCache(self, db): @@ -669,6 +671,7 @@ class HoldemOmahaHand(Hand): if self.maxseats is None: self.maxseats = hhc.guessMaxSeats(self) hhc.readOther(self) + #print "\nHand:\n"+str(self) elif builtFrom == "DB": if handid is not None: self.select(handid) # Will need a handId diff --git a/pyfpdb/fpdb_import.py b/pyfpdb/fpdb_import.py index 95ffd525..689858e0 100755 --- a/pyfpdb/fpdb_import.py +++ b/pyfpdb/fpdb_import.py @@ -456,7 +456,7 @@ class Importer: # FIXME: Need to test for bulk import that isn't rebuilding the cache if self.callHud: for hand in handlist: - if hand is not None: + if hand is not None and not hand.is_duplicate: hand.updateHudCache(self.database) self.database.commit() From 09801cd00e4ea3e8eb6cfd89ecbce105e04d622e Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Sat, 20 Feb 2010 18:59:49 +0000 Subject: [PATCH 02/10] first go at db maintenance window, turned off for now --- pyfpdb/Configuration.py | 31 ++++++++------ pyfpdb/Database.py | 92 +++++++++++++++++++++-------------------- pyfpdb/fpdb.py | 38 +++++++++++++---- 3 files changed, 97 insertions(+), 64 deletions(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index 3d506735..07c96a04 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -695,18 +695,8 @@ class Config: try: db['db-server'] = self.supported_databases[name].db_server except: pass - if self.supported_databases[name].db_server== DATABASE_TYPE_MYSQL: - db['db-backend'] = 2 - elif self.supported_databases[name].db_server== DATABASE_TYPE_POSTGRESQL: - db['db-backend'] = 3 - elif self.supported_databases[name].db_server== DATABASE_TYPE_SQLITE: - db['db-backend'] = 4 - # sqlcoder: this assignment fixes unicode problems for me with sqlite (windows, cp1252) - # feel free to remove or improve this if you understand the problems - # better than me (not hard!) - Charset.not_needed1, Charset.not_needed2, Charset.not_needed3 = True, True, True - else: - raise ValueError('Unsupported database backend: %s' % self.supported_databases[name].db_server) + db['db-backend'] = self.get_backend(self.supported_databases[name].db_server) + return db def set_db_parameters(self, db_name = 'fpdb', db_ip = None, db_user = None, @@ -725,6 +715,23 @@ class Config: if db_server is not None: self.supported_databases[db_name].dp_server = db_server if db_type is not None: self.supported_databases[db_name].dp_type = db_type return + + def get_backend(self, name): + """Returns the number of the currently used backend""" + if name == DATABASE_TYPE_MYSQL: + ret = 2 + elif name == DATABASE_TYPE_POSTGRESQL: + ret = 3 + elif name == DATABASE_TYPE_SQLITE: + ret = 4 + # sqlcoder: this assignment fixes unicode problems for me with sqlite (windows, cp1252) + # feel free to remove or improve this if you understand the problems + # better than me (not hard!) + Charset.not_needed1, Charset.not_needed2, Charset.not_needed3 = True, True, True + else: + raise ValueError('Unsupported database backend: %s' % self.supported_databases[name].db_server) + + return ret def getDefaultSite(self): "Returns first enabled site or None" diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0303aad2..debaee59 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -226,7 +226,7 @@ class Database: # create index indexname on tablename (col); - def __init__(self, c, sql = None): + def __init__(self, c, sql = None, autoconnect = True): #log = Configuration.get_logger("logging.conf", "db", log_dir=c.dir_log) log.debug("Creating Database instance, sql = %s" % sql) self.config = c @@ -247,41 +247,42 @@ class Database: else: self.sql = sql - # connect to db - self.do_connect(c) - - if self.backend == self.PGSQL: - from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE - #ISOLATION_LEVEL_AUTOCOMMIT = 0 - #ISOLATION_LEVEL_READ_COMMITTED = 1 - #ISOLATION_LEVEL_SERIALIZABLE = 2 + if autoconnect: + # connect to db + self.do_connect(c) + + if self.backend == self.PGSQL: + from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_SERIALIZABLE + #ISOLATION_LEVEL_AUTOCOMMIT = 0 + #ISOLATION_LEVEL_READ_COMMITTED = 1 + #ISOLATION_LEVEL_SERIALIZABLE = 2 - if self.backend == self.SQLITE and self.database == ':memory:' and self.wrongDbVersion: - log.info("sqlite/:memory: - creating") - self.recreate_tables() - self.wrongDbVersion = False + if self.backend == self.SQLITE and self.database == ':memory:' and self.wrongDbVersion: + log.info("sqlite/:memory: - creating") + self.recreate_tables() + self.wrongDbVersion = False - self.pcache = None # PlayerId cache - self.cachemiss = 0 # Delete me later - using to count player cache misses - self.cachehit = 0 # Delete me later - using to count player cache hits + self.pcache = None # PlayerId cache + self.cachemiss = 0 # Delete me later - using to count player cache misses + self.cachehit = 0 # Delete me later - using to count player cache hits - # config while trying out new hudcache mechanism - self.use_date_in_hudcache = True + # config while trying out new hudcache mechanism + self.use_date_in_hudcache = True - #self.hud_hero_style = 'T' # Duplicate set of vars just for hero - not used yet. - #self.hud_hero_hands = 2000 # Idea is that you might want all-time stats for others - #self.hud_hero_days = 30 # but last T days or last H hands for yourself + #self.hud_hero_style = 'T' # Duplicate set of vars just for hero - not used yet. + #self.hud_hero_hands = 2000 # Idea is that you might want all-time stats for others + #self.hud_hero_days = 30 # but last T days or last H hands for yourself - # vars for hand ids or dates fetched according to above config: - self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now - self.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) - self.h_date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) for hero - self.date_nhands_ago = {} # dates N hands ago per player - not used yet + # vars for hand ids or dates fetched according to above config: + self.hand_1day_ago = 0 # max hand id more than 24 hrs earlier than now + self.date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) + self.h_date_ndays_ago = 'd000000' # date N days ago ('d' + YYMMDD) for hero + self.date_nhands_ago = {} # dates N hands ago per player - not used yet - self.saveActions = False if self.import_options['saveActions'] == False else True + self.saveActions = False if self.import_options['saveActions'] == False else True - self.connection.rollback() # make sure any locks taken so far are released + self.connection.rollback() # make sure any locks taken so far are released #end def __init__ # could be used by hud to change hud style @@ -313,7 +314,7 @@ class Database: self.__connected = True def connect(self, backend=None, host=None, database=None, - user=None, password=None): + user=None, password=None, create=False): """Connects a database with the given parameters""" if backend is None: raise FpdbError('Database backend not defined') @@ -384,32 +385,35 @@ class Database: # log.warning("SQLite won't work well without 'sqlalchemy' installed.") if database != ":memory:": - if not os.path.isdir(self.config.dir_database): + if not os.path.isdir(self.config.dir_database) and create: print "Creating directory: '%s'" % (self.config.dir_database) log.info("Creating directory: '%s'" % (self.config.dir_database)) os.mkdir(self.config.dir_database) database = os.path.join(self.config.dir_database, database) self.db_path = database log.info("Connecting to SQLite: %(database)s" % {'database':self.db_path}) - self.connection = sqlite3.connect(self.db_path, detect_types=sqlite3.PARSE_DECLTYPES ) - sqlite3.register_converter("bool", lambda x: bool(int(x))) - sqlite3.register_adapter(bool, lambda x: "1" if x else "0") - self.connection.create_function("floor", 1, math.floor) - tmp = sqlitemath() - self.connection.create_function("mod", 2, tmp.mod) - if use_numpy: - self.connection.create_aggregate("variance", 1, VARIANCE) + if os.path.exists(database) or create: + self.connection = sqlite3.connect(self.db_path, detect_types=sqlite3.PARSE_DECLTYPES ) + sqlite3.register_converter("bool", lambda x: bool(int(x))) + sqlite3.register_adapter(bool, lambda x: "1" if x else "0") + self.connection.create_function("floor", 1, math.floor) + tmp = sqlitemath() + self.connection.create_function("mod", 2, tmp.mod) + if use_numpy: + self.connection.create_aggregate("variance", 1, VARIANCE) + else: + log.warning("Some database functions will not work without NumPy support") + self.cursor = self.connection.cursor() + self.cursor.execute('PRAGMA temp_store=2') # use memory for temp tables/indexes + self.cursor.execute('PRAGMA synchronous=0') # don't wait for file writes to finish else: - log.warning("Some database functions will not work without NumPy support") - self.cursor = self.connection.cursor() - self.cursor.execute('PRAGMA temp_store=2') # use memory for temp tables/indexes - self.cursor.execute('PRAGMA synchronous=0') # don't wait for file writes to finish + raise FpdbError("sqlite database "+database+" does not exist") else: - raise FpdbError("unrecognised database backend:"+backend) + raise FpdbError("unrecognised database backend:"+str(backend)) self.cursor = self.connection.cursor() self.cursor.execute(self.sql.query['set tx level']) - self.check_version(database=database, create=True) + self.check_version(database=database, create=create) def check_version(self, database, create): diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index 29f5ff6a..7e81d1e6 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -97,6 +97,7 @@ except: import GuiPrefs import GuiLogView +import GuiDatabase import GuiBulkImport import GuiPlayerStats import GuiPositionalStats @@ -288,10 +289,31 @@ class fpdb: dia.destroy() - def dia_create_del_database(self, widget, data=None): - self.warning_box("Unimplemented: Create/Delete Database") - self.obtain_global_lock() - self.release_global_lock() + def dia_maintain_dbs(self, widget, data=None): + self.warning_box("Unimplemented: Maintain Databases") + return + if len(self.tab_names) == 1: + if self.obtain_global_lock(): # returns true if successful + # only main tab has been opened, open dialog + dia = gtk.Dialog("Maintain Databases", + self.window, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, + gtk.STOCK_SAVE, gtk.RESPONSE_ACCEPT)) + dia.set_default_size(700, 320) + + prefs = GuiDatabase.GuiDatabase(self.config, self.window, dia) + response = dia.run() + if response == gtk.RESPONSE_ACCEPT: + # save updated config + self.config.save() + + self.release_global_lock() + + dia.destroy() + else: + self.warning_box("Cannot open Database Maintenance window because " + + "other windows have been opened. Re-start fpdb to use this option.") def dia_create_del_user(self, widget, data=None): self.warning_box("Unimplemented: Create/Delete user") @@ -620,7 +642,7 @@ class fpdb: - + @@ -663,7 +685,7 @@ class fpdb: ('sessionreplay', None, '_Session Replayer (todo)', None, 'Session Replayer (todo)', self.not_implemented), ('tableviewer', None, 'Poker_table Viewer (mostly obselete)', None, 'Poker_table Viewer (mostly obselete)', self.tab_table_viewer), ('database', None, '_Database'), - ('createdb', None, 'Create or Delete _Database (todo)', None, 'Create or Delete Database', self.dia_create_del_database), + ('maintaindbs', None, '_Maintain Databases (todo)', None, 'Maintain Databases', self.dia_maintain_dbs), ('createuser', None, 'Create or Delete _User (todo)', None, 'Create or Delete User', self.dia_create_del_user), ('createtabs', None, 'Create or Recreate _Tables', None, 'Create or Recreate Tables ', self.dia_recreate_tables), ('rebuildhudcache', None, 'Rebuild HUD Cache', None, 'Rebuild HUD Cache', self.dia_recreate_hudcache), @@ -685,7 +707,7 @@ class fpdb: window.add_accel_group(accel_group) return menubar - def load_profile(self): + def load_profile(self, create_db = False): """Loads profile from the provided path name.""" self.config = Configuration.Config(file=options.config, dbname=options.dbname) if self.config.file_error: @@ -911,7 +933,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") self.tab_main_help(None, None) self.window.show() - self.load_profile() + self.load_profile(create_db = True) if not options.errorsToConsole: fileName = os.path.join(self.config.dir_log, 'fpdb-errors.txt') From 03880bbc63f7635821b5ff5ac75796d83ef6a94a Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Wed, 24 Feb 2010 10:28:12 -0500 Subject: [PATCH 03/10] Trivial refactor of get_stats_from_hand for readability. --- pyfpdb/Database.py | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 0303aad2..76addf59 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -643,6 +643,29 @@ class Database: , hero_id = -1 , num_seats = 6 ): + + (hud_style, h_hud_style, query, subs) = self.prep_aggregation(hand, hud_params, hero_id, num_seats) + + c = self.connection.cursor() + +# now get the stats + stat_dict = {} + c.execute(self.sql.query[query], subs) + colnames = [desc[0] for desc in c.description] + for row in c.fetchall(): + playerid = row[0] + if (playerid == hero_id and h_hud_style != 'S') or (playerid != hero_id and hud_style != 'S'): + t_dict = {} + for name, val in zip(colnames, row): + t_dict[name.lower()] = val +# print t_dict + stat_dict[t_dict['player_id']] = t_dict + + return stat_dict + + def prep_aggregation(self, hand, hud_params, hero_id, num_seats): +# This sorts through the all the info having to do with aggregation +# and returns what get_stats needs. hud_style = hud_params['hud_style'] agg_bb_mult = hud_params['agg_bb_mult'] seats_style = hud_params['seats_style'] @@ -652,8 +675,6 @@ class Database: h_seats_style = hud_params['h_seats_style'] h_seats_cust_nums = hud_params['h_seats_cust_nums'] - stat_dict = {} - if seats_style == 'A': seats_min, seats_max = 0, 10 elif seats_style == 'C': @@ -715,23 +736,7 @@ class Database: subs = (hand ,hero_id, stylekey, agg_bb_mult, agg_bb_mult, seats_min, seats_max # hero params ,hero_id, h_stylekey, h_agg_bb_mult, h_agg_bb_mult, h_seats_min, h_seats_max) # villain params - - #print "get stats: hud style =", hud_style, "query =", query, "subs =", subs - c = self.connection.cursor() - -# now get the stats - c.execute(self.sql.query[query], subs) - colnames = [desc[0] for desc in c.description] - for row in c.fetchall(): - playerid = row[0] - if (playerid == hero_id and h_hud_style != 'S') or (playerid != hero_id and hud_style != 'S'): - t_dict = {} - for name, val in zip(colnames, row): - t_dict[name.lower()] = val -# print t_dict - stat_dict[t_dict['player_id']] = t_dict - - return stat_dict + return (hud_style, h_hud_style, query, subs) # uses query on handsplayers instead of hudcache to get stats on just this session def get_stats_from_hand_session(self, hand, stat_dict, hero_id From 6ac76d2d9be0021bbd1a00ecd10d4895f81effe5 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 24 Feb 2010 21:25:19 +0000 Subject: [PATCH 04/10] remove earlier bracket change that screwed stats up - it seemed necessary then but I can't figure out why now --- pyfpdb/GuiPlayerStats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyfpdb/GuiPlayerStats.py b/pyfpdb/GuiPlayerStats.py index 047c1ff1..3c3f46e3 100644 --- a/pyfpdb/GuiPlayerStats.py +++ b/pyfpdb/GuiPlayerStats.py @@ -520,7 +520,7 @@ class GuiPlayerStats (threading.Thread): blindtest = str(tuple(nolims)) blindtest = blindtest.replace("L", "") blindtest = blindtest.replace(",)",")") - bbtest = bbtest + blindtest + ' ) ) )' + bbtest = bbtest + blindtest + ' ) )' else: bbtest = bbtest + '(-1) ) )' if type == 'ring': From 04e8f117d5ebd47a29307328002d5f1bc49449ef Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Wed, 24 Feb 2010 17:06:36 -0500 Subject: [PATCH 05/10] Revert "Trivial refactor of get_stats_from_hand for readability." This reverts commit 03880bbc63f7635821b5ff5ac75796d83ef6a94a. --- pyfpdb/Database.py | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 76addf59..0303aad2 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -643,29 +643,6 @@ class Database: , hero_id = -1 , num_seats = 6 ): - - (hud_style, h_hud_style, query, subs) = self.prep_aggregation(hand, hud_params, hero_id, num_seats) - - c = self.connection.cursor() - -# now get the stats - stat_dict = {} - c.execute(self.sql.query[query], subs) - colnames = [desc[0] for desc in c.description] - for row in c.fetchall(): - playerid = row[0] - if (playerid == hero_id and h_hud_style != 'S') or (playerid != hero_id and hud_style != 'S'): - t_dict = {} - for name, val in zip(colnames, row): - t_dict[name.lower()] = val -# print t_dict - stat_dict[t_dict['player_id']] = t_dict - - return stat_dict - - def prep_aggregation(self, hand, hud_params, hero_id, num_seats): -# This sorts through the all the info having to do with aggregation -# and returns what get_stats needs. hud_style = hud_params['hud_style'] agg_bb_mult = hud_params['agg_bb_mult'] seats_style = hud_params['seats_style'] @@ -675,6 +652,8 @@ class Database: h_seats_style = hud_params['h_seats_style'] h_seats_cust_nums = hud_params['h_seats_cust_nums'] + stat_dict = {} + if seats_style == 'A': seats_min, seats_max = 0, 10 elif seats_style == 'C': @@ -736,7 +715,23 @@ class Database: subs = (hand ,hero_id, stylekey, agg_bb_mult, agg_bb_mult, seats_min, seats_max # hero params ,hero_id, h_stylekey, h_agg_bb_mult, h_agg_bb_mult, h_seats_min, h_seats_max) # villain params - return (hud_style, h_hud_style, query, subs) + + #print "get stats: hud style =", hud_style, "query =", query, "subs =", subs + c = self.connection.cursor() + +# now get the stats + c.execute(self.sql.query[query], subs) + colnames = [desc[0] for desc in c.description] + for row in c.fetchall(): + playerid = row[0] + if (playerid == hero_id and h_hud_style != 'S') or (playerid != hero_id and hud_style != 'S'): + t_dict = {} + for name, val in zip(colnames, row): + t_dict[name.lower()] = val +# print t_dict + stat_dict[t_dict['player_id']] = t_dict + + return stat_dict # uses query on handsplayers instead of hudcache to get stats on just this session def get_stats_from_hand_session(self, hand, stat_dict, hero_id From a26dfa09f25ac1c5f6369afb246345ea66dd6ddd Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Wed, 24 Feb 2010 22:21:13 +0000 Subject: [PATCH 06/10] automation: prompt for gtk dir location and copy files and dirs - resulting dir should be ready for distribution (once zipped up) --- pyfpdb/py2exe_setup.py | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/pyfpdb/py2exe_setup.py b/pyfpdb/py2exe_setup.py index 9975317f..cf9560af 100644 --- a/pyfpdb/py2exe_setup.py +++ b/pyfpdb/py2exe_setup.py @@ -73,6 +73,7 @@ from distutils.core import setup import py2exe import glob import matplotlib +import shutil from datetime import date @@ -111,7 +112,7 @@ def test_and_remove(top): # remove build and dist dirs if they exist test_and_remove('dist') test_and_remove('build') -test_and_remove('gfx') +#test_and_remove('gfx') today = date.today().strftime('%Y%m%d') @@ -174,3 +175,36 @@ dest = dest.replace('\\', '\\\\') os.rename( 'pyfpdb', dest ) +print "Enter directory name for GTK 2.14 (e.g. c:\code\gtk_2.14.7-20090119)\n: ", # the comma means no newline +gtk_dir = sys.stdin.readline().rstrip() + + +print "\ncopying files and dirs from ", gtk_dir, "to", dest.replace('\\\\', '\\'), "..." +src = os.path.join(gtk_dir, 'bin', 'libgdk-win32-2.0-0.dll') +src = src.replace('\\', '\\\\') +shutil.copy( src, dest ) + +src = os.path.join(gtk_dir, 'bin', 'libgobject-2.0-0.dll') +src = src.replace('\\', '\\\\') +shutil.copy( src, dest ) + + +src_dir = os.path.join(gtk_dir, 'etc') +src_dir = src_dir.replace('\\', '\\\\') +dest_dir = os.path.join(dest, 'etc') +dest_dir = dest_dir.replace('\\', '\\\\') +shutil.copytree( src_dir, dest_dir ) + +src_dir = os.path.join(gtk_dir, 'lib') +src_dir = src_dir.replace('\\', '\\\\') +dest_dir = os.path.join(dest, 'lib') +dest_dir = dest_dir.replace('\\', '\\\\') +shutil.copytree( src_dir, dest_dir ) + +src_dir = os.path.join(gtk_dir, 'share') +src_dir = src_dir.replace('\\', '\\\\') +dest_dir = os.path.join(dest, 'share') +dest_dir = dest_dir.replace('\\', '\\\\') +shutil.copytree( src_dir, dest_dir ) + + From 134a13bf298678c4f59bebbd4e443e7f240475d7 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 25 Feb 2010 20:43:15 +0000 Subject: [PATCH 07/10] create indexes on hudcache in sqlite --- pyfpdb/Database.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index debaee59..d0fe733b 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -142,14 +142,18 @@ class Database: , {'tab':'TourneyTypes', 'col':'siteId', 'drop':0} ] , [ # indexes for sqlite (list index 4) - # {'tab':'Players', 'col':'name', 'drop':0} unique indexes not dropped - # {'tab':'Hands', 'col':'siteHandNo', 'drop':0} unique indexes not dropped {'tab':'Hands', 'col':'gametypeId', 'drop':0} , {'tab':'HandsPlayers', 'col':'handId', 'drop':0} , {'tab':'HandsPlayers', 'col':'playerId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneyTypeId', 'drop':0} , {'tab':'HandsPlayers', 'col':'tourneysPlayersId', 'drop':0} - #, {'tab':'Tourneys', 'col':'siteTourneyNo', 'drop':0} unique indexes not dropped + , {'tab':'HudCache', 'col':'gametypeId', 'drop':1} + , {'tab':'HudCache', 'col':'playerId', 'drop':0} + , {'tab':'HudCache', 'col':'tourneyTypeId', 'drop':0} + , {'tab':'Players', 'col':'siteId', 'drop':1} + , {'tab':'Tourneys', 'col':'tourneyTypeId', 'drop':1} + , {'tab':'TourneysPlayers', 'col':'playerId', 'drop':0} + , {'tab':'TourneyTypes', 'col':'siteId', 'drop':0} ] ] @@ -725,6 +729,8 @@ class Database: # now get the stats c.execute(self.sql.query[query], subs) + #for row in c.fetchall(): # needs "explain query plan" in sql statement + # print "query plan: ", row colnames = [desc[0] for desc in c.description] for row in c.fetchall(): playerid = row[0] @@ -2100,6 +2106,7 @@ class HandToWrite: if __name__=="__main__": c = Configuration.Config() + sql = SQL.Sql(db_server = 'sqlite') db_connection = Database(c) # mysql fpdb holdem # db_connection = Database(c, 'fpdb-p', 'test') # mysql fpdb holdem @@ -2117,12 +2124,25 @@ if __name__=="__main__": if hero: print "nutOmatic is id_player = %d" % hero + # example of displaying query plan in sqlite: + if db_connection.backend == 4: + print + c = db_connection.get_cursor() + c.execute('explain query plan '+sql.query['get_table_name'], (h, )) + for row in c.fetchall(): + print "query plan: ", row + print + + t0 = time() stat_dict = db_connection.get_stats_from_hand(h, "ring") + t1 = time() for p in stat_dict.keys(): print p, " ", stat_dict[p] print "cards =", db_connection.get_cards(u'1') db_connection.close_connection + + print "get_stats took: %4.3f seconds" % (t1-t0) print "press enter to continue" sys.stdin.readline() From 70bb9d687dfe441274f717d18aa4be61c8935864 Mon Sep 17 00:00:00 2001 From: sqlcoder Date: Thu, 25 Feb 2010 20:57:28 +0000 Subject: [PATCH 08/10] add commented out 'explain query plan' to go with previous commit --- pyfpdb/SQL.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyfpdb/SQL.py b/pyfpdb/SQL.py index 6db24fb4..51863698 100644 --- a/pyfpdb/SQL.py +++ b/pyfpdb/SQL.py @@ -1346,6 +1346,7 @@ class Sql: # same as above except stats are aggregated for all blind/limit levels self.query['get_stats_from_hand_aggregated'] = """ + /* explain query plan */ SELECT hc.playerId AS player_id, max(case when hc.gametypeId = h.gametypeId then hp.seatNo From 5c0e4cb0c2b623effbd8d91d6191d69ca9f8ab8d Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Thu, 25 Feb 2010 20:28:41 -0500 Subject: [PATCH 09/10] Use correct dirs for database and log. --- pyfpdb/Configuration.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyfpdb/Configuration.py b/pyfpdb/Configuration.py index d87014e6..d0f81a1b 100755 --- a/pyfpdb/Configuration.py +++ b/pyfpdb/Configuration.py @@ -470,7 +470,8 @@ class Config: self.file = file self.dir_self = get_exec_path() - self.dir_config = os.path.dirname(self.file) +# self.dir_config = os.path.dirname(self.file) + self.dir_config = get_default_config_path() self.dir_log = os.path.join(self.dir_config, 'log') self.dir_database = os.path.join(self.dir_config, 'database') self.log_file = os.path.join(self.dir_log, 'fpdb-log.txt') From aca5682daf4fe6a4402ef47592c77a01b3c7ae28 Mon Sep 17 00:00:00 2001 From: Eratosthenes Date: Thu, 25 Feb 2010 21:32:49 -0500 Subject: [PATCH 10/10] Get rid of erroneous error message. --- pyfpdb/XTables.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyfpdb/XTables.py b/pyfpdb/XTables.py index a14debc1..28737002 100644 --- a/pyfpdb/XTables.py +++ b/pyfpdb/XTables.py @@ -89,7 +89,6 @@ class Table(Table_Window): # break if window_number is None: - print "Window %s not found. Skipping." % search_string return None # my_geo = self.window.get_geometry()