123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- """
- demeter database
- name:__base__.py
- author:rabin
- """
- import os
- import uuid
- import short_url
- import json
- import traceback
- import re
- import math
- from demeter.core import *
- class Model(object):
- __table__ = ''
- __comment__ = ''
- def __init__(self, type, db, config):
- self.db = db
- self._type = type
- self._config = config
- self._table = self._config['prefix'] + '_' + self.__table__
- self._set = ''
- self._bind = {}
- self._attr = {}
- self._key = {}
- self.create()
- def cur(self):
- return self.db.cursor()
- def query(self, sql, method='select', fetch='fetchall'):
- cur = self.cur()
- bind = []
- if self._set:
- for key in self._set:
- self.check(key, self._set[key], self._attr[key])
- if self._set[key] == 'time':
- self._set[key] = self.time()
- elif self._set[key] == 'True':
- self._set[key] = True
- elif self._set[key] == 'False':
- self._set[key] = False
- elif 'date' in key and type(self._set[key]) != int:
- self._set[key] = self.mktime(self._set[key])
- elif self._attr[key].md5:
- self._set[key] = self.createMd5(self._set[key])
- bind.append(self._set[key])
- for value in self._key:
- if value[0] in self._bind and self._bind[value[0]] != None:
- val = self._bind[value[0]]
- if method == 'insert':
- self.check(value[0], val, self._attr[value[0]])
- self._attr[value[0]].unset()
- if type(val) == list and val:
- for i in val:
- bind.append(i)
- else:
- bind.append(val)
- if method == 'select' and ';' in sql:
- temp = sql.split(';')
- sql = temp[1]
- totalSql = temp[0]
- cur.execute(totalSql, bind)
- Demeter.config['page']['totalNum'] = self.fetch(cur, 'fetchone', 'count')
- Demeter.config['page']['total'] = int(math.ceil(round(float(Demeter.config['page']['totalNum'])/float(Demeter.config['page']['num']),2)))
- cur.execute(sql, bind)
- if method == 'select':
- return self.fetch(cur, fetch)
- id = True
- if method == 'insert':
- id = cur.fetchone()[0]
- self.db.commit()
- self._set = {}
- return id
- """
- try:
-
- except Exception, e:
- print e.message
- os._exit(0)
- """
- def fetch(self, cur, type, method = ''):
- load = getattr(cur, type)
- rows = load()
- if type == 'fetchall':
- result = []
- if rows:
- for key in rows:
- row = {}
- i = 0
- for v in key:
- row[self._key[i][0]] = v
- i = i + 1
- result.append(row)
- elif method == 'count':
- return rows[0]
- else:
- result = {}
- i = 0
- if rows:
- for key in rows:
- if not key:
- key = ''
- result[self._key[i][0]] = key
- i = i + 1
- return result
- def attr(self, method):
- fields = vars(self.__class__)
- self._attr = {}
- self._bind = {}
- self._key = {}
- col = (int, str, long, float, unicode, bool, uuid.UUID)
- for field in fields:
- if isinstance(fields[field], Fields):
- self._attr[field] = fields[field]
- self._key[field] = self._attr[field].getKey()
- insert = (method == 'insert')
- update = (insert or method == 'update')
- if insert and self._attr[field].uuid:
- self.setUuid(field, col)
- bind = False
- val = self._attr[field].getArgv()
- if val or val == False:
- bind = True
- else:
- val = getattr(self, field)
- if isinstance(val, col):
- setattr(self, field, self._attr[field])
- bind = True
- elif insert and self._attr[field].default:
- val = self._attr[field].default
- bind = True
- if val == 'time':
- val = self.time()
- elif '.' in val:
- temp = val.split('.')
- val = Demeter.config[temp[0]][temp[1]]
- elif method == 'select' and self._attr[field].default and field == 'state':
- val = self._attr[field].default
- bind = True
- if bind and val != None:
- if type(val) == list:
- length = len(val)
- if length <= 1:
- val = val[0]
- if insert and self._attr[field].md5:
- val = self.createMd5(val)
- if self._attr[field].type == 'boolean' and isinstance(val, (str, unicode)):
- val = Demeter.bool(val)
- if type(val) == list:
- val = tuple(val)
- self._bind[field] = val
- self._attr[field].val(self._bind[field])
- self._attr[field].bind('%s')
- self._key = sorted(self._key.items(), key=lambda d:d[1], reverse = False)
- Counter().unset()
- def check(self, field, val, attr):
- if val == 'undefined':
- self.error(error)
- if attr.match == 'not':
- if not val:
- self.error(field + ' not exists')
- elif attr.match:
- if '|' in attr.match:
- temp = attr.match.split('|')
- match = temp[0]
- error = temp[1]
- else:
- match = attr.match
- error = field + ' not match:' + match
- if hasattr(Check, match):
- method = getattr(Check, match)
- result = method(val)
- else:
- result = re.search(match, val)
- if not result:
- self.error(error)
- def error(self, msg):
- for value in self._key:
- if value[0] in self._bind and self._bind[value[0]] != None:
- self._attr[value[0]].unset()
- self._set = {}
- Demeter.error(msg)
- def time(self):
- return Demeter.time()
- def mktime(self, value):
- return Demeter.mktime(value)
- def setUuid(self, field, col):
- id = getattr(self, self._attr[field].uuid)
- if isinstance(id, col):
- system = short_url.encode_url(id)
- else:
- system = self._attr[field].uuid
- name = system + '.' + self.__table__
- result = uuid.uuid5(uuid.uuid1(), name)
- result = str(result)
- setattr(self, field, result)
- def createMd5(self, value):
- return Demeter.md5(value, salt=True)
- def createState(self):
- if 'create' in self._config:
- create = Demeter.bool(self._config['create'])
- if create:
- return Demeter.runtime(self._type, self.__table__, json.dumps(self._key))
- return False
- def drop(self):
- return self.handle('drop')
- def create(self):
- return self.handle('create')
- def insert(self):
- return self.handle('insert')
- def update(self, *args, **kwargs):
- if args:
- self._set = args[0]
- else:
- self._set = kwargs
- return self.handle('update', set=self._set)
- def delete(self):
- return self.handle('delete')
- def select(self, type='fetchall',col = '*', order = 'cdate desc', group = '', limit = '0,100', page=False):
- pageConfig = {}
- if page and 'page' in Demeter.config:
- pageConfig['current'] = Demeter.config['page']['current']
- if page == True:
- pageConfig['num'] = 15
- elif 'num' in page:
- pageConfig['num'] = page['num']
- Demeter.config['page']['num'] = pageConfig['num']
- return self.handle('select', type=type, col=col, order=order, group=group, limit=limit, page=pageConfig)
- def manage(self):
- self.attr(method)
- return
- def handle(self, method='select', type='fetchall', col = '*', order = '', group = '', limit = '0,100', page=False, set = ''):
- self.attr(method)
- if method == 'create':
- create = self.createState()
- if create == False:
- return False
- if type == 'fetchone':
- limit = '0,1'
- load = getattr(Sql(self._type), method)
- return self.query(load(self._table, {'key':self._key, 'fields':self._attr, 'col':col, 'order':order, 'group':group, 'limit':limit, 'page':page, 'set':set, 'table_comment':self.__comment__}), method, type)
- class Fields(object):
- def __init__(self, type='', default='', primaryKey=False, autoIncrement=False, null=True, unique=False, check='', constraint='', comment='', uuid='', index=False, indexs=False, md5=False, match='', manage=''):
- self.type = type
- self.default = default
- self.primaryKey = primaryKey
- self.autoIncrement = autoIncrement
- self.null = null
- self.unique = unique
- self.check = check
- self.constraint = constraint
- self.comment = comment
- self.uuid = uuid
- self.index = index
- self.indexs = indexs
- self.md5 = md5
- self.key = Counter().inc()
- self.match = match
- self.value = ''
- self.argv = ''
- self.bindValue = ''
- self.expValue = '='
- self.logicValue = 'and'
- self.manage = manage
- def assgin(self, value, exp='=', logic='and'):
- self.add(value)
- self.exp(exp)
- self.logic(logic)
- return self
- def bind(self, value):
- self.bindValue = value
- return self
- def exp(self, value):
- """
- if type(self.expValue) != list:
- self.expValue = []
- self.expValue.append(value)
- """
- self.expValue = value
- return self
- def logic(self, value):
- """
- if type(self.logicValue) != list:
- self.logicValue = []
- self.logicValue.append(value)
- """
- self.logicValue = value
- return self
- def val(self, value, exp='=', logic='and'):
- if type(value) == list:
- length = len(value)
- if length <= 1:
- value = value[0]
- self.value = value
- if not self.expValue:
- self.exp(exp)
- if not self.logicValue:
- self.logic(logic)
- return self
- def getArgv(self):
- return self.argv
- def getVal(self):
- return self.value
- def getBind(self):
- return self.bindValue
- def getExp(self):
- if not self.expValue:
- return ''
- if type(self.expValue) == list:
- length = len(self.expValue)
- if length <= 1:
- result = self.expValue[0]
- else:
- result = self.expValue
- else:
- result = self.expValue
- return result
- def getKey(self):
- return self.key
- def getLogic(self):
- if not self.logicValue:
- return ''
- if type(self.logicValue) == list:
- length = len(self.logicValue)
- if length <= 1:
- result = self.logicValue[0]
- else:
- result = self.logicValue
- else:
- result = self.logicValue
- return result
- def unset(self):
- self.argv = None
- self.value = None
- self.bindValue = None
- self.expValue = '='
- self.logicValue = 'and'
- return self
- def add(self, value):
- """
- if not self.argv:
- self.argv = []
- self.argv.append(value)
- """
- self.argv = value
- return self
- def ins(self, value):
- self.argv = value
- self.exp('in')
- return self
- def nq(self, value):
- self.argv = value
- self.exp('!=')
- return self
- def like(self, value):
- self.argv = '%' + value + '%'
- self.exp('like')
- return self
- def mlike(self, value):
- self.argv = value
- self.exp('~')
- self.logic('and')
- return self
- def time(self, value):
- self.add(Demeter.mktime(value))
- return self
- def start(self, value):
- self.time(value)
- self.exp('>=')
- self.logic('and')
- return self
- def end(self, value):
- self.time(value)
- self.exp('<=')
- self.logic('and')
- return self
- class Counter(object):
- num = 0
- instance = None
- def __new__(cls, *args, **kwd):
- if Counter.instance is None:
- Counter.instance = object.__new__(cls, *args, **kwd)
- return Counter.instance
- def inc(self):
- self.num = self.num + 1
- return self.num
- def dec(self):
- self.num = self.num - 1
- return self.num
- def unset(self):
- self.num = 0
- return self.num
- class Sql(object):
- instance = None
- def __new__(cls, *args, **kwd):
- if Sql.instance is None:
- Sql.instance = object.__new__(cls, *args, **kwd)
- return Sql.instance
- def __init__(self, type):
- self.type = type
- def drop(self, table, args):
- sql = 'DROP TABLE IF EXISTS ' + table
- return sql
- def alter(self, table, args):
- sql = 'ALTER TABLE ' + table + ' ADD COLUMN '
- return sql
- def create(self, table, args):
- create = []
- primary = []
- unique = []
- indexs = []
- index = []
- comment = {}
- for value in args['key']:
- key = value[0]
- val = args['fields'][key]
- if val.primaryKey:
- primary.append(key)
- if val.unique:
- unique.append(key)
- if val.index:
- index.append((key, val.index))
- if val.indexs:
- indexs.append(key)
- fields = []
- fields.append(key)
- if val.autoIncrement and self.type == 'postgresql':
- fields.append('SERIAL')
- else:
- fields.append(val.type)
- if not val.null:
- fields.append('NOT NULL')
-
- if val.autoIncrement and self.type == 'mysql':
- fields.append('AUTO_INCREMENT')
- #约束
- if val.constraint:
- fields.append('CONSTRAINT ' + val.constraint)
- if val.check:
- fields.append('CHECK ' + val.check)
-
- if val.default:
- default = val.default
- if val.default == 'time':
- default = '0'
- if '.' in val.default:
- temp = val.default.split('.')
- default = Demeter.config[temp[0]][temp[1]]
- fields.append('DEFAULT \'' + str(default) + '\'')
- if val.comment:
- if self.type == 'mysql':
- fields.append('COMMENT \'' + val.comment + '\'')
- else:
- comment[key] = val.comment
- fields = ' '.join(fields)
- create.append(fields)
- if primary:
- create.append('PRIMARY KEY (' + ','.join(primary) + ')')
- if unique:
- create.append('UNIQUE (' + ','.join(unique) + ')')
- create = ','.join(create)
- sql = 'CREATE TABLE ' + table + '(' + create + ')'
- sql = self.drop(table, args) + ';' + sql
- if indexs:
- name = '_'.join(indexs)
- value = ','.join(indexs)
- sql = sql + ';' + 'CREATE INDEX ' + table + '_' + name +' ON ' + table + '(' + value + ')'
- if index:
- for value in index:
- sql = sql + ';' + 'CREATE INDEX ' + table + '_' + value[0] +' ON ' + table + value[1]
- if comment:
- if args['table_comment']:
- sql = sql + ';' + 'COMMENT ON TABLE ' + table + ' IS \''+args['table_comment']+'\''
- for key in comment:
- sql = sql + ';' + 'COMMENT ON COLUMN ' + table + '.'+key+' IS \''+comment[key]+'\''
- return sql
- def insert(self, table, args):
- fields = []
- values = []
- for value in args['key']:
- key = value[0]
- val = args['fields'][key].getBind()
- if val:
- values.append(val)
- fields.append(key)
- fields = ','.join(fields)
- values = ','.join(values)
- sql = 'INSERT INTO ' + table + ' (' + fields + ') VALUES (' + values + ')'
- if self.type == 'postgresql':
- sql = sql + ' RETURNING id'
- return sql
- def update(self, table, args):
- fields = []
- for key in args['set']:
- fields.append(key + ' = %s')
- fields = ','.join(fields)
- sql = 'UPDATE ' + table + ' SET ' + fields + self.where(args['key'], args['fields'])
- return sql
- def delete(self, table, args):
- sql = 'DELETE FROM ' + table + self.where(args['key'], args['fields'])
- return sql
- def select(self, table, args):
- string = ' FROM ' + table + self.where(args['key'], args['fields']) + ' ' + self.group(args['group'])
- sql = ''
- if args['page']:
- sql = 'SELECT count(1) as total' + string + ';'
- sql = sql + 'SELECT ' + args['col'] + string + ' ' + self.order(args['order']) + ' ' + self.limit(args['limit'], args['page'])
- return sql
- def where(self, key, fields):
- fields = self.fields(key, fields)
- if fields:
- return ' WHERE ' + fields
- return ''
- def fields(self, key, fields):
- result = ''
- k = 0
- for value in key:
- key = value[0]
- field = fields[key]
- bind = field.getBind()
- val = field.getVal()
- logic = field.getLogic()
- exp = field.getExp()
- if type(val) == list and val:
- n = 0
- for i in val:
- data = self.field(field, bind, key, k, logic[n], exp[n])
- n = n + 1
- if data:
- result = result + data
- k = 1
- else:
- data = self.field(field, bind, key, k, logic, exp)
- if data:
- result = result + data
- k = 1
- return result
- def field(self, field, val, key, k, logic, exp):
- result = ''
- if val:
- if k == 0:
- logic = ''
- else:
- logic = ' ' + logic
- result = logic + ' ' + key + ' ' + exp + ' ' + str(val)
- return result
- def order(self, value):
- result = ''
- if value:
- result = ' ORDER BY ' + value
- return result
- def group(self, value):
- result = ''
- if value:
- result = ' GROUP BY ' + value
- return result
- def limit(self, value, page):
- result = ''
- if page:
- value = str((int(page['current'])-1) * page['num']) + ',' + str(page['num'])
- if value:
- value = value.split(',')
- if self.type == 'mysql':
- result = ' LIMIT ' + value[0] + ',' + value[1]
- elif self.type == 'postgresql':
- result = ' LIMIT ' + value[1] + ' OFFSET ' + value[0]
- return result
|