model.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. demeter database
  5. name:__base__.py
  6. author:rabin
  7. """
  8. import os
  9. import uuid
  10. import short_url
  11. import json
  12. import traceback
  13. import uuid
  14. import re
  15. import math
  16. from demeter.core import *
  17. class Model(object):
  18. __table__ = ''
  19. __comment__ = ''
  20. def __init__(self, type, db, config):
  21. self.db = db
  22. self._type = type
  23. self._config = config
  24. self._table = self._config['prefix'] + '_' + self.__table__
  25. self._set = ''
  26. self._bind = {}
  27. self._attr = {}
  28. self._key = {}
  29. self.create()
  30. def cur(self):
  31. return self.db.cursor()
  32. def query(self, sql, method='select', fetch='fetchall'):
  33. cur = self.cur()
  34. bind = []
  35. if self._set:
  36. for key in self._set:
  37. if self._set[key] == 'time':
  38. self._set[key] = self.time()
  39. elif self._set[key] == 'True':
  40. self._set[key] = True
  41. elif self._set[key] == 'False':
  42. self._set[key] = False
  43. elif 'date' in key:
  44. self._set[key] = self.mktime(self._set[key])
  45. bind.append(self._set[key])
  46. for value in self._key:
  47. if value[0] in self._bind and self._bind[value[0]] != None:
  48. val = self._bind[value[0]]
  49. self._attr[value[0]].unset()
  50. if type(val) == list and val:
  51. for i in val:
  52. bind.append(i)
  53. else:
  54. bind.append(val)
  55. if method == 'select' and ';' in sql:
  56. temp = sql.split(';')
  57. sql = temp[1]
  58. totalSql = temp[0]
  59. cur.execute(totalSql, bind)
  60. Demeter.config['page']['totalNum'] = self.fetch(cur, 'fetchone', 'count')
  61. Demeter.config['page']['total'] = math.ceil(round(float(Demeter.config['page']['totalNum'])/float(Demeter.config['page']['num']),2))
  62. cur.execute(sql, bind)
  63. if method == 'select':
  64. return self.fetch(cur, fetch)
  65. id = True
  66. if method == 'insert':
  67. id = cur.fetchone()[0]
  68. self.db.commit()
  69. self._set = {}
  70. return id
  71. """
  72. try:
  73. except Exception, e:
  74. print e.message
  75. os._exit(0)
  76. """
  77. def fetch(self, cur, type, method = ''):
  78. load = getattr(cur, type)
  79. rows = load()
  80. if type == 'fetchall':
  81. result = []
  82. if rows:
  83. for key in rows:
  84. row = {}
  85. i = 0
  86. for v in key:
  87. row[self._key[i][0]] = v
  88. i = i + 1
  89. result.append(row)
  90. elif method == 'count':
  91. return rows[0]
  92. else:
  93. result = {}
  94. i = 0
  95. if rows:
  96. for key in rows:
  97. if not key:
  98. key = ''
  99. result[self._key[i][0]] = key
  100. i = i + 1
  101. return result
  102. def attr(self, method):
  103. fields = vars(self.__class__)
  104. self._attr = {}
  105. self._bind = {}
  106. self._key = {}
  107. col = (int, str, long, float, unicode, bool, uuid.UUID)
  108. for field in fields:
  109. if isinstance(fields[field], Fields):
  110. self._attr[field] = fields[field]
  111. self._key[field] = self._attr[field].getKey()
  112. insert = (method == 'insert')
  113. if insert and self._attr[field].uuid:
  114. self.setUuid(field, col)
  115. bind = False
  116. val = self._attr[field].getArgv()
  117. if val:
  118. bind = True
  119. else:
  120. val = getattr(self, field)
  121. if isinstance(val, col):
  122. setattr(self, field, self._attr[field])
  123. bind = True
  124. elif insert and self._attr[field].default:
  125. val = self._attr[field].default
  126. bind = True
  127. if val == 'time':
  128. val = self.time()
  129. elif '.' in val:
  130. temp = val.split('.')
  131. val = Demeter.config[temp[0]][temp[1]]
  132. elif method == 'select' and self._attr[field].default and field == 'state':
  133. val = self._attr[field].default
  134. bind = True
  135. if bind and val:
  136. if type(val) == list:
  137. length = len(val)
  138. if length <= 1:
  139. val = val[0]
  140. if insert and self._attr[field].md5:
  141. val = self.createMd5(val)
  142. if self._attr[field].type == 'boolean' and isinstance(val, (str, unicode)):
  143. val = Demeter.bool(val)
  144. self.check(field, val, self._attr[field])
  145. self._bind[field] = val
  146. self._attr[field].val(self._bind[field])
  147. self._attr[field].bind('%s')
  148. self._key = sorted(self._key.items(), key=lambda d:d[1], reverse = False)
  149. Counter().unset()
  150. def check(self, field, val, attr):
  151. if attr.match == 'not':
  152. if not val:
  153. Demeter.error(field + ' not exists')
  154. elif attr.match:
  155. result = re.search(attr.match, val)
  156. if not result:
  157. Demeter.error(field + ' not match:' + attr.match)
  158. def time(self):
  159. module = __import__('time')
  160. time = getattr(module, 'time')
  161. return int(time())
  162. def mktime(self, value):
  163. return Demeter.mktime(value)
  164. def setUuid(self, field, col):
  165. id = getattr(self, self._attr[field].uuid)
  166. if isinstance(id, col):
  167. system = short_url.encode_url(id)
  168. else:
  169. system = self._attr[field].uuid
  170. name = system + '.' + self.__table__
  171. result = uuid.uuid5(uuid.uuid1(), name)
  172. result = str(result)
  173. setattr(self, field, result)
  174. def createMd5(self, value):
  175. return Demeter.md5(value, salt=True)
  176. def createState(self):
  177. if 'create' in self._config:
  178. create = Demeter.bool(self._config['create'])
  179. if create:
  180. return Demeter.runtime(self._type, self.__table__, json.dumps(self._key))
  181. return False
  182. def drop(self):
  183. return self.handle('drop')
  184. def create(self):
  185. return self.handle('create')
  186. def insert(self):
  187. return self.handle('insert')
  188. def update(self, *args, **kwargs):
  189. if args:
  190. self._set = args[0]
  191. else:
  192. self._set = kwargs
  193. return self.handle('update', set=self._set)
  194. def delete(self):
  195. return self.handle('delete')
  196. def select(self, type='fetchall',col = '*', order = 'cdate desc', group = '', limit = '0,100', page=False):
  197. pageConfig = {}
  198. if page and 'page' in Demeter.config:
  199. pageConfig['current'] = Demeter.config['page']['current']
  200. if page == True:
  201. pageConfig['num'] = 15
  202. elif 'num' in page:
  203. pageConfig['num'] = page['num']
  204. Demeter.config['page']['num'] = pageConfig['num']
  205. return self.handle('select', type=type, col=col, order=order, group=group, limit=limit, page=pageConfig)
  206. def manage(self):
  207. self.attr(method)
  208. return
  209. def handle(self, method='select', type='fetchall', col = '*', order = '', group = '', limit = '0,100', page=False, set = ''):
  210. self.attr(method)
  211. if method == 'create':
  212. create = self.createState()
  213. if create == False:
  214. return False
  215. if type == 'fetchone':
  216. limit = '0,1'
  217. load = getattr(Sql(self._type), method)
  218. 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)
  219. class Fields(object):
  220. 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=''):
  221. self.type = type
  222. self.default = default
  223. self.primaryKey = primaryKey
  224. self.autoIncrement = autoIncrement
  225. self.null = null
  226. self.unique = unique
  227. self.check = check
  228. self.constraint = constraint
  229. self.comment = comment
  230. self.uuid = uuid
  231. self.index = index
  232. self.indexs = indexs
  233. self.md5 = md5
  234. self.key = Counter().inc()
  235. self.match = match
  236. self.value = ''
  237. self.argv = ''
  238. self.bindValue = ''
  239. self.expValue = '='
  240. self.logicValue = 'and'
  241. self.manage = manage
  242. def assgin(self, value, exp='=', logic='and'):
  243. self.add(value)
  244. self.exp(exp)
  245. self.logic(logic)
  246. return self
  247. def bind(self, value):
  248. self.bindValue = value
  249. return self
  250. def exp(self, value):
  251. if type(self.expValue) != list:
  252. self.expValue = []
  253. self.expValue.append(value)
  254. return self
  255. def logic(self, value):
  256. if type(self.logicValue) != list:
  257. self.logicValue = []
  258. self.logicValue.append(value)
  259. return self
  260. def val(self, value, exp='=', logic='and'):
  261. if type(value) == list:
  262. length = len(value)
  263. if length <= 1:
  264. value = value[0]
  265. self.value = value
  266. if not self.expValue:
  267. self.exp(exp)
  268. if not self.logicValue:
  269. self.logic(logic)
  270. return self
  271. def getArgv(self):
  272. return self.argv
  273. def getVal(self):
  274. return self.value
  275. def getBind(self):
  276. return self.bindValue
  277. def getExp(self):
  278. if not self.expValue:
  279. return ''
  280. if type(self.expValue) == list:
  281. length = len(self.expValue)
  282. if length <= 1:
  283. result = self.expValue[0]
  284. else:
  285. result = self.expValue
  286. else:
  287. result = self.expValue
  288. return result
  289. def getKey(self):
  290. return self.key
  291. def getLogic(self):
  292. if not self.logicValue:
  293. return ''
  294. if type(self.logicValue) == list:
  295. length = len(self.logicValue)
  296. if length <= 1:
  297. result = self.logicValue[0]
  298. else:
  299. result = self.logicValue
  300. else:
  301. result = self.logicValue
  302. return result
  303. def unset(self):
  304. self.argv = None
  305. self.value = None
  306. self.bindValue = None
  307. self.expValue = '='
  308. self.logicValue = 'and'
  309. return self
  310. def add(self, value):
  311. if not self.argv:
  312. self.argv = []
  313. self.argv.append(value)
  314. return self
  315. def ins(self, value):
  316. self.argv = value
  317. self.exp('in')
  318. return self
  319. def nq(self, value):
  320. self.argv = value
  321. self.exp('!=')
  322. return self
  323. def like(self, value):
  324. self.argv = '%' + value + '%'
  325. self.exp('like')
  326. return self
  327. def mlike(self, value):
  328. self.argv = value
  329. self.exp('~')
  330. self.logic('and')
  331. return self
  332. def time(self, value):
  333. self.add(Demeter.mktime(value))
  334. return self
  335. def start(self, value):
  336. self.time(value)
  337. self.exp('>=')
  338. self.logic('and')
  339. return self
  340. def end(self, value):
  341. self.time(value)
  342. self.exp('<=')
  343. self.logic('and')
  344. return self
  345. class Counter(object):
  346. num = 0
  347. instance = None
  348. def __new__(cls, *args, **kwd):
  349. if Counter.instance is None:
  350. Counter.instance = object.__new__(cls, *args, **kwd)
  351. return Counter.instance
  352. def inc(self):
  353. self.num = self.num + 1
  354. return self.num
  355. def dec(self):
  356. self.num = self.num - 1
  357. return self.num
  358. def unset(self):
  359. self.num = 0
  360. return self.num
  361. class Sql(object):
  362. instance = None
  363. def __new__(cls, *args, **kwd):
  364. if Sql.instance is None:
  365. Sql.instance = object.__new__(cls, *args, **kwd)
  366. return Sql.instance
  367. def __init__(self, type):
  368. self.type = type
  369. def drop(self, table, args):
  370. sql = 'DROP TABLE IF EXISTS ' + table
  371. return sql
  372. def alter(self, table, args):
  373. sql = 'ALTER TABLE ' + table + ' ADD COLUMN '
  374. return sql
  375. def create(self, table, args):
  376. create = []
  377. primary = []
  378. unique = []
  379. indexs = []
  380. index = []
  381. comment = {}
  382. for value in args['key']:
  383. key = value[0]
  384. val = args['fields'][key]
  385. if val.primaryKey:
  386. primary.append(key)
  387. if val.unique:
  388. unique.append(key)
  389. if val.index:
  390. index.append((key, val.index))
  391. if val.indexs:
  392. indexs.append(key)
  393. fields = []
  394. fields.append(key)
  395. if val.autoIncrement and self.type == 'postgresql':
  396. fields.append('SERIAL')
  397. else:
  398. fields.append(val.type)
  399. if not val.null:
  400. fields.append('NOT NULL')
  401. if val.autoIncrement and self.type == 'mysql':
  402. fields.append('AUTO_INCREMENT')
  403. #约束
  404. if val.constraint:
  405. fields.append('CONSTRAINT ' + val.constraint)
  406. if val.check:
  407. fields.append('CHECK ' + val.check)
  408. if val.default:
  409. default = val.default
  410. if val.default == 'time':
  411. default = '0'
  412. if '.' in val.default:
  413. temp = val.default.split('.')
  414. default = Demeter.config[temp[0]][temp[1]]
  415. fields.append('DEFAULT \'' + str(default) + '\'')
  416. if val.comment:
  417. if self.type == 'mysql':
  418. fields.append('COMMENT \'' + val.comment + '\'')
  419. else:
  420. comment[key] = val.comment
  421. fields = ' '.join(fields)
  422. create.append(fields)
  423. if primary:
  424. create.append('PRIMARY KEY (' + ','.join(primary) + ')')
  425. if unique:
  426. create.append('UNIQUE (' + ','.join(unique) + ')')
  427. create = ','.join(create)
  428. sql = 'CREATE TABLE ' + table + '(' + create + ')'
  429. sql = self.drop(table, args) + ';' + sql
  430. if indexs:
  431. name = '_'.join(indexs)
  432. value = ','.join(indexs)
  433. sql = sql + ';' + 'CREATE INDEX ' + table + '_' + name +' ON ' + table + '(' + value + ')'
  434. if index:
  435. for value in index:
  436. sql = sql + ';' + 'CREATE INDEX ' + table + '_' + value[0] +' ON ' + table + value[1]
  437. if comment:
  438. if args['table_comment']:
  439. sql = sql + ';' + 'COMMENT ON TABLE ' + table + ' IS \''+args['table_comment']+'\''
  440. for key in comment:
  441. sql = sql + ';' + 'COMMENT ON COLUMN ' + table + '.'+key+' IS \''+comment[key]+'\''
  442. return sql
  443. def insert(self, table, args):
  444. fields = []
  445. values = []
  446. for value in args['key']:
  447. key = value[0]
  448. val = args['fields'][key].getBind()
  449. if val:
  450. values.append(val)
  451. fields.append(key)
  452. fields = ','.join(fields)
  453. values = ','.join(values)
  454. sql = 'INSERT INTO ' + table + ' (' + fields + ') VALUES (' + values + ')'
  455. if self.type == 'postgresql':
  456. sql = sql + ' RETURNING id'
  457. return sql
  458. def update(self, table, args):
  459. fields = []
  460. for key in args['set']:
  461. fields.append(key + ' = %s')
  462. fields = ','.join(fields)
  463. sql = 'UPDATE ' + table + ' SET ' + fields + self.where(args['key'], args['fields'])
  464. return sql
  465. def delete(self, table, args):
  466. sql = 'DELETE FROM ' + table + self.where(args['fields'])
  467. return sql
  468. def select(self, table, args):
  469. string = ' FROM ' + table + self.where(args['key'], args['fields']) + ' ' + self.group(args['group'])
  470. sql = ''
  471. if args['page']:
  472. sql = 'SELECT count(1) as total' + string + ';'
  473. sql = sql + 'SELECT ' + args['col'] + string + ' ' + self.order(args['order']) + ' ' + self.limit(args['limit'], args['page'])
  474. return sql
  475. def where(self, key, fields):
  476. fields = self.fields(key, fields)
  477. if fields:
  478. return ' WHERE ' + fields
  479. return ''
  480. def fields(self, key, fields):
  481. result = ''
  482. k = 0
  483. for value in key:
  484. key = value[0]
  485. field = fields[key]
  486. bind = field.getBind()
  487. val = field.getVal()
  488. logic = field.getLogic()
  489. exp = field.getExp()
  490. if type(val) == list and val:
  491. n = 0
  492. for i in val:
  493. data = self.field(field, bind, key, k, logic[n], exp[n])
  494. n = n + 1
  495. if data:
  496. result = result + data
  497. k = 1
  498. else:
  499. data = self.field(field, bind, key, k, logic, exp)
  500. if data:
  501. result = result + data
  502. k = 1
  503. return result
  504. def field(self, field, val, key, k, logic, exp):
  505. result = ''
  506. if val:
  507. if k == 0:
  508. logic = ''
  509. else:
  510. logic = ' ' + logic
  511. result = logic + ' ' + key + ' ' + exp + ' ' + str(val)
  512. return result
  513. def order(self, value):
  514. result = ''
  515. if value:
  516. result = ' ORDER BY ' + value
  517. return result
  518. def group(self, value):
  519. result = ''
  520. if value:
  521. result = ' GROUP BY ' + value
  522. return result
  523. def limit(self, value, page):
  524. result = ''
  525. if page:
  526. value = str((int(page['current'])-1) * page['num']) + ',' + str(page['num'])
  527. if value:
  528. value = value.split(',')
  529. if self.type == 'mysql':
  530. result = ' LIMIT ' + value[0] + ',' + value[1]
  531. elif self.type == 'postgresql':
  532. result = ' LIMIT ' + value[1] + ' OFFSET ' + value[0]
  533. return result