#coding:utf-8

import os
import sys
import sunhpc
import sqlite3
import threading
import subprocess

threadlocal = threading.local()

class Database(object):
    """
    This class should proxy all the connection to the database.

    These two objects have two separate DB connections, which means
    that DB status can be different when queried through them.
    
    Usage Example::
      db = Database()
      db.connect()
    """

    def __init__(self):
        self.conn       = None
        self.curs       = None
        self.results    = None
        self._dbPath    = "/opt/sunhpc/data"
        self._dbFile    = "sunhpc.db"
        self._datafile   = os.path.join(self._dbPath, self._dbFile)

    def connect(self):
        """
        It start the connection to the DB and create all the internal
        data structure
        """
        self.conn = sqlite3.connect(self._datafile, isolation_level=None)
        self.curs = self.conn.cursor()

    def getSession(self):
        session = getattr(threadlocal, "session", None)

        if session:
            return session
        elif self.conn:
            session = self.curs
            setattr(threadlocal, "session", session)
            return session
        else:
            return None

    def closeSession(self):
        session = getattr(threadlocal, "session", None)
        if session:
            session.close()
            setattr(threadlocal, "session", None)

    def commit(self):
        """
        Commit the current session if it existsi. *It does not touch the
        connection.*
        """
        session = self.getSession()
        if session:
            self.conn.commit()
        else:
            pass

    def fetchone(self):
        """
        Fetch one row from the results of the previous query

        :rtype: tuple
        :return: a tuple containing the values of the fetched row.
        """
        if self.results:
            return self.results.fetchone()
        return ()
    
    def fetchall(self):
        """
        Fetch all rows from the results of the previous query

        :rtype: list
        :return: a list of tuples containing the values of the fetched rows
        """
        if self.results:
            return self.results.fetchall()
        return ()

    def execute(self, command):

        if self.conn:
            if '%' in command:
                command = command.replace('%', '%%')
            try:
                self.results = self.curs.execute(command)
            except sqlite3.OperationalError as e:
                print ('SQliteErr: ', repr(e))
                sys.exit(-1)
            #
            # lastrowid 返回插入行的id
            # rowcount  使用insert, update, delete语句,一般返回1, 
            #   其他操作, 例如select,或者创建表等操作返回-1
            # 如果需要给execute方法传递参数,则有几个?占位符,就必须对应几个参数,
            # 例如: 
            #   cursor.execute('select * from user where name=? and pwd=?', ('abc', 'password'))
            #
            # print ('lastrowid: ', self.results.lastrowid)
            # print ('rowcount : ', self.results.rowcount)
            # lastrowid: 0
            # rowcount : -1
            # bool     : (-1, 1, 2, )-> True, (0,None)-> False
            return self.results.rowcount
        else:
            return None

    def close(self):
        if self.results:
            self.results.close()
            self.results = None
        if self.conn:
            self.conn.close()

    def closeSession(self):
        session = getattr(threadlocal, 'session', None)
        if session:
            session.close()
            setattr(threadlocal, 'session', None)

    def test(self):
        qry = 'create table userb (id varchar(20) primary key, name varchar(20))'
        self.execute(qry)

        # insert
        #qry = 'insert into user (id, name) values ("5", "Michael")'
        #row = self.execute(qry)
        #print ('row: ', row)

        '''
        qry = 'select * from usera'
        self.execute(qry)
        data = self.fetchall()
        print ('data: ', data)
        '''


if __name__ == "__main__":
    d = Database()
    d.connect()

    d.test()













