Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

sqlutils.py 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import logging as logger
  4. import sqlalchemy as sqla
  5. from django.conf import settings
  6. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Lodel.settings")
  7. ENGINES = {
  8. 'mysql': {
  9. 'driver': 'pymysql',
  10. 'encoding': 'utf8'
  11. },
  12. 'postgresql': {
  13. 'driver': 'psycopg2',
  14. 'encoding': 'utf8',
  15. },
  16. 'sqlite': {
  17. 'driver': 'pysqlite',
  18. 'encoding': 'utf8',
  19. },
  20. }
  21. sql_config = settings.LODEL2SQLWRAPPER
  22. ## Returns an engine given dbconf name
  23. #
  24. # @param ename str: name of an item in django.conf.settings.LODEL2SQLWRAPPER['db']
  25. # @param sqlaloggin None|bool: If None leave default value, if true activate sqlalchemy logging
  26. # @return SqlAlchemy engine
  27. def get_engine(ename='default', sqlalogging=None):
  28. # Loading confs
  29. cfg = sql_config['db'][ename]
  30. edata = ENGINES[cfg['ENGINE']] # engine infos
  31. conn_str = ""
  32. if cfg['ENGINE'] == 'sqlite':
  33. #SQLite connection string
  34. conn_str = '%s+%s:///%s' % (cfg['ENGINE'], edata['driver'], cfg['NAME'])
  35. else:
  36. #MySQL and PostgreSQL connection string
  37. user = cfg['USER']
  38. user += (':' + cfg['PASSWORD'] if 'PASSWORD' in cfg else '')
  39. if 'HOST' not in cfg:
  40. logger.info('Not HOST in configuration, using localhost')
  41. host = 'localhost'
  42. else:
  43. host = cfg['HOST']
  44. host += (':' + cfg['PORT'] if 'PORT' in cfg else '')
  45. conn_str = '%s+%s://' % (cfg['ENGINE'], edata['driver'])
  46. conn_str += '%s@%s/%s' % (user, host, cfg['NAME'])
  47. ret = sqla.create_engine(conn_str, encoding=edata['encoding'], echo=sqlalogging)
  48. logger.debug("Getting engine :" + str(ret))
  49. return ret
  50. ## Return a sqlalchemy.MetaData object
  51. # @param engine sqlalchemy.engine : A sqlalchemy engine
  52. # @return an sql alechemy MetaData instance bind to engine
  53. def meta(engine):
  54. res = sqla.MetaData(bind=engine)
  55. res.reflect(bind=engine)
  56. return res
  57. ## Return an sqlalchemy table given an EmComponent child class
  58. # @warning Except a class type not an instance
  59. # @param cls : An EmComponent child class
  60. # @return An sqlalchemy table
  61. # @throw TypeError if em_instance is an EmComponent or not an EmComponent child class (or an instance)
  62. def get_table(cls):
  63. from EditorialModel.components import EmComponent # dirty circula inclusion hack
  64. if not issubclass(cls, EmComponent) or cls.table is None:
  65. raise TypeError("Excepting an EmComponent child class not an " + str(cls))
  66. engine = cls.db_engine()
  67. return sqla.Table(cls.table, meta(engine))
  68. def getTable(cls):
  69. return get_table(cls)
  70. ## This function is intended to execute ddl defined in sqlalter
  71. # @warning There is a dirty workaround here, DDL should returns only one query, but DropColumn for sqlite has to return 4 queries (rename, create, insert, drop). There is a split on the compiled SQL to extract and execute one query at a time
  72. # @param ddl DDLElement: Can be an Database.sqlalter.DropColumn Database.sqlalter.AddColumn or Database.sqlalter.AlterColumn
  73. # @param db_engine: A database engine
  74. # @return True if success, else False
  75. def ddl_execute(ddl, db_engine):
  76. conn = db_engine.connect()
  77. req = str(ddl.compile(dialect=db_engine.dialect))
  78. queries = req.split(';')
  79. for query in queries:
  80. logger.debug("Executing custom raw SQL query : '" + query + "'")
  81. ret = conn.execute(query)
  82. if not bool(ret):
  83. return False
  84. conn.close()
  85. return True