# -*- coding: utf8 -*-
'''DB MODULE - Filemaker Pro
******************************
***  DB MODULE - Filemaker Pro
******************************
$RCSfile: dbmod_odbc_filemaker.py,v $
$Revision: 875 $
$Author: markus $
$Date: 2008-04-24 02:23:32 +0200 (Do, 24. Apr 2008) $

The biocase.wrapper database module to access Filemaker Pro atabases.
You will need the mxODBC module to connect to a ODBC source.
The Filemaker ODBC driver does not seem to support parameter passing.
Therefore no real unicode can be passed and all parameters are encoded first into the PSF setting.
'''

import os
from biocase.wrapper.errorclasses         import *
from biocase.tools.various_functions     import unique
from biocase.wrapper.sql.base             import sqlBase
from biocase.wrapper.dbmod.base_dbmod   import DBBasemodule

import logging
log = logging.getLogger("pywrapper.dbmod")


#############################################
#
# CUSTOMIZATION for Filemaker
#
# OVERLOAD BASE CLASSES AND OTHER METHODS
#
#############################################

# uses inherited ANSI SQL apart from the following.
sqlBase.templates['attribute'] = '#1.#2'
sqlBase.templates['table'] = '#1'
sqlBase.templates['join'] = '#1 LEFT OUTER JOIN #2 ON #3'



# override a lot of standard routines, because filemaker has a very limited SQL syntax:
#
#     NO TABLE ALIASING supported
#
# testing if real tablenames are used twice is done in init routine (see below):

# override joinDBAttrObj method of class base.
# use the original table!
def joinDBAttrObj(self, obj):
    '''create a TABLE.ATTRIBUTE string out of a DBAttributeObject with the help of templates'''
    table = self.psfObj.tablegraph.alias2tablename[obj.table]
    return self.apply_template('attribute', [table, obj.attr])
sqlBase.joinDBAttrObj = joinDBAttrObj

# override getTableSyntax method of class select. 
# use the original table!
def getTableSyntax(self, table):
    '''returns the table as referenced in SQL excluding aliases'''
    return self.apply_template('table', [self.psfObj.tablegraph.alias2tablename.get(table, None)])
sqlSelect.getTableSyntax = getTableSyntax

        

# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
class DBmodule(DBBasemodule):
    __version__ = '0.71 using mxODBC ?'
    __dbmod__    = u'FilemakerPro module'
    

    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def __init__(self, psfObj):
        # setting the psfObj reference to self.psfObj
        # call createDBconnection method
        DBBasemodule.__init__(self, psfObj)
        # test if real tablenames are used twice, as FMP does not support aliasing:
        if len(psfObj.tablegraph.alias2tablename.values()) <> len(unique(psfObj.tablegraph.alias2tablename.values())):
            raise DbOperationNotSupportedError('table aliasing', 'Filemaker')
        #
        # read DB 8bit encoding
        #
        log.debug("8bit DB Encoding: %s"%(psfObj.encoding))
        self.conn.encoding = psfObj.encoding
        #
        # dont use parameters but integrate all parameters into SQL strings:
        self.trans.integrateParametersInSQLString()
        

    # ------------------   FUNCTION OVERLOAD OF BASE DBMOD MODULE   ------------------
    # --------------------------------------------------------------------------------
    def createDBconnection(self):
        try:
            import mx.ODBC
        except:
            raise DbModuleMissingError('mx_ODBC')
        self.__class__.__version__ = self.__class__.__version__[:-1]+mx.ODBC.__version__
        #
        # connect
        #
        # import OS specific ODBC version:
        # 'posix', 'nt', 'dos', 'mac', 'os2', 'ce', 'java', 'riscos'
        if os.name in ("nt","dos"):
            import mx.ODBC.Windows    as odbc
        elif os.name in ("unix","posix","java"):
            import mx.ODBC.unixODBC        as odbc
        else:
            raise ConnectionError(os=os.name)
        loginParas = "DSN=%s;UID=%s;PWD=%s" % (self.psfObj.database, self.psfObj.user ,self.psfObj.password )
        conn = odbc.DriverConnect( loginParas )
        conn.stringformat = odbc.NATIVE_UNICODE_STRINGFORMAT
        return conn
