Viewing file: Odbc.py (8.95 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# Warning: This ODBC driver ships with win32all
def _connect(keywords): # Create an ODBC connection string (probably Windows specific) # data source/username/password conn_str = keywords['dsn'] if keywords.get('user'): conn_str += '/' + keywords['user'] if keywords.get('password'): conn_str += '/' + keywords['password'] return odbc.odbc(conn_str)
import sys
# -- RDF support ----------------------------------------------------
from Ft.Rdf import Model
SYSTEM_MODEL_NAME = 'system' USER_MODEL_NAME = 'user'
def BuildDbiKeywords(properties): # Creates a DBI 2.0 keyword dictionary for connection # dsn Data source name as string # user Username as string (opt) # password Password as string (opt) # host Hostname (opt) # database Database name (opt) conn = {'dsn' : properties['DataSource']}
if properties.get('User'): conn['user'] = properties['User'] if properties.get('Password'): conn['password'] = properties['Password']
if properties.get('Host'): conn['host'] = properties['Host']
if properties.get('Database'): conn['database'] = properties['Database']
return conn
# -- Database interface ---------------------------------------------
def InitializeModule(): """ Post-import hook to initialize module's runtime variables that are not required at import time, but will be needed before the module-level functions are called. """ global odbc global RdfDriver
# Load the required database interface module import odbc
# Incorporate the RDF driver module from Ft.Rdf.Drivers import Memory as RdfDriver RdfDriver.InitializeModule() return
def Exists(properties): """ See if this repo exists. The return value for this is three states: 1 Everything is present, 0 Some things are there, or -1 Nothing is there. """ conn = _connect(BuildDbiKeywords(properties)) cursor = conn.cursor() exists = -1 try: for table in ('ftss_strings', 'ftss_stringdata', 'ftss_sequences'): # This should return a list of tuples cursor.execute('SELECT COUNT(*) FROM %s' % table) if cursor.fetchall(): exists = 0 except: pass else: # No exceptions means all tables where successfully created exists = 1 cursor.close() conn.rollback() conn.close() return exists
def Initialize(properties): """Initialize a new copy of the repo. This is not the same as a 4ss_manager init. This is very raw. The adapter will take care of calling our other interfaces (createContainer, createUser, etc) with all of the information about the rest of the 'init' stuff to do """ keywords = BuildDbiKeywords(properties) RdfDriver.CreateDb(keywords, SYSTEM_MODEL_NAME) RdfDriver.CreateDb(keywords, USER_MODEL_NAME)
conn = _connect(keywords) cursor = conn.cursor() cursor.execute('CREATE TABLE ftss_strings (sid integer, path varchar, type integer)') cursor.execute('CREATE TABLE ftss_stringdata (sid integer, chunk integer, data varchar)') cursor.execute('CREATE TABLE ftss_sequences (name varchar, position integer)') cursor.execute("INSERT INTO ftss_sequences VALUES ('string_id', 1)") cursor.close() conn.commit() conn.close() return
def Destroy(properties,tryOnly=0): """Completly destroy the repo"""
keywords = BuildDbiKeywords(properties) RdfDriver.DestroyDb(keywords, SYSTEM_MODEL_NAME) RdfDriver.DestroyDb(keywords, USER_MODEL_NAME)
conn = _connect(keywords) cursor = conn.cursor()
for table_name in ['ftss_strings', 'ftss_stringdata', 'ftss_sequences', ]: try: cursor.execute('DROP TABLE %s' % table_name) except: sys.stderr.write("Unable to drop table %s\n" % table_name); cursor.close() conn.commit() conn.close() return
def Begin(**properties): """Begin a new transaction. Every driver must support this interface. The properties keyword arguments are passed from the config file (or where ever) to the driver. The Begin file is responsible for doing what ever is needed to validate these arguements """ keywords = BuildDbiKeywords(properties) return OdbcDriver(keywords)
class OdbcDriver: """Store information via an ODBC connection to a database"""
def __init__(self, keywords): self._keywords = keywords self._conn = _connect(keywords) self._cursor = self._conn.cursor()
# Create the system model rdf_db = RdfDriver.DbAdapter({}, SYSTEM_MODEL_NAME) rdf_db._db = self._cursor self._systemRdfModel = Model.Model(rdf_db)
# Create the user model rdf_db = RdfDriver.DbAdapter({}, USER_MODEL_NAME) rdf_db._db = self._cursor self._userRdfModel = Model.Model(rdf_db) return
def _getId(self, path, type): self._cursor.execute("SELECT sid FROM ftss_strings " "WHERE path='%s' and type=%d" % (path, type)) result = self._cursor.fetchall() if result: return int(result[0][0]) return 0
def _writeString(self, sid, content): """ Convert a large string into manageable chunks fro the database. """ chunks = Split(content)
# Remove the old data (a no-op if it doesn't exist) self._cursor.execute("DELETE FROM ftss_stringdata where sid=%d" % sid)
# Add the new data inputs = map(lambda pos, chunk, sid=sid: (sid, pos, chunk), range(len(chunks)), chunks) self._cursor.execute("INSERT INTO ftss_stringdata VALUES(?,?,?)", inputs) return
def createFile(self, path, type, content): """ When creating a resource, store the content """ self._cursor.execute("SELECT position FROM ftss_sequences " "WHERE name='string_id'") sid = self._cursor.fetchall()[0][0] self._cursor.execute("UPDATE ftss_sequences SET position=%d " "WHERE name='string_id'" % (sid + 1)) self._writeString(sid, content) self._cursor.execute("INSERT INTO ftss_strings VALUES (%d, '%s', %d)" % (sid, path, type)) return
def hasFile(self, path, type): """See if we have any meta information about this resource""" sid = self._getId(path, type) # Force a boolean value return not not sid
def fetchFile(self, path, type): sid = self._getId(path, type) if not sid: return None
self._cursor.execute("SELECT data FROM ftss_stringdata WHERE sid=%d " "ORDER BY chunk" % sid) chunks = self._cursor.fetchall() if chunks: print chunks data = Join(chunks) print 'path',path print repr(data) else: data = None return data
def updateFile(self, path, type, content): """Update only the content about this resource""" sid = self._getId(path, type) if not sid: return None self._writeString(sid, content) return
def deleteFile(self, path, type): """Delete an object""" sid = self._getId(path, type) if not sid: return None self._cursor.execute("DELETE FROM ftss_stringdata WHERE sid=%d" % sid) self._cursor.execute("DELETE FROM ftss_strings WHERE sid=%d" % sid) return def getSystemModel(self): return self._systemRdfModel
def getUserModel(self): return self._userRdfModel
def commit(self): """Make it so!""" self._cursor.close() self._conn.commit() self._conn.close() self._systemRdfModel = None self._userRdfModel = None return
def rollback(self): """Undo it""" self._cursor.close() self._conn.rollback() self._conn.close() self._systemRdfModel = None self._userRdfModel = None return
# -- Large file support -----------------------------------
import base64 BLOB_CHUNK_LENGTH = 7900
def Split(content): data = base64.encodestring(content.encode('utf-8'))
chunks = [] index = 0 while (len(data) - index) > BLOB_CHUNK_LENGTH: chunks.append(data[index:index+BLOB_CHUNK_LENGTH]) index = index + BLOB_CHUNK_LENGTH chunks.append(data[index:]) print chunks return chunks
def Join(chunks): return unicode(base64.decodestring(''.join(map(lambda x:x[0],chunks))),'utf-8')
#try: # # use the C-optimized versions, if available # from Postgres import EscapeAndSplitc # Split = EscapeAndSplitc.split # Join = EscapeAndSplitc.join #except ImportError: # pass
NAME='Odbc'
|