ó
H`¾Tc           @   sÕ   d  Z  d d l m Z m Z d d l m Z d d l m Z m	 Z	 d d l
 Z
 d e f d	 „  ƒ  YZ d
 e e j f d „  ƒ  YZ d e e j f d „  ƒ  YZ d e f d „  ƒ  YZ d e e f d „  ƒ  YZ e Z d S(   s  
.. dialect:: mssql+pyodbc
    :name: PyODBC
    :dbapi: pyodbc
    :connectstring: mssql+pyodbc://<username>:<password>@<dsnname>
    :url: http://pypi.python.org/pypi/pyodbc/

Additional Connection Examples
-------------------------------

Examples of pyodbc connection string URLs:

* ``mssql+pyodbc://mydsn`` - connects using the specified DSN named ``mydsn``.
  The connection string that is created will appear like::

    dsn=mydsn;Trusted_Connection=Yes

* ``mssql+pyodbc://user:pass@mydsn`` - connects using the DSN named
  ``mydsn`` passing in the ``UID`` and ``PWD`` information. The
  connection string that is created will appear like::

    dsn=mydsn;UID=user;PWD=pass

* ``mssql+pyodbc://user:pass@mydsn/?LANGUAGE=us_english`` - connects
  using the DSN named ``mydsn`` passing in the ``UID`` and ``PWD``
  information, plus the additional connection configuration option
  ``LANGUAGE``. The connection string that is created will appear
  like::

    dsn=mydsn;UID=user;PWD=pass;LANGUAGE=us_english

* ``mssql+pyodbc://user:pass@host/db`` - connects using a connection
  that would appear like::

    DRIVER={SQL Server};Server=host;Database=db;UID=user;PWD=pass

* ``mssql+pyodbc://user:pass@host:123/db`` - connects using a connection
  string which includes the port
  information using the comma syntax. This will create the following
  connection string::

    DRIVER={SQL Server};Server=host,123;Database=db;UID=user;PWD=pass

* ``mssql+pyodbc://user:pass@host/db?port=123`` - connects using a connection
  string that includes the port
  information as a separate ``port`` keyword. This will create the
  following connection string::

    DRIVER={SQL Server};Server=host;Database=db;UID=user;PWD=pass;port=123

* ``mssql+pyodbc://user:pass@host/db?driver=MyDriver`` - connects using a
  connection string that includes a custom ODBC driver name.  This will create
  the following connection string::

    DRIVER={MyDriver};Server=host;Database=db;UID=user;PWD=pass

If you require a connection string that is outside the options
presented above, use the ``odbc_connect`` keyword to pass in a
urlencoded connection string. What gets passed in will be urldecoded
and passed directly.

For example::

    mssql+pyodbc:///?odbc_connect=dsn%3Dmydsn%3BDatabase%3Ddb

would create the following connection string::

    dsn=mydsn;Database=db

Encoding your connection string can be easily accomplished through
the python shell. For example::

    >>> import urllib
    >>> urllib.quote_plus('dsn=mydsn;Database=db')
    'dsn%3Dmydsn%3BDatabase%3Ddb'

Unicode Binds
-------------

The current state of PyODBC on a unix backend with FreeTDS and/or
EasySoft is poor regarding unicode; different OS platforms and versions of
UnixODBC versus IODBC versus FreeTDS/EasySoft versus PyODBC itself
dramatically alter how strings are received.  The PyODBC dialect attempts to
use all the information it knows to determine whether or not a Python unicode
literal can be passed directly to the PyODBC driver or not; while SQLAlchemy
can encode these to bytestrings first, some users have reported that PyODBC
mis-handles bytestrings for certain encodings and requires a Python unicode
object, while the author has observed widespread cases where a Python unicode
is completely misinterpreted by PyODBC, particularly when dealing with
the information schema tables used in table reflection, and the value
must first be encoded to a bytestring.

It is for this reason that whether or not unicode literals for bound
parameters be sent to PyODBC can be controlled using the
``supports_unicode_binds`` parameter to ``create_engine()``.  When
left at its default of ``None``, the PyODBC dialect will use its
best guess as to whether or not the driver deals with unicode literals
well.  When ``False``, unicode literals will be encoded first, and when
``True`` unicode literals will be passed straight through.  This is an interim
flag that hopefully should not be needed when the unicode situation stabilizes
for unix + PyODBC.

.. versionadded:: 0.7.7
    ``supports_unicode_binds`` parameter to ``create_engine()``\ .

i   (   t   MSExecutionContextt	   MSDialecti   (   t   PyODBCConnector(   t   typest   utiliÿÿÿÿNt   _ms_numeric_pyodbcc           B   s)   e  Z d  Z d „  Z d „  Z d „  Z RS(   s¡   Turns Decimals with adjusted() < 0 or > 7 into strings.

    The routines here are needed for older pyodbc versions
    as well as current mxODBC versions.

    c            s;   t  t ˆ ƒ j | ƒ ‰  | j s% ˆ  S‡  ‡ f d †  } | S(   Nc            st   ˆ j  r\ t |  t j ƒ r\ |  j ƒ  } | d k  r@ ˆ j |  ƒ S| d k r\ ˆ j |  ƒ Sn  ˆ  rl ˆ  |  ƒ S|  Sd  S(   Ni    i   (   t	   asdecimalt
   isinstancet   decimalt   Decimalt   adjustedt   _small_dec_to_stringt   _large_dec_to_string(   t   valueR
   (   t   super_processt   self(    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyt   processŠ   s    	
(   t   superR   t   bind_processort   _need_decimal_fix(   R   t   dialectR   (    (   R   R   sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR   ‚   s    		c      
   C   sc   d | d k  r d p d d t  | j ƒ  ƒ d d j g  | j ƒ  d D] } t | ƒ ^ qF ƒ f S(   Ns   %s0.%s%si    t   -t    t   0i   (   t   absR
   t   joint   as_tuplet   str(   R   R   t   nint(    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR      s    c      
   C   s„  | j  ƒ  d } d t | ƒ k r„ d | d k  r7 d p: d d j g  | D] } t | ƒ ^ qG ƒ d | j ƒ  t | ƒ d f } nü t | ƒ d | j ƒ  k r+d | d k  rµ d p¸ d d j g  | D] } t | ƒ ^ qÅ d | j ƒ  d !ƒ d j g  | D] } t | ƒ ^ qû | j ƒ  d ƒ f } nU d	 | d k  r@d pCd d j g  | D] } t | ƒ ^ qPd | j ƒ  d !ƒ f } | S(
   Ni   t   Es   %s%s%si    R   R   R   s   %s%s.%ss   %s%s(   R   R   R   R
   t   len(   R   R   t   _intt   st   result(    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR   £   s$    %%077(   t   __name__t
   __module__t   __doc__R   R   R   (    (    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR   y   s   		t   _MSNumeric_pyodbcc           B   s   e  Z RS(    (   R"   R#   (    (    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR%   º   s   t   _MSFloat_pyodbcc           B   s   e  Z RS(    (   R"   R#   (    (    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR&   ¾   s   t   MSExecutionContext_pyodbcc           B   s    e  Z e Z d  „  Z d „  Z RS(   c         C   sZ   t  t |  ƒ j ƒ  |  j rV |  j j rV t |  j d ƒ rV t |  _	 |  j
 d 7_
 n  d S(   sº  where appropriate, issue "select scope_identity()" in the same
        statement.

        Background on why "scope_identity()" is preferable to "@@identity":
        http://msdn.microsoft.com/en-us/library/ms190315.aspx

        Background on why we attempt to embed "scope_identity()" into the same
        statement as the INSERT:
        http://code.google.com/p/pyodbc/wiki/FAQs#How_do_I_retrieve_autogenerated/identity_values?

        i    s   ; select scope_identity()N(   R   R'   t   pre_exect   _select_lastrowidR   t   use_scope_identityR   t
   parameterst   Truet   _embedded_scope_identityt	   statement(   R   (    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR(   Å   s    		c         C   s‡   |  j  rp xN t rY y |  j j ƒ  d } PWq |  j j j k
 rU } |  j j ƒ  q Xq Wt | d ƒ |  _	 n t
 t |  ƒ j ƒ  d  S(   Ni    (   R-   R,   t   cursort   fetchallR   t   dbapit   Errort   nextsett   intt
   _lastrowidR   R'   t	   post_exec(   R   t   rowt   e(    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR6   Ý   s    		(   R"   R#   t   FalseR-   R(   R6   (    (    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR'   Â   s   	t   MSDialect_pyodbcc           B   sI   e  Z e Z d  Z e j e j i e	 e
 j 6e e
 j 6ƒ Z d d „ Z RS(   s
   SQL Serverc         K   sƒ   d | k r! | j  d ƒ |  _ n  t t |  ƒ j |   |  j o[ |  j o[ t |  j j d ƒ |  _ |  j oy |  j	 ƒ  d k  |  _
 d  S(   Nt   description_encodingR3   i   i   i   (   i   i   i   (   t   popR;   R   R:   t   __init__R*   R1   t   hasattrt   Cursort   _dbapi_versionR   (   R   R;   t   params(    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR=      s    			N(   R"   R#   R'   t   execution_ctx_clst   pyodbc_driver_nameR   t   update_copyR   t   colspecsR%   t   sqltypest   NumericR&   t   Floatt   NoneR=   (    (    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyR:   ò   s   
(   R$   t   baseR    R   t   connectors.pyodbcR   R   R   RF   R   R   t   objectR   RG   R%   RH   R&   R'   R:   R   (    (    (    sf   /var/www/send.findwatt.com/datamanager/lib/python2.7/site-packages/sqlalchemy/dialects/mssql/pyodbc.pyt   <module>q   s   A0