Mercurial > hg > ZDBInterface
changeset 3:d70e57193731
new executeZSQL method that returns Zope Results.
new ZDBInterfaceFolder that doesn't do much yet.
author | casties |
---|---|
date | Mon, 14 Feb 2011 23:20:43 +0100 |
parents | 881fcea6a57d |
children | 0ade331198de |
files | DBInterface.py RestDbInterface.py ZDBInterfaceFolder.py __init__.py zpt/addZDBInterfaceFolder.zpt zpt/editRestDbInterface.zpt zpt/editZDBInterfaceFolder.zpt |
diffstat | 7 files changed, 166 insertions(+), 133 deletions(-) [+] |
line wrap: on
line diff
--- a/DBInterface.py Mon Feb 14 11:11:34 2011 +0100 +++ b/DBInterface.py Mon Feb 14 23:20:43 2011 +0100 @@ -12,6 +12,7 @@ psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY) from Products.ZSQLMethods.SQL import SQLConnectionIDs +from Shared.DC.ZRDB.Results import Results def unicodify(s,alternate='latin-1'): @@ -65,46 +66,80 @@ return s -class DbInterface: - """Object for database queries - """ - def __init__(self, id, title, connection_id=None): +class DBInterface: + """Object for database queries""" + + def __init__(self, connection_id=None): """init""" - self.id = id - self.title = title # database connection id self.connection_id = connection_id + def getConnectionIDs(self): + """return list of available connection ids""" + return SQLConnectionIDs(self) + + def getDB(self): + """returns DB object""" + # TODO: can we cache and reuse a DB object? + if self.connection_id is None: + # try to take the first existing ID + connids = self.getConnectionIDs() + if len(connids) > 0: + connection_id = connids[0][1] + self.connection_id = connection_id + logging.debug("connection_id: %s"%repr(connection_id)) + + # get Connection instance + con = getattr(self, self.connection_id) + # call to get db object + db = con() + return db + + def executeZSQL(self, query, args=None, max_rows=None): + """execute query with args on the database and return all results as Result object.""" + logging.debug("executeZSQL query=%s args=%s"%(query,args)) + dbc = self.getDB() + res = dbc.query(query, max_rows=max_rows, query_data=args) + # return result set as Result object with Brains + return Results(res) + + + # + # Old way using cursor from DA + # + def getCursor(self,autocommit=True): """returns fresh DB cursor""" - conn = getattr(self,"_v_database_connection",None) + conn = getattr(self,"_v_database_connection", None) if conn is None: # create a new connection object try: if self.connection_id is None: # try to take the first existing ID - connids = SQLConnectionIDs(self) + connids = self.getConnectionIDs() if len(connids) > 0: - connection_id = connids[0][0] + connection_id = connids[0][1] self.connection_id = connection_id logging.debug("connection_id: %s"%repr(connection_id)) da = getattr(self, self.connection_id) + logging.debug('da=%s'%da) da.connect('') # we copy the DAs database connection conn = da._v_database_connection - #conn._register() # register with the Zope transaction system + #conn._register() # register with the Zope transaction system(?) self._v_database_connection = conn + except Exception, e: raise IOError("No database connection! (%s)"%str(e)) cursor = conn.getcursor() if autocommit: - # is there a better version to get to the connection? + # TODO: is there a better version to get to the connection? cursor.connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) return cursor - + def getFieldNameMap(self,fields): """returns a dict mapping field names to row indexes""" map = {}
--- a/RestDbInterface.py Mon Feb 14 11:11:34 2011 +0100 +++ b/RestDbInterface.py Mon Feb 14 23:20:43 2011 +0100 @@ -11,69 +11,15 @@ import re import json import time -import psycopg2 -# make psycopg use unicode objects -import psycopg2.extensions -psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) -psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY) from zope.interface import implements from zope.publisher.interfaces import IPublishTraverse from ZPublisher.BaseRequest import DefaultPublishTraverse - -def unicodify(s,alternate='latin-1'): - """decode str (utf-8 or latin-1 representation) into unicode object""" - if not s: - return u"" - if isinstance(s, str): - try: - return s.decode('utf-8') - except: - return s.decode(alternate) - else: - return s - -def utf8ify(s): - """encode unicode object or string into byte string in utf-8 representation. - assumes string objects to be utf-8""" - if not s: - return "" - if isinstance(s, str): - return s - else: - return s.encode('utf-8') - -def getTextFromNode(node): - """get the cdata content of a XML node""" - if node is None: - return "" - - if isinstance(node, list): - nodelist = node - else: - nodelist=node.childNodes - - rc = "" - for node in nodelist: - if node.nodeType == node.TEXT_NODE: - rc = rc + node.data - return rc - -def sqlName(s,lc=True): - """returns restricted ASCII-only version of string""" - if s is None: - return "" - - # all else -> "_" - s = re.sub(r'[^A-Za-z0-9_]','_',s) - if lc: - return s.lower() - - return s +from DBInterface import * -class RestDbInterface(Folder): +class RestDbInterface(DBInterface, Folder): """Object for RESTful database queries path schema: /db/{schema}/{table}/ omitting table gives a list of schemas @@ -81,7 +27,7 @@ """ implements(IPublishTraverse) - meta_type="RESTdb" + meta_type="RESTdb2" manage_options=Folder.manage_options+( {'label':'Config','action':'manage_editRestDbInterfaceForm'}, ) @@ -134,69 +80,6 @@ """returns a JSON formatted string from object""" return json.dumps(object) - def getCursor(self,autocommit=True): - """returns fresh DB cursor""" - conn = getattr(self,"_v_database_connection",None) - if conn is None: - # create a new connection object - try: - if self.connection_id is None: - # try to take the first existing ID - connids = SQLConnectionIDs(self) - if len(connids) > 0: - connection_id = connids[0][0] - self.connection_id = connection_id - logging.debug("connection_id: %s"%repr(connection_id)) - - da = getattr(self, self.connection_id) - da.connect('') - # we copy the DAs database connection - conn = da._v_database_connection - #conn._register() # register with the Zope transaction system - self._v_database_connection = conn - except Exception, e: - raise IOError("No database connection! (%s)"%str(e)) - - cursor = conn.getcursor() - if autocommit: - # is there a better version to get to the connection? - cursor.connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) - - return cursor - - def getFieldNameMap(self,fields): - """returns a dict mapping field names to row indexes""" - map = {} - i = 0 - for f in fields: - map[f[0]] = i - i += 1 - - return map - - def executeSQL(self, query, args=None, hasResult=True, autocommit=True): - """execute query with args on database and return all results. - result format: {"fields":fields, "rows":data}""" - logging.debug("executeSQL query=%s args=%s"%(query,args)) - cur = self.getCursor(autocommit=autocommit) - if args is not None: - # make sure args is a list - if isinstance(args,basestring): - args = (args,) - - cur.execute(query, args) - # description of returned fields - fields = cur.description - if hasResult: - # get all data in an array - data = cur.fetchall() - cur.close() - #logging.debug("fields: %s"%repr(fields)) - #logging.debug("rows: %s"%repr(data)) - return {"fields":fields, "rows":data} - else: - cur.close() - return None def isAllowed(self,action,schema,table,user=None): """returns if the requested action on the table is allowed""" @@ -240,7 +123,6 @@ # continue traversing return self - def index_html(self,REQUEST,RESPONSE): """index method""" # ReST path was stored in request
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ZDBInterfaceFolder.py Mon Feb 14 23:20:43 2011 +0100 @@ -0,0 +1,65 @@ +''' +Created on 14.2.2011 + +@author: casties +''' + +from OFS.Folder import Folder +from Products.PageTemplates.PageTemplateFile import PageTemplateFile +from AccessControl import getSecurityManager, Unauthorized +import logging +import re + +from DBInterface import * + + +class ZDBInterfaceFolder(DBInterface, Folder): + """Folder for database queries + """ + + meta_type="ZDBInterfaceFolder" + manage_options=Folder.manage_options+( + {'label':'Config','action':'manage_editZDBInterfaceFolderForm'}, + ) + + # management templates + manage_editZDBInterfaceFolderForm=PageTemplateFile('zpt/editZDBInterfaceFolder',globals()) + + + def __init__(self, id, title, connection_id=None): + """init""" + self.id = id + self.title = title + # database connection id + self.connection_id = connection_id + + + + def manage_editZDBInterfaceFolder(self, title=None, connection_id=None, + REQUEST=None): + """Change the object""" + if title is not None: + self.title = title + + if connection_id is not None: + self.connection_id = connection_id + + #checkPermission=getSecurityManager().checkPermission + REQUEST.RESPONSE.redirect('manage_main') + + +manage_addZDBInterfaceFolderForm=PageTemplateFile('zpt/addZDBInterfaceFolder',globals()) + +def manage_addZDBInterfaceFolder(self, id, title='', label='', description='', + createPublic=0, + createUserF=0, + REQUEST=None): + """Add a new object with id *id*.""" + + ob=ZDBInterfaceFolder(str(id),title) + self._setObject(id, ob) + + #checkPermission=getSecurityManager().checkPermission + REQUEST.RESPONSE.redirect('manage_main') + +
--- a/__init__.py Mon Feb 14 11:11:34 2011 +0100 +++ b/__init__.py Mon Feb 14 23:20:43 2011 +0100 @@ -1,6 +1,7 @@ import RestDbInterface import WritableRestDbInterface +import ZDBInterfaceFolder def initialize(context): @@ -19,3 +20,11 @@ WritableRestDbInterface.manage_addWritableRestDbInterface ) ) + + context.registerClass( + ZDBInterfaceFolder.ZDBInterfaceFolder, + constructors = ( + ZDBInterfaceFolder.manage_addZDBInterfaceFolderForm, + ZDBInterfaceFolder.manage_addZDBInterfaceFolder + ) + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/zpt/addZDBInterfaceFolder.zpt Mon Feb 14 23:20:43 2011 +0100 @@ -0,0 +1,9 @@ + <div tal:replace="structure here/manage_page_header">Header</div> + <h2>Add a ZDB interface folder</h2> + <form method="post" action="manage_addZDBInterfaceFolder"> + <p class="form-label">ID</p> + <p class="form-element"><input size="80" name="id"/></p> + <p class="form-label">Title</p> + <p class="form-element"><input size="80" name="title"/></p> + <p><input type="submit" value="Add" /></p> + </form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/zpt/editRestDbInterface.zpt Mon Feb 14 23:20:43 2011 +0100 @@ -0,0 +1,16 @@ + <div tal:replace="structure here/manage_page_header">Header</div> + <h2>Edit a RESTdb</h2> + <form method="post" action="manage_editRestDbInterface"> + <p class="form-label">Title</p> + <p class="form-element"><input size="80" name="title" tal:attributes="value here/title"/></p> + <p class="form-label">Connection ID</p> + <p> + <select name="connection_id"> + <tal:block tal:repeat="id python:[i[0] for i in here.getConnectionIDs()]"> + <option tal:condition="python:getattr(here,'connection_id','')==id" tal:attributes="value id" selected tal:content="id"/> + <option tal:condition="not:python:getattr(here,'connection_id','')==id" tal:attributes="value id" tal:content="id"/> + </tal:block> + </select> + </p> + <p><input type="submit" value="Change" /></p> + </form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/zpt/editZDBInterfaceFolder.zpt Mon Feb 14 23:20:43 2011 +0100 @@ -0,0 +1,17 @@ + <div tal:replace="structure here/manage_page_header">Header</div> + <h2>Edit a ZDB interface folder</h2> + <form method="post" action="manage_editZDBInterfaceFolder"> + <p class="form-label">Title</p> + <p class="form-element"><input size="80" name="title" tal:attributes="value here/title"/></p> + <p class="form-label">Connection ID</p> + <pre tal:content="python:repr(here.getConnectionIDs())"/> + <p> + <select name="connection_id"> + <tal:block tal:repeat="id python:[i[0] for i in here.getConnectionIDs()]"> + <option tal:condition="python:getattr(here,'connection_id','')==id" tal:attributes="value id" selected tal:content="id"/> + <option tal:condition="not:python:getattr(here,'connection_id','')==id" tal:attributes="value id" tal:content="id"/> + </tal:block> + </select> + </p> + <p><input type="submit" value="Change" /></p> + </form>