2008-08-04 05:44:28 +02:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
|
|
|
#Copyright 2008 Steffen Jobbagy-Felso
|
|
|
|
#This program is free software: you can redistribute it and/or modify
|
|
|
|
#it under the terms of the GNU Affero General Public License as published by
|
|
|
|
#the Free Software Foundation, version 3 of the License.
|
|
|
|
#
|
|
|
|
#This program is distributed in the hope that it will be useful,
|
|
|
|
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
#GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
#You should have received a copy of the GNU Affero General Public License
|
|
|
|
#along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#In the "official" distribution you can find the license in
|
|
|
|
#agpl-3.0.txt in the docs folder of the package.
|
|
|
|
|
|
|
|
import os
|
2008-10-07 19:41:06 +02:00
|
|
|
import re
|
2009-06-07 21:07:18 +02:00
|
|
|
import sys
|
2009-07-14 01:04:10 +02:00
|
|
|
import logging
|
2009-06-07 23:21:58 +02:00
|
|
|
from time import time, strftime
|
2009-06-07 21:07:18 +02:00
|
|
|
|
2008-08-04 05:44:28 +02:00
|
|
|
import fpdb_simple
|
2008-10-07 11:33:37 +02:00
|
|
|
import FpdbSQLQueries
|
2008-08-04 05:44:28 +02:00
|
|
|
|
|
|
|
class fpdb_db:
|
2009-07-14 01:04:10 +02:00
|
|
|
MYSQL_INNODB = 2
|
|
|
|
PGSQL = 3
|
|
|
|
SQLITE = 4
|
2008-12-06 13:40:04 +01:00
|
|
|
def __init__(self):
|
|
|
|
"""Simple constructor, doesnt really do anything"""
|
2009-03-17 01:52:50 +01:00
|
|
|
self.db = None
|
|
|
|
self.cursor = None
|
|
|
|
self.sql = {}
|
2008-12-06 13:40:04 +01:00
|
|
|
#end def __init__
|
2008-12-18 00:03:17 +01:00
|
|
|
|
|
|
|
def do_connect(self, config=None):
|
|
|
|
"""Connects a database using information in config"""
|
|
|
|
if config is None:
|
|
|
|
raise FpdbError('Configuration not defined')
|
|
|
|
|
|
|
|
self.settings = {}
|
2009-03-17 01:52:50 +01:00
|
|
|
self.settings['os'] = "linuxmac" if os.name != "nt" else "windows"
|
2008-12-18 00:03:17 +01:00
|
|
|
|
2009-07-14 01:04:10 +02:00
|
|
|
db = config.get_db_parameters()
|
|
|
|
self.connect(backend=db['db-backend'],
|
|
|
|
host=db['db-host'],
|
|
|
|
database=db['db-databaseName'],
|
|
|
|
user=db['db-user'],
|
|
|
|
password=db['db-password'])
|
2008-12-18 00:03:17 +01:00
|
|
|
#end def do_connect
|
2008-12-06 13:40:04 +01:00
|
|
|
|
2008-12-06 14:07:37 +01:00
|
|
|
def connect(self, backend=None, host=None, database=None,
|
|
|
|
user=None, password=None):
|
2008-12-06 13:40:04 +01:00
|
|
|
"""Connects a database with the given parameters"""
|
2008-12-06 14:07:37 +01:00
|
|
|
if backend is None:
|
|
|
|
raise FpdbError('Database backend not defined')
|
2008-12-06 13:40:04 +01:00
|
|
|
self.backend=backend
|
|
|
|
self.host=host
|
|
|
|
self.user=user
|
|
|
|
self.password=password
|
2008-12-06 14:07:37 +01:00
|
|
|
self.database=database
|
2009-07-14 01:04:10 +02:00
|
|
|
if backend==fpdb_db.MYSQL_INNODB:
|
2008-12-06 13:40:04 +01:00
|
|
|
import MySQLdb
|
2009-05-21 19:02:42 +02:00
|
|
|
try:
|
2009-08-06 08:11:26 +02:00
|
|
|
self.db = MySQLdb.connect(host = host, user = user, passwd = password, db = database, use_unicode=True)
|
2009-05-21 19:02:42 +02:00
|
|
|
except:
|
|
|
|
raise fpdb_simple.FpdbError("MySQL connection failed")
|
2009-07-14 01:04:10 +02:00
|
|
|
elif backend==fpdb_db.PGSQL:
|
2008-12-06 13:40:04 +01:00
|
|
|
import psycopg2
|
2009-06-01 03:25:36 +02:00
|
|
|
import psycopg2.extensions
|
2009-05-07 22:24:06 +02:00
|
|
|
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
2008-12-06 14:07:37 +01:00
|
|
|
# If DB connection is made over TCP, then the variables
|
|
|
|
# host, user and password are required
|
|
|
|
# For local domain-socket connections, only DB name is
|
|
|
|
# needed, and everything else is in fact undefined and/or
|
|
|
|
# flat out wrong
|
2009-06-09 22:38:30 +02:00
|
|
|
# sqlcoder: This database only connect failed in my windows setup??
|
|
|
|
# Modifed it to try the 4 parameter style if the first connect fails - does this work everywhere?
|
|
|
|
connected = False
|
2009-06-02 16:59:54 +02:00
|
|
|
if self.host == "localhost" or self.host == "127.0.0.1":
|
2009-06-09 22:38:30 +02:00
|
|
|
try:
|
|
|
|
self.db = psycopg2.connect(database = database)
|
|
|
|
connected = True
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
#msg = "PostgreSQL direct connection to database (%s) failed, trying with user ..." % (database,)
|
|
|
|
#print msg
|
|
|
|
#raise fpdb_simple.FpdbError(msg)
|
|
|
|
if not connected:
|
|
|
|
try:
|
|
|
|
self.db = psycopg2.connect(host = host,
|
|
|
|
user = user,
|
|
|
|
password = password,
|
|
|
|
database = database)
|
|
|
|
except:
|
|
|
|
msg = "PostgreSQL connection to database (%s) user (%s) failed." % (database, user)
|
|
|
|
print msg
|
|
|
|
raise fpdb_simple.FpdbError(msg)
|
2009-07-14 01:04:10 +02:00
|
|
|
elif backend==fpdb_db.SQLITE:
|
2009-07-15 01:14:25 +02:00
|
|
|
logging.info("Connecting to SQLite:%(database)s" % {'database':database})
|
2009-07-14 01:04:10 +02:00
|
|
|
import sqlite3
|
|
|
|
self.db = sqlite3.connect(database,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")
|
|
|
|
|
2008-12-06 13:40:04 +01:00
|
|
|
else:
|
|
|
|
raise fpdb_simple.FpdbError("unrecognised database backend:"+backend)
|
|
|
|
self.cursor=self.db.cursor()
|
|
|
|
# Set up query dictionary as early in the connection process as we can.
|
|
|
|
self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())
|
2009-07-14 01:04:10 +02:00
|
|
|
self.cursor.execute(self.sql.query['set tx level'])
|
2008-12-06 13:40:04 +01:00
|
|
|
self.wrongDbVersion=False
|
|
|
|
try:
|
|
|
|
self.cursor.execute("SELECT * FROM Settings")
|
|
|
|
settings=self.cursor.fetchone()
|
2009-06-07 21:07:18 +02:00
|
|
|
if settings[0]!=118:
|
2008-12-06 13:40:04 +01:00
|
|
|
print "outdated or too new database version - please recreate tables"
|
|
|
|
self.wrongDbVersion=True
|
|
|
|
except:# _mysql_exceptions.ProgrammingError:
|
|
|
|
print "failed to read settings table - please recreate tables"
|
|
|
|
self.wrongDbVersion=True
|
|
|
|
#end def connect
|
2008-08-04 05:44:28 +02:00
|
|
|
|
2008-12-06 13:40:04 +01:00
|
|
|
def disconnect(self, due_to_error=False):
|
|
|
|
"""Disconnects the DB"""
|
|
|
|
if due_to_error:
|
|
|
|
self.db.rollback()
|
|
|
|
else:
|
|
|
|
self.db.commit()
|
|
|
|
self.cursor.close()
|
|
|
|
self.db.close()
|
|
|
|
#end def disconnect
|
|
|
|
|
|
|
|
def reconnect(self, due_to_error=False):
|
|
|
|
"""Reconnects the DB"""
|
|
|
|
#print "started fpdb_db.reconnect"
|
|
|
|
self.disconnect(due_to_error)
|
|
|
|
self.connect(self.backend, self.host, self.database, self.user, self.password)
|
|
|
|
|
|
|
|
def get_backend_name(self):
|
|
|
|
"""Returns the name of the currently used backend"""
|
|
|
|
if self.backend==2:
|
|
|
|
return "MySQL InnoDB"
|
|
|
|
elif self.backend==3:
|
|
|
|
return "PostgreSQL"
|
2009-07-14 01:04:10 +02:00
|
|
|
elif self.backend==4:
|
|
|
|
return "SQLite"
|
2008-12-06 13:40:04 +01:00
|
|
|
else:
|
|
|
|
raise fpdb_simple.FpdbError("invalid backend")
|
|
|
|
#end def get_backend_name
|
|
|
|
|
|
|
|
def get_db_info(self):
|
|
|
|
return (self.host, self.database, self.user, self.password)
|
|
|
|
#end def get_db_info
|
2009-06-07 21:45:09 +02:00
|
|
|
|
2009-08-04 22:48:03 +02:00
|
|
|
def getLastInsertId(self, cursor=None):
|
2009-07-26 02:42:09 +02:00
|
|
|
try:
|
|
|
|
if self.backend == self.MYSQL_INNODB:
|
|
|
|
ret = self.db.insert_id()
|
|
|
|
if ret < 1 or ret > 999999999:
|
|
|
|
print "getLastInsertId(): problem fetching insert_id? ret=", ret
|
|
|
|
ret = -1
|
|
|
|
elif self.backend == self.PGSQL:
|
|
|
|
# some options:
|
|
|
|
# currval(hands_id_seq) - use name of implicit seq here
|
|
|
|
# lastval() - still needs sequences set up?
|
|
|
|
# insert ... returning is useful syntax (but postgres specific?)
|
|
|
|
# see rules (fancy trigger type things)
|
|
|
|
c = self.db.cursor()
|
|
|
|
ret = c.execute ("SELECT lastval()")
|
|
|
|
row = c.fetchone()
|
|
|
|
if not row:
|
|
|
|
print "getLastInsertId(%s): problem fetching lastval? row=" % seq, row
|
|
|
|
ret = -1
|
|
|
|
else:
|
|
|
|
ret = row[0]
|
|
|
|
elif self.backend == fpdb_db.SQLITE:
|
2009-08-04 22:48:03 +02:00
|
|
|
ret = cursor.lastrowid
|
2009-06-20 00:22:57 +02:00
|
|
|
else:
|
2009-07-26 02:42:09 +02:00
|
|
|
print "getLastInsertId(): unknown backend ", self.backend
|
|
|
|
ret = -1
|
|
|
|
except:
|
2009-06-20 00:22:57 +02:00
|
|
|
ret = -1
|
2009-07-26 02:42:09 +02:00
|
|
|
print "getLastInsertId error:", str(sys.exc_value), " ret =", ret
|
|
|
|
raise fpdb_simple.FpdbError( "getLastInsertId error: " + str(sys.exc_value) )
|
|
|
|
|
2009-06-20 00:22:57 +02:00
|
|
|
return ret
|
2009-06-08 12:19:55 +02:00
|
|
|
|
|
|
|
def storeHand(self, p):
|
|
|
|
#stores into table hands:
|
2009-07-14 01:04:10 +02:00
|
|
|
self.cursor.execute ("""INSERT INTO Hands (
|
|
|
|
tablename,
|
|
|
|
sitehandno,
|
|
|
|
gametypeid,
|
|
|
|
handstart,
|
|
|
|
importtime,
|
|
|
|
seats,
|
|
|
|
maxseats,
|
|
|
|
boardcard1,
|
|
|
|
boardcard2,
|
|
|
|
boardcard3,
|
|
|
|
boardcard4,
|
|
|
|
boardcard5,
|
|
|
|
-- texture,
|
|
|
|
playersVpi,
|
|
|
|
playersAtStreet1,
|
|
|
|
playersAtStreet2,
|
|
|
|
playersAtStreet3,
|
|
|
|
playersAtStreet4,
|
|
|
|
playersAtShowdown,
|
|
|
|
street0Raises,
|
|
|
|
street1Raises,
|
|
|
|
street2Raises,
|
|
|
|
street3Raises,
|
|
|
|
street4Raises,
|
|
|
|
-- street1Pot,
|
|
|
|
-- street2Pot,
|
|
|
|
-- street3Pot,
|
|
|
|
-- street4Pot,
|
|
|
|
-- showdownPot
|
2009-06-08 12:19:55 +02:00
|
|
|
)
|
|
|
|
VALUES
|
2009-07-14 01:04:10 +02:00
|
|
|
(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
|
|
|
|
%s, %s, %s, %s, %s, %s, %s)""",
|
|
|
|
(
|
|
|
|
p['tablename'],
|
|
|
|
p['sitehandno'],
|
|
|
|
p['gametypeid'],
|
|
|
|
p['handStart'],
|
|
|
|
datetime.datetime.today(),
|
|
|
|
len(p['names']),
|
|
|
|
p['maxSeats'],
|
|
|
|
p['boardcard1'],
|
|
|
|
p['boardcard2'],
|
|
|
|
p['boardcard3'],
|
|
|
|
p['boardcard4'],
|
|
|
|
p['boardcard5'],
|
|
|
|
hudCache['playersVpi'],
|
|
|
|
hudCache['playersAtStreet1'],
|
|
|
|
hudCache['playersAtStreet2'],
|
|
|
|
hudCache['playersAtStreet3'],
|
|
|
|
hudCache['playersAtStreet4'],
|
|
|
|
hudCache['playersAtShowdown'],
|
|
|
|
hudCache['street0Raises'],
|
|
|
|
hudCache['street1Raises'],
|
|
|
|
hudCache['street2Raises'],
|
|
|
|
hudCache['street3Raises'],
|
|
|
|
hudCache['street4Raises'],
|
|
|
|
hudCache['street1Pot'],
|
|
|
|
hudCache['street2Pot'],
|
|
|
|
hudCache['street3Pot'],
|
|
|
|
hudCache['street4Pot'],
|
|
|
|
hudCache['showdownPot']
|
|
|
|
)
|
|
|
|
)
|
2009-06-08 12:19:55 +02:00
|
|
|
#return getLastInsertId(backend, conn, cursor)
|
2009-06-07 21:07:18 +02:00
|
|
|
#end class fpdb_db
|