a _K?bL @sdZddlmZmZzddlTWney0ZzddlZdZej dkred7Zddl Z dd ej d  ej DZe jd kreD]jZeejeDz ddlTWneyYn0dZWdqWdq1s0Yqerd eZned 7ZeredeefWYdZ[n dZ[00eZgdZddlZddlZddlZddlmZmZmZmZmZddlmZddl m!Z!m"Z"ddl#m$Z$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z,ddl-m.Z/m0Z1ddl2m3Z3zddl4m5Z5m6Z6m7Z7dZ8WneydZ8Yn0ze9Wne:y4e;Z9Yn0ze<Wne:yVe=ZWne:y|e=e?fZ>Yn0zddl(m@Z@Wn^eyddl(mAZAzddlBmCZCWn"eyGdd d ZCYn0dd"d#Z@Yn0zdd$lDmEZEWn(ey&dd%lDmFZFd&d'ZGYn 0d(d'ZGzdd)lmHZHWn8eyxGd*d+d+eZHeHedd,eH_IdZJYn0dZJeKd-d.d/d0d1d-d2d0d0d0d3 ZLd4d5ZMd6d7ZNd8d9ZOGd:d;d;e?ZPGdd?d?ZRGd@dAdAeKZSeSZTeTUZVdBdCZWGdDdEdEeXZYGdFdGdGe=ZZGdHdIdIe%Z[GdJdKdKZ\dLdMZ]dNdOZ^dPdQZ_dRdSZ`dTdUZadVdWZbdXdYZce,dZZdd[d\Zed]d^Zfd_d`Zge,daZhe,dbZie,dcZje,ddZkdedfZlGdgdhdheKZmdidjZndkdlZoGdmdndne=ZpGdodpdpeKZqe,dqZre@drdsdtduasdvdwZtdxdyZudzd{Zvd|d}Zwd~dZxGdddZyezfddZ{ddZ|ddZ}e~eee/eeuevewexGdddeZddZGdddZedkredeedeedS)aZPyGreSQL classic interface. This pg module implements some basic database management stuff. It includes the _pg module and builds on it, providing the higher level wrapper class named DB with additional functionality. This is known as the "classic" ("old style") PyGreSQL interface. For a DB-API 2 compliant interface use the newer pgdb module. )print_functiondivision)*Nzlibpq.ntdllcCs&g|]}tjtj|tr|qS)ospathexistsjoinlibpq).0r rr)/tmp/pip-target-llefyurp/lib/python/pg.py !srPATH)z compatible sozRCannot import shared library for PyGreSQL, probably because no %s is installed. %s)HDBAdapterNotificationHandler TypecastsByteaHstoreJsonLiteralErrorWarningZ DataError DatabaseErrorZIntegrityErrorInterfaceError InternalErrorZInvalidResultErrorZMultipleResultsErrorZ NoResultErrorZNotSupportedErrorZOperationalErrorProgrammingErrorZINV_READZ INV_WRITEZ POLLING_OKZPOLLING_FAILEDZPOLLING_READINGZPOLLING_WRITINGSEEK_CURSEEK_ENDSEEK_SETZ TRANS_ACTIVEZ TRANS_IDLEZ TRANS_INERRORZ TRANS_INTRANSZ TRANS_UNKNOWN cast_array cast_hstore cast_recordconnect escape_bytea escape_stringunescape_byteaZ get_arrayget_boolZget_bytea_escapedZ get_datestyle get_decimalget_decimal_pointZ get_defbaseZ get_defhostZ get_defoptZ get_defportZ get_defuserget_jsondecode get_typecastZ set_arrayZset_boolZset_bytea_escapedZ set_datestyle set_decimalZset_decimal_pointZ set_defbaseZ set_defhostZ set_defoptZ set_defpasswdZ set_defportZ set_defuserset_jsondecodeset_query_helpers set_typecastversion __version__)datetimedatetime timedeltatzinfo)Decimal)isnanisinf) namedtuple OrderedDict) itemgetter)partial)compile)loadsdumps)UUID)DictListUnionTF) lru_cache)update_wrapper)RLockc@seZdZddZddZdS)rLcCsdSNrselfrrr __enter__szRLock.__enter__cCsdSrMr)rOexctypeexcinstexctbrrr__exit__szRLock.__exit__N)__name__ __module__ __qualname__rPrTrrrrrLsrLcsfdd}|S)z:Simplified functools.lru_cache decorator for one argument.cstijtg}|dg||ddg|dd<dkrLfdd}n2durhfdd}nfdd}|_t|S)NFrcs |}|SrMrargres)functionrrwrappersz-lru_cache..decorator..wrappercs*|}|ur|S|}||<|SrMrrY)cacher\getsentinelrrr]s  c sr~|}|durtd}|\}}}}||d<||d<|d}||d<|d<||d<||d<|WdSWdn1s0Y|}\}}|vrn|r |} || d<|| d<| d}d<|d} |d} d|d<|d<| =| |<nB|d}||||g}||d<|d<|<tkrNdd<Wdn1sd0Y|S)NrrT)len) rZlinkrootZprvZnxtZ_argr[lastfullZoldrootZoldargZoldres)r^r\r_lockmaxsize root_fullrrr]sB 0  ()objectr_rL __wrapped__rK)r\rer]ri)r^r\r_rhrjr`r decorators $zlru_cache..decoratorr)rirnrrmrrJs BrJ) signature) getargspeccCs t|jSrM)rpargsfuncrrrget_argssrtcCstt|jSrM)listro parametersrrrrrrts)timezonec@s2eZdZdZd ddZddZddZd d ZdS) rwzSimple timezone implementation.NcCsf||_|s\|jjd|jjd}|dkrBt| d\}}| }nt|d\}}d||f}||_dS)Ni<rz UTC%+03d:%02d)offsetdayssecondsdivmodname)rOryr}minuteshoursrrr__init__s ztimezone.__init__cCs|jSrM)ryrOdtrrr utcoffsetsztimezone.utcoffsetcCs|jSrM)r}rrrrtznamesztimezone.tznamecCsdSrMrrrrrdstsz timezone.dst)N)rUrVrW__doc__rrrrrrrrrws  rwUTCz+0100z+0200z-0500+0000z-1000z-0700) ZCETZEETESTGMTZHSTZMETMSTZUCTrZWETcCs6|dr*t|dkr|dS|ddSt|dS)N)+-Z00:r) startswithrcreplace _timezonesr_)tzrrr_timezone_as_offsets    rcCsNt|}dt|ddt|dd}|ddkr>| }tt|d|S)Nrxrarrrr)r~)rintrwr:)rr~rrr _get_timezones $ rcCsd|S)z Build oid key from a table name.zoid(%s)r)tablerrr_oid_keysrc@seZdZdZdS)rz'Wrapper class for marking Bytea values.NrUrVrWrrrrrrsrc@s,eZdZdZedZeddZddZdS)rz(Wrapper class for marking hstore values.z^[Nn][Uu][Ll][Ll]$|[ ,=>]cCsJ|dur dSt|tst|}|s&dS|dd}|j|rFd|}|S)NNULL"""z\""%s") isinstance basestringstrr _re_quotesearch)clssrrr_quote$s   z Hstore._quotecs"|jdfdd|DS)N,c3s&|]\}}d||fVqdS)z%s=>%sNr)r kvqrr 3z!Hstore.__str__..)rr itemsrNrrr__str__1szHstore.__str__N) rUrVrWrregexr classmethodrrrrrrrs  rc@s"eZdZdZdddZddZdS)rz&Wrapper class for marking Json values.NcCs||_|p t|_dSrM)obj jsonencodeencode)rOrrrrrr9sz Json.__init__cCs|j}t|tr|S||SrM)rrrr)rOrrrrr=s z Json.__str__)N)rUrVrWrrrrrrrr6s rc@seZdZdZegegdddddddd d eeee g d d e gd ddddde ge gde gegdeggddddeeegd Zee urededdZeddZdd Zd!S)" _SimpleTypeszDictionary mapping pg_type names to simple type names. The corresponding Python types and simple names are also mapped. intervalr8timetz timestamp timestamptzZabstimeZreltimer9r:float4float8Zcidint2int4int8oidxidjsonbnumericbpcharcharr}varchar) boolbytear7floatrhstorejsonuuidnummoneytextrcCsn|jD]^\}}|g|}|D]F}|||<t|trHd||d|<q tr t|ts d||t|<q q dS)zInitialize type mapping.%s[]_%sN) _type_aliasesrrr has_typingtuplerH)rOtypkeyskeyrrrr]s  z_SimpleTypes.__init__cCsdS)z'Unmapped types are interpreted as text.rrrrrr __missing__hsz_SimpleTypes.__missing__cCstdd|DS)z)Get a plain dictionary of only the types.css(|] \}}t|ttfs||fVqdSrM)rrr)r rrrrrros z-_SimpleTypes.get_type_dict..)dictrrNrrr get_type_dictmsz_SimpleTypes.get_type_dictN)rUrVrWrrrr7r8r9r:rrrrrFr<bytesunicoderrlongappendr staticmethodrrrrrrrDs,   rcCs t|trd|vrd|fS|S)a$Quote parameter representing a qualified name. Puts a quote_ident() call around the given parameter unless the name contains a dot, in which case the name is ambiguous (could be a qualified name or just a name with a dot in it) and must be quoted manually by the caller. .zquote_ident(%s))rr)paramr}rrr_quote_if_unqualifiedws rc@seZdZdZdddZdS)_ParameterListz0Helper class for building typed parameter lists.NcCs0|||}t|tr|S||dt|S)zTypecast value with known database type and build parameter list. If this is a literal value, it will be returned as is. Otherwise, a placeholder will be returned and the parameter list will be augmented. z$%d)adaptrrrrc)rOvaluerrrradds    z_ParameterList.add)N)rUrVrWrrrrrrrsrc@seZdZdZdS)rz-Wrapper class for marking literal SQL values.Nrrrrrrsrc@s4eZdZdZddZddZddZedd Zd S) AttrDictz@Simple read-only ordered dictionary for storing attribute names.cOsLd|_tj|g|Ri|d|_|j}||_|_||_|_|_dS)NFT) _read_onlyr@r_read_only_errorclearupdatepop setdefaultpopitem)rOrqkwerrorrrrrs  zAttrDict.__init__cCs |jr|t|||dSrM)rrr@ __setitem__)rOrrrrrrszAttrDict.__setitem__cCs|jr|t||dSrM)rrr@ __delitem__)rOrrrrrszAttrDict.__delitem__cOs tddS)NzThis object is read-only) TypeErrorrqrrrrrszAttrDict._read_only_errorN) rUrVrWrrrrrrrrrrrs rc@sJeZdZdZedZedZedZ edZ edZ Z ddZ ed d Zed d Zed dZeZZZddZddZddZddZeddZeZeddZeddZeZZZ ddZ!dd Z"d!d"Z#d7d$d%Z$ed&d'Z%ed(d)Z&ed*d+Z'ed,d-Z(ed.d/Z)d8d1d2Z*d3d4Z+d9d5d6Z,d#S):rz@Class providing methods for adapting parameters to the database.zt true 1 y yes onzDcurrent_date current_time current_timestamp localtime localtimestampz[{},"\\\s]|^[Nn][Uu][Ll][Ll]$z[(,"\\]z(["\\])cCst||_dSrM)weakrefproxydbrOrrrrrszAdapter.__init__cCs,t|tr |sdS||jv}|r(dSdS)zAdapt a boolean parameter.Ntf)rrlower_bool_true_valuesrrrrr _adapt_bools  zAdapter._adapt_boolcCs,|sdSt|tr(||jvr(t|S|S)zAdapt a date parameter.N)rrr_date_literalsrrrrr _adapt_dates zAdapter._adapt_datecCs|s|dkrdS|S)zAdapt a numeric parameter.rNrrrrr _adapt_nums zAdapter._adapt_numcCs |j|S)zAdapt a bytea parameter.)rr)rOrrrr _adapt_byteaszAdapter._adapt_byteacCs4|sdSt|tr|St|tr(t|S|j|S)zAdapt a json parameter.N)rrrrr encode_jsonrrrr _adapt_jsons  zAdapter._adapt_jsoncCsN|sdSt|tr|St|tr(t|St|tr>tt|Std|dS)zAdapt a hstore parameter.Nz"Hstore parameter %s has wrong type)rrrrrrrrrr _adapt_hstores    zAdapter._adapt_hstorecCs|sdSt|tr|St|S)zAdapt a UUID parameter.N)rrrrrrr _adapt_uuids  zAdapter._adapt_uuidcsjt|tr,|jddfdd|DS|dur8dS|s@dSt|}|j|rfd|jd |}|S) z"Adapt a text type array parameter.{%s}rc3s|]}|VqdSrMrr rrrrrrz,Adapter._adapt_text_array..Nnullrr\\\1) rru_adapt_text_arrayr r_re_array_quoter_re_array_escapesubrrr rrs  zAdapter._adapt_text_arraycsdt|tr,|jddfdd|DS|dur8dSt|trX|sJdS||jv}|r`dSdS) z Adapt a boolean array parameter.r rc3s|]}|VqdSrMrr r rrrrz,Adapter._adapt_bool_array..Nr rr)rru_adapt_bool_arrayr rrrrrr rrs  zAdapter._adapt_bool_arraycsDt|tr,|jddfdd|DS|s<|dkr.rr )rru_adapt_num_arrayr rrrr rrs   zAdapter._adapt_num_arraycsJt|tr*ddfdd|DdS|dur6dSj|dd S) zAdapt a bytea array parameter.{,c3s|]}|VqdSrM)_adapt_bytea_arrayr rNrrr/sz-Adapter._adapt_bytea_array..}Nsnull\s\\)rrur rr)rrrrNrr,s zAdapter._adapt_bytea_arraycslt|tr,|jddfdd|DS|s4dSt|tsJ|j|}|j|rhd|j d|}|S)zAdapt a json array parameter.r rc3s|]}|VqdSrMrr r rrr9rz,Adapter._adapt_json_array..r rr ) rru_adapt_json_arrayr rrrrrrrrrr rr5s    zAdapter._adapt_json_arraycCs||}t|t|kr*td||j}g}t||D]x\}}|||}|dur^d}nN|shd}nDt|trttur| d}nt|}|j |rd|j d|}||q>dd |S) z)Adapt a record parameter with given type.z"Record parameter %s has wrong sizeNrrasciirr (%s)r) get_attnamesvaluesrcrrziprrrdecode_re_record_quoter_re_record_escaperrr )rOrrrrrrrr _adapt_recordBs&      zAdapter._adapt_recordNcCs|durt|ts|r"||}n||p.d}}t|dd}|rL||}|dkrVnj|dkrvt|tr|||}nJ|drt|trt|d|dd}||}nt|d|}||}|S) z'Adapt a value with known database type.NrZ __pg_str__recordz[]z_adapt_%s_arrayz _adapt_%s) rrget_simple_nameguess_simple_typegetattrrr"endswithru)rOrrsimpleZpg_strrrrrrZs&      z Adapter.adaptcCst|}||_|S)z9Create a simple database type with given attribute names.)DbTyper))r}rrrr simple_typerszAdapter.simple_typecCst|tr|jSt|S)z'Get the simple name of a database type.)rr*r) _simpletypesrrrrr%ys zAdapter.get_simple_namecCst|tr|jSiS)z5Get the attribute names of a composite database type.)rr*attnamesr-rrrrs zAdapter.get_attnamescszttWSty Yn0ttr0dSttr>dStttfrPdSttr^dStt rldStt t t t frdSttrdSttrdSttrd Sttrd Sttrd |pdfSttr|j|jfd d }d}||_|SdS)z5Try to guess which database type the given value has.rrrrrr7rrrrrcstfddtDS)Nc3s*|]"\}}t|d|fVqdS)raNrr nr)guessr+rrrszBAdapter.guess_simple_type..get_attnames..)r enumeraterNr2r+rrrrsz/Adapter.guess_simple_type..get_attnamesr#N)_simple_type_dicttypeKeyErrorrrrrrrr<r7r8r9r:rrrrFruguess_simple_base_typerr+r& _get_attnames)rrrrrr4rr&sB           zAdapter.guess_simple_typecCs:|D]0}t|tr||}n ||}|r|SqdS)z,Try to guess the base type of a given array.N)rrur8r&)rrrrrrrr8s    zAdapter.guess_simple_base_typeFcs|dur dSt|tr|St|trD|j|}ttur^|d}nt|tt t t fr^t|}t|t r||j |}d|St|tr|rdSdSt|trt|r|dkrdSd St|rd S|St|tttfr|St|tr|j|rd nd }|d fdd|DSt|tr@|jdd fdd|DSt|trd|j t|}d|St|tr|j t|}d|St|dd}|stdt||}t|ttfr||}|S)z>Adapt a value that is put into the SQL and needs to be quoted.Nrr'%s'truefalserz '-Infinity'z 'Infinity'z'NaN'z[%s]z ARRAY[%s]rc3s|]}t|ddVqdS)T)nestedNr/r rrrrrz'Adapter.adapt_inline..rc3s|]}t|VqdSrMr/r rrrrrz '%s'::jsonz '%s'::hstoreZ __pg_repr__z Do not know how to adapt type %s)rrrrr)rrrr9r7r8r:rr*rrr>r=rrr<ru adapt_inliner rrrr'rr6)rOrr=rZpg_reprrrrr>sZ                 zAdapter.adapt_inlinecCst}|j|_|S)zReturn a parameter list for parameters with known database types. The list has an add(value, typ) method that will build up the list and return either the literal value or a placeholder. )rr)rOparamsrrrparameter_listszAdapter.parameter_listc ss |gfS|rrtd|}tttfr|rP|jfddD}nn|jrttrltttfrt t krt dfddt D}nfddD}|t|;}ntt ri}t d}D]@}||=z ||Wn ty"|||<Yn0d||<q||rV|jfdd D}nT|jrtt svt dfd d tD}nfd d tD}||;}nt d ||fS) aFormat a database query using the given values and types. The optional types describe the values and must be passed as a list, tuple or string (that will be split on whitespace) when values are passed as a list or tuple, or as a dict if values are passed as a dict. If inline is set to True, then parameters will be passed inline together with the query string. z(Typed parameters must be sent separatelycsg|] }|qSrrr rr rrr rz(Adapter.format_query..z!The values and types do not matchcsg|]\}}||qSrr)r rrrrrrscsg|] }|qSrrrArBrrrrrcsi|]\}}||qSrr)r rrr rr &sz(Adapter.format_query..cs"i|]}|||qSr)r_r r)rtypesrrrrC-scsi|]}||qSrrrD)rrrrrC0sz0The values must be passed as tuple, list or dict) ValueErrorr@rrurr>rrsplitrcrrrfromkeysr7rsorted) rOcommandrrEinliner?literalsZ used_valuesrr)rrrErr format_querysf           zAdapter.format_query)N)F)NNF)-rUrVrWr frozensetrGrrrrr rr!rrrrrrZ _adapt_intZ _adapt_floatZ _adapt_moneyrrrrrZ_adapt_date_arrayrrZ_adapt_int_arrayZ_adapt_float_arrayZ_adapt_money_arrayrrr"rr+r%rr&r8r>r@rMrrrrrs\                   * / rcCsts |S|ddkS)zCast a boolean value.rr)r,rrrr cast_bool8srPcCst}|s|S||S)zCast a JSON value.)r/)rcastrrr cast_json?srRcCstpt|S)zCast a numeric value.)r-rrOrrrcast_numGsrScCsPt}|s|S|dkr"||d}|dd}ddd|D}tpJt|S)zCast a money value.r(rrcss"|]}|s|dvr|VqdS)z.-N)isdigit)r crrrrTrzcast_money..)r.rr r-r)rZpointrrr cast_moneyLs  rWcCsdd|DS)zCast an int2vector value.cSsg|] }t|qSrrr rrrrZrz#cast_int2vector..)rGrOrrrcast_int2vectorXsrYcCsh|dkrtjS|dkrtjS|}|ddkr6tjS|d}t|dkrPtjS|}t||S)zCast a date value. -infinityinfinityBCr )r7minmaxrGrc date_formatr9strptimer connectionfmtrrr cast_date]s  rfcCs$t|dkrdnd}t||S)zCast a time value.r %H:%M:%S.%f%H:%M:%S)rcr9rbr8)rrerrr cast_timeqsriz (.*)([+-].*)cCsxt|}|r|\}}nd}t|dkr0dnd}tr\|t|7}|d7}t||St||j t |dS)zCast a timetz value.rrrgrh%zr;) _re_timezonematchgroupsrc _has_timezonerr9rbrrr)rrrerrr cast_timetzzs  rpcCs|dkrtjS|dkrtjS|}|ddkr6tjS|}|drt|dkr|dd}t|d d krvtjS|d rd nd t|ddkrdnddg}n2t|ddkrtjS|t|ddkrdndg}td |d |S)zCast a timestamp value.rZr[r\r]-%Yrbrarr%d%d %b%b %drrgrh%Yrr^ ) r9r_r`rGrar(rcrrbr rcrrrcast_timestamps&  rxcCs|dkrtjS|dkrtjS|}|ddkr6tjS|}|drt|dkr|dd}t|d d krvtjS|d rd nd t|ddkrdnddg}|dd|d}}n|drt |d}|r| \|d<}nd}n|dd|d}}t|ddkrtjS|t|ddkr4dndg}t rp| t || dtd|d|Std|d|jt|dS)zCast a timestamptz value.rZr[r\r]rqrbraNrrrrsrtrurrgrhrvz%Y-rrr^rjrwrk)r9r_r`rGrar(rcrrlrmrnrorrrbr rr)rrdrerrrrcast_timestamptzs@    ryzm(?:([+-])?([0-9]+)-([0-9]+) ?)?(?:([+-]?[0-9]+)(?!:) ?)?(?:([+-])?([0-9]+):([0-9]+):([0-9]+)(?:\.([0-9]+))?)?z(?:([+-]?[0-9]+) ?years? ?)?(?:([+-]?[0-9]+) ?mons? ?)?(?:([+-]?[0-9]+) ?days? ?)?(?:([+-])?([0-9]+):([0-9]+):([0-9]+)(?:\.([0-9]+))?)?z@ ?(?:([+-]?[0-9]+) ?years? ?)?(?:([+-]?[0-9]+) ?mons? ?)?(?:([+-]?[0-9]+) ?days? ?)?(?:([+-]?[0-9]+) ?hours? ?)?(?:([+-]?[0-9]+) ?mins? ?)?(?:([+-])?([0-9]+)(?:\.([0-9]+))? ?secs?)? ?(ago)?zP(?:([+-]?[0-9]+)Y)?(?:([+-]?[0-9]+)M)?(?:([+-]?[0-9]+)D)?(?:T(?:([+-]?[0-9]+)H)?(?:([+-]?[0-9]+)M)?(?:([+-])?([0-9]+)(?:\.([0-9]+))?S)?)?c Cs8t|}|rbdd|D}|ddk}dd|D}|\}}}}}}} |r^| }| } nt|}|rdd|ddD|d }} |ddk}| rd d|Dn d d|D}|\}}}}}}} |r| }| } n(t|}|rht|rhd d|D}|d dk} dd|D}|\}}}}}}} | r| }| }| }| } nt|}|rt|rdd|D}|ddk} |d dk} dd|D}|\}}}}}}} | r| }| }| r| }| }| }| } n t d||d|d|7}t ||||| dS)zCast an interval value.cSsg|] }|pdqS0rr drrrrrz!cast_interval..rrcSsg|] }t|qSrrXr|rrrrrcSsg|] }|pdqSrzrr|rrrrrNr cSsg|]}t| qSrrXr|rrrrrcSsg|] }t|qSrrXr|rrrrrcSsg|] }|pdqSrzrr|rrrrrrcSsg|] }t|qSrrXr|rrrrrcSsg|] }|pdqSrzrr|rrrr rrcSsg|] }t|qSrrXr|rrrr rzCannot parse interval: %sim)rzrr~r{ microseconds) _re_interval_iso_8601rmrnr_re_interval_postgres_verbosegroup_re_interval_postgresany_re_interval_sql_standardrFr:) rmZsecs_agoZyearsZmonsrzrZminsZsecsZusecsZagoZ hours_agoZ years_agorrr cast_intervalsb   &     rc@seZdZdZeeeeeeeeeeeee e e e e e e eeeeeeeeeedZdZddZeddZdd Zdd d Zd d ZdddZ e!ddZ"e!ddZ#ddZ$ddZ%ddZ&ddZ'dS)raDictionary mapping database types to typecast functions. The cast functions get passed the string representation of a value in the database which they need to convert to a Python object. The passed string will never be None since NULL values are already handled before the cast function is called. Note that the basic types are already handled by the C extension. They only need to be handled here as record or array components. )rrr}rrrrrrserialrrrrrrrrrr7rr8rrrZ int2vectorranyarrayr#Ncst|tstd|j|}|r:|}||<nl|drl|dd}|}|r||<n:|}|rfdd| D} |||}||<|S)zCreate a cast function if it is not cached. Note that this class never raises a KeyError, but returns None when no special cast function exists. zInvalid type: %s_raNcsg|]}|jqSr)pgtyper rNrrrPrz)Typecasts.__missing__..) rrrdefaultsr__add_connectionrcreate_array_castrrcreate_record_cast)rOrrQZ base_castr.castsrrNrr;s"         zTypecasts.__missing__c Cs:z t|}Wnttfy$YdS0d|ddvSdS)z9Check if a typecast function needs a connection argument.FrdraN)rtrrF)rsrqrrr_needs_connectionUs  zTypecasts._needs_connectioncCs"|jr||s|St||jdS)z@Add a connection argument to the typecast function if necessary.)rd)rdrrB)rOrQrrrr_szTypecasts._add_connectioncCs ||p |Sz6Get the typecast function for the given database type.r)rOrdefaultrrrr_esz Typecasts.getcCs|t|tr|g}|dur@|D] }||d|d|dqn8t|sPtd|D]"}||||<|d|dqTdS);Set a typecast function for the specified database type(s).NrCast parameter must be callable)rrrcallablerr)rOrrQrrrrsetis  z Typecasts.setcCs<|dur|n&t|tr"|g}|D]}||dq&dS)zReset the typecasts for the specified type(s) to their defaults. When no type is specified, all typecasts will be reset. N)rrrr)rOrrrrrresetxs   zTypecasts.resetcCs |j|S)z>Get the default typecast function for the given database type.)rr_)rrrrr get_defaultszTypecasts.get_defaultcCs|t|tr|g}|j}|durF|D] }||d|d|dq"n2t|sVtd|D]}|||<|d|dqZdS)z?Set a default typecast function for the given database type(s).Nrr)rrrrrr)rrrQrrrrr set_defaults  zTypecasts.set_defaultcCsiS)zReturn the fields for the given record type. This method will be replaced with the get_attnames() method of DbTypes. rrOrrrrrszTypecasts.get_attnamescCsdS)zwReturn the current date format. This method will be replaced with the dateformat() method of DbTypes. z%Y-%m-%drrNrrr dateformatszTypecasts.dateformatcs|dfdd}|S)z1Create an array typecast for the given base cast.rcs |SrMrrbasecastr%rrrQsz)Typecasts.create_array_cast..castr)rOrrQrrrrszTypecasts.create_array_castcs&|dt||fdd}|S)z>Create a named record typecast for the given fields and casts.r#cs|SrMrrr'rr#rrrQsz*Typecasts.create_record_cast..cast)r?)rOr}fieldsrrQrrrrs zTypecasts.create_record_cast)N)N)(rUrVrWrrrPr+rrr&rRrrSrWrfrrirprxryrYrFr%r'rrdrrrrr_rrrrrrrrrrrrrrs<      rcCs t|S)z@Get the global typecast function for the given database type(s).)rrr-rrrr0sr0cCst||dS)zSet a global typecast function for the given database type(s). Note that connections cache cast functions. To be sure a global change is picked up by a running connection, call db.db_types.reset_typecast(). N)rr)rrQrrrr4sr4c@seZdZdZeddZdS)r*aClass augmenting the simple type name with additional info. The following additional information is provided: oid: the PostgreSQL type OID pgtype: the internal PostgreSQL data type name regtype: the registered PostgreSQL data type name simple: the more coarse-grained PyGreSQL type name typlen: the internal size, negative if variable typtype: b = base type, c = composite type etc. category: A = Array, b = Boolean, C = Composite etc. delim: delimiter for array types relid: corresponding table for composite types attnames: attributes for composite types cCs ||S)6Get names and types of the fields of a composite type.)r9rNrrrr.szDbType.attnamesN)rUrVrWrpropertyr.rrrrr*sr*cspeZdZdZedZfddZddZddZ dd d Z d d Z ddZ ddZ dddZddZZS)DbTypeszCache for PostgreSQL data types. This cache maps type OIDs and names to DbType objects containing information on the associated database type. z>int float num money int2 int4 int8 float4 float8 numeric moneycsXtt|t||_d|_t|_|j |j_ |j|j_ |j dkrNd|_ nd|_ dS)z%Initialize type cache for connection.F:zSELECT oid, typname, oid::pg_catalog.regtype, typlen, typtype, null as typcategory, typdelim, typrelid FROM pg_catalog.pg_type WHERE oid OPERATOR(pg_catalog.=) %s::pg_catalog.regtypezSELECT oid, typname, oid::pg_catalog.regtype, typlen, typtype, typcategory, typdelim, typrelid FROM pg_catalog.pg_type WHERE oid OPERATOR(pg_catalog.=) %s::pg_catalog.regtypeN) superrrrr_db _regtypesr _typecastsrrdserver_version_query_pg_typer __class__rrrs    zDbTypes.__init__c Cst||vr||S|rdnt|} t|jr,|n| } || _| | _|| _|| _|| _|| _|| _ || _ || _ |j | _ | S)z3Create a PostgreSQL type name with additional info.r#)r,r*rrr)rregtypetyplentyptypecategorydelimrelidrr9) rOrrrrrrrrr)rrrrrsz DbTypes.addcCs~z*|jtd|f}|j||f}Wnty@d}Yn0|sTtd|f|d}|j|}|||j<||j <|S)z8Get the type info from the database if it is not cached.$1NzType %s could not be foundr) rrrquery getresultr!r7rrr)rOrrr[rrrrrs   zDbTypes.__missing__NcCs&z ||WSty |YS0dS)z&Get the type even if it is not cached.N)r7)rOrrrrrr_%s  z DbTypes.getcCs8t|ts||}|sdS|js&dS|jj|jddS)rNF)with_oid)rr*r_rrrrrrrr,s  zDbTypes.get_attnamescCs |j|Sr)rr_rrrrr06szDbTypes.get_typecastcCs|j||dS)rN)rr)rOrrQrrrr4:szDbTypes.set_typecastcCs|j|dS)z?Reset the typecast function for the specified database type(s).N)rrrrrrreset_typecast>szDbTypes.reset_typecastcCsT|dur dSt|ts*||}|r*|j}|r8||nd}|rH|turL|S||S)z:Cast the given value according to the given database type.N)rr*r_rr0r)rOrrrQrrrtypecastBs   zDbTypes.typecast)N)N)rUrVrWrrNrG _num_typesrrrr_rr0r4rr __classcell__rrrrrs     rz^[A-Za-z][_a-zA-Z0-9]*$irmcCsLztd|ddjWStyFddtt|D}td|jYS0dS)z>Get a namedtuple factory for row results with the given names.ZRowT)renamecSsg|]}d|fqS)z column_%dr)r r1rrrr`rz _row_factory..N)r?_makerFrangerc)namesrrr _row_factoryZs  rcCst|tjadS)zwChange the size of the namedtuple factory cache. If maxsize is set to None, the cache can grow without bound. N)rJrrlrmrrrset_row_factory_sizedsrccs&|}|D]}tt||Vq dS)z0Get query result as an iterator of dictionaries.N) listfieldsrr)rrrrrr _dictiterpsrccs$t|}|D]}||VqdS)z0Get query result as an iterator of named tuples.N)rr)rrowrrrr _namediterws rcCst|t|S)z0Get next row from query result as a named tuple.)rrnextrrrr _namednext~srccs|D]}|dVqdS)z1Get query result as an iterator of scalar values.rNr)rrrrr _scalaritersrc@s0eZdZdZddZddZddZdd Zd S) _MemoryQueryz)Class that embodies a given query result.cCs||_t||_dS)z4Create query from given result rows and field names.N)resultrr)rOrrrrrrsz_MemoryQuery.__init__cCs|jS)z,Return the stored field names of this query.)rrNrrrrsz_MemoryQuery.listfieldscCs|jS)z'Return the stored result of this query.)rrNrrrrsz_MemoryQuery.getresultcCs t|jSrM)iterrrNrrr__iter__sz_MemoryQuery.__iter__N)rUrVrWrrrrrrrrrrs rcCs||}d|_|S)z3Return DatabaseError with empty sqlstate attribute.N)Zsqlstate)msgrrrrr _db_errorsrcCs t|tS)zReturn InternalError.)rr rrrr _int_errorsrcCs t|tS)zReturn ProgrammingError.)rr!rrrr _prg_errorsrc@sLeZdZdZdddZddZddZd d Zd d ZdddZ ddZ dS)rz;A PostgreSQL client-side asynchronous notification handler.NcCsB||_||_|pd||_d|_||_|dur2i}||_||_dS)aInitialize the notification handler. You must pass a PyGreSQL database connection, the name of an event (notification channel) to listen for and a callback function. You can also specify a dictionary arg_dict that will be passed as the single argument to the callback function, and a timeout value in seconds (a floating point number denotes fractions of seconds). If it is absent or None, the callers will never time out. If the timeout is reached, the callback function will be called with a single argument that is None. If you set the timeout to zero, the handler will poll notifications synchronously and return. You can specify the name of the event that will be used to signal the handler to stop listening as stop_event. By default, it will be the event name prefixed with 'stop_'. zstop_%sFN)revent stop_event listeningcallbackarg_dicttimeout)rOrrrrrrrrrrszNotificationHandler.__init__cCs |dSrM)unlistenrNrrr__del__szNotificationHandler.__del__cCs"|jr||jd|_dS)z(Stop listening and close the connection.N)rrcloserNrrrrs zNotificationHandler.closecCs4|js0|jd|j|jd|jd|_dS)z1Start listening for the event and the stop event.z listen "%s"TNrrrrrrNrrrlistenszNotificationHandler.listencCs4|jr0|jd|j|jd|jd|_dS)z0Stop listening for the event and the stop event.z unlisten "%s"FNrrNrrrrszNotificationHandler.unlistenFcCsB|jr>|s|j}d|r|jn|j}|r4|d|7}||SdS)aGenerate a notification. Optionally, you can pass a payload with the notification. If you set the stop flag, a stop notification will be sent that will cause the handler to stop listening. Note: If the notification handler is running in another thread, you must pass a different database connection since PyGreSQL database connections are not thread-safe. z notify "%s"z, '%s'N)rrrrr)rOrstoppayloadrrrrnotifys  zNotificationHandler.notifycCs||jdk}|s"|jg}|jr|sBt|gg|jdr|jr|j}|sXq|\}}}||j|jfvr| t d|j|j|f||jkr| |j j |||d| |j qB|rqq"| | dq"dS)asInvoke the notification handler. The handler is a loop that listens for notifications on the event and stop event channels. When either of these notifications are received, its associated 'pid', 'event' and 'extra' (the payload passed with the notification) are inserted into its arg_dict dictionary and the callback is invoked with this dictionary as a single argument. When the handler receives a stop event, it stops listening to both events and return. In the special case that the timeout of the handler has been set to zero, the handler will poll all events synchronously and return. If will keep listening until it receives a stop event. Note: If you run this loop in another thread, don't use the same database connection for database operations in the main thread. rz1Listening for "%s" and "%s", but notified of "%s")pidrextraN)rrrfilenorselectZ getnotifyrrrrrrr)rOpollZrlistZnoticerrrrrr__call__s4      zNotificationHandler.__call__)NNNN)NFN) rUrVrWrrrrrrrrrrrrrs  rcOstjdtddt|i|S)z8Same as NotificationHandler, under the traditional name.z7pgnotify is deprecated, use NotificationHandler insteadrb) stacklevel)warningswarnDeprecationWarningrrrrrpgnotify1src@seZdZdZdZddZddZddZd d Zd d Z d dZ ddZ ddZ e ddZe ddZe eZe ddZe ddZddZddZdd Zd`d!d"ZeZd#d$ZeZdad%d&ZeZd'd(Zd)d*Zd+d,Zdbd.d/Zd0d1Z dcd2d3Z!d4d5Z"d6d7Z#ddd8d9Z$ded:d;Z%dfdd?Z'dgd@dAZ(dhdBdCZ)didEdFZ*djdGdHZ+dkdJdKZ,dldLdMZ-dmdNdOZ.dndPdQZ/dodRdSZ0dpdTdUZ1dqdVdWZ2drdXdYZ3dsdZd[Z4dtd\d]Z5dud^d_Z6dS)vrz*Wrapper class for the _pg connection type.NcOs|st|dkr|d}n|s6t|dkr6|d}nd}|rnt|trP|j}nz |j}WntylYn0|rt|drt|dst|i|}||f|_ d|_ n ||_ d|_ ||_|j|_ d|_ i|_ i|_i|_t||_t||_|jdkrd |_nd |_||jjd|_dS) zCreate a new connection You can pass either the connection parameters or an existing _pg or pgdb connection. This allows you to use the methods of the classic pg interface with a DB-API 2 pgdb connection. rarrNrTFraSSELECT a.attname, t.oid, t.typname, t.oid::pg_catalog.regtype, t.typlen, t.typtype, null as typcategory, t.typdelim, t.typrelid FROM pg_catalog.pg_attribute a JOIN pg_catalog.pg_type t ON t.oid OPERATOR(pg_catalog.=) a.atttypid WHERE a.attrelid OPERATOR(pg_catalog.=) %s::pg_catalog.regclass AND %s AND NOT a.attisdropped ORDER BY a.attnumaMSELECT a.attname, t.oid, t.typname, t.oid::pg_catalog.regtype, t.typlen, t.typtype, t.typcategory, t.typdelim, t.typrelid FROM pg_catalog.pg_attribute a JOIN pg_catalog.pg_type t ON t.oid OPERATOR(pg_catalog.=) a.atttypid WHERE a.attrelid OPERATOR(pg_catalog.=) %s::pg_catalog.regclass AND %s AND NOT a.attisdropped ORDER BY a.attnum)rcr_rrrZ_cnxAttributeErrorhasattrr(_db_args _closeableZdbnamer _attnames_pkeys _privilegesradapterrdbtypesr_query_attnames set_cast_hookrdebug)rOrqrrrrrr?sB           z DB.__init__cCs|jrt|j|StddS)NConnection is not valid)rr'rrOr}rrr __getattr__s zDB.__getattr__cCs0t|jj}||j|t|jt|SrM)rr__dict__rdirrrI)rOattrsrrr__dir__s  z DB.__dir__cCs ||S)z9Enter the runtime context. This will start a transaction.)beginrNrrrrPsz DB.__enter__cCs.|dur"|dur"|dur"|n|dS)z8Exit the runtime context. This will end the transaction.N)commitrollback)rOetZevtbrrrrTs z DB.__exit__cCsrz |j}Wnty d}Yn0|rnz|dWntyFYn0|jrnz |WntylYn0dSrM)rrrrrrr rrrrrs      z DB.__del__cGsv|jrrddd|D}t|jtr6t|j|n.writeN)rr rrprintrrr)rOrqrrrr _do_debugs    z DB._do_debugcCsd|vr||}|S)aEscape a qualified name. Escapes the name for use as an SQL identifier, unless the name contains a dot, in which case the name is ambiguous (could be a qualified name or just a name with a dot in it) and must be quoted manually by the caller. r)escape_identifier)rOrrrr_escape_qualified_names zDB._escape_qualified_namecCstrt|S|rdSdS)z%Get boolean value corresponding to d.rr)r,rr}rrr _make_boolsz DB._make_boolcCsdddt|dDS)z'Create a human readable parameter list., css|]\}}d||fVqdS)z$%d=%rNrr0rrrrrz"DB._list_params..ra)r r3)r?rrr _list_paramsszDB._list_paramscCstpt|S)z.Decode a JSON string coming from the database.)r/ jsondecode)rrrr decode_jsonszDB.decode_jsoncCst|S)z(Encode a JSON string for use within SQL.)rr rrrrszDB.encode_jsoncCsN|j}|rBz|dWnty*Yn0|jr:|d|_ntddS)zClose the database connection.NConnection already closed)rrrrrrrrrrrs zDB.closecCs|jr|jntddS)zReset connection with current parameters. All derived queries and large objects derived from this connection will not be usable after this call. rN)rrrrNrrrrs zDB.resetcCs^|jrRt|jdi|jd}|jr<|jd|j||jj||_n|j|_dS)zReopen connection to the database. Used in case we need another connection to the same database. Note that we can still reopen a database that we have closed. rraN)rr(rrrrrrrrrrreopens  z DB.reopencCsd}|r|d|7}||S)zBegin a transaction.ZBEGINrwr)rOmodeqstrrrrrs zDB.begincCs |dS)zCommit the current transaction.ZCOMMITrrNrrrrsz DB.commitcCsd}|r|d|7}||S)z"Roll back the current transaction.ZROLLBACKz TO r)rOr}rrrrr"s z DB.rollbackcCs|d|S)z6Define a new savepoint within the current transaction.z SAVEPOINT rrrrr savepoint+sz DB.savepointcCs|d|S)z'Destroy a previously defined savepoint.zRELEASE rrrrrrelease/sz DB.releasecCsNt|tr|g}d}n@t|ttfr*g}n,t|ttfr>i}nt|trN|}ntd|sbtdt|trping}|D]x}t|tr| nd}|std|dkrd}|j | }dd|D}qJt|tr|||<qx| |qx|D]R}d |f}|j |}|dur$|}qt|tr<| |q||||<q|S) a/Get the value of a run-time parameter. If the parameter is a string, the return value will also be a string that is the current setting of the run-time parameter with that name. You can get several parameters at once by passing a list, set or dict. When passing a list of parameter names, the return value will be a corresponding list of parameter settings. When passing a set of parameter names, a new dict will be returned, mapping these parameter names to their settings. Finally, if you pass a dict as parameter, its values will be set to the current parameter settings corresponding to its keys. By passing the special name 'all' as the parameter, you can get a dict of all existing configuration parameters. N1The parameter must be a string, list, set or dictNo parameter has been specifiedInvalid parameterallzSHOW ALLcSsi|]}|d|dqS)rrarrArrrrC[rz$DB.get_parameter..zSHOW %s)rrrurrrNrrstriprrrrr singlescalar)rO parameterrr?rrrrrrr get_parameter3sP         zDB.get_parameterFcCst|tr||i}nt|ttfrNt|ttfr@tt||}qt||}nt|ttfrt|ttttfrt|}t |dkr| }|dust|tst dt||}n$t|tr|durt dnt d|st di}| D]d\}}t|tr|nd}|s t d|dkrJ|durCrzDB.pkey..rcss|]}|dVqdS)rNrr rrrrrDrzDB.pkey..) rrrr7rrrrrcrIrr)rOrZ compositeflushZpkeyspkeyrrr)rr-s.          zDB.pkeycCsdd|jdDS)z$Get list of databases in the system.cSsg|] }|dqSrr)r rrrrrNrz$DB.get_databases..z*SELECT datname FROM pg_catalog.pg_database)rrrrNrrr get_databasesLs zDB.get_databasescCslg}|r&|dddd|D|s4|d|rFdd|nd}d |}d d |j|DS) a`Get list of relations in connected database of specified kinds. If kinds is None or empty, all kinds of relations are returned. Otherwise kinds can be a string or sequence of type letters specifying which kind of relations you want to list. Set the system flag if you want to get the system relations as well. zr.relkind IN (%s)rcss|]}d|VqdS)r:Nrr rrrrr]rz#DB.get_relations..z?s.nspname NOT SIMILAR TO 'pg/_%|information/_schema' ESCAPE '/'z WHERE %s AND raSELECT pg_catalog.quote_ident(s.nspname) OPERATOR(pg_catalog.||) '.' OPERATOR(pg_catalog.||) pg_catalog.quote_ident(r.relname) FROM pg_catalog.pg_class r JOIN pg_catalog.pg_namespace s ON s.oid OPERATOR(pg_catalog.=) r.relnamespace%s ORDER BY s.nspname, r.relnamecSsg|] }|dqSr.r)r rrrrrhrz$DB.get_relations..)rr rrr)rOZkindssystemwhererrrr get_relationsQs  zDB.get_relationscCs |d|S)zReturn list of tables in connected database. Set the system flag if you want to get the system tables as well. r)r4)rOr2rrr get_tablesjsz DB.get_tablesTcs|j}|r||dz ||}Wnrtyd}|rFd|}|jtd||f}|j||f}|j fdd|D}t |}|||<Yn0|S)atGiven the name of a table, dig out the set of attribute names. Returns a read-only dictionary of attribute names (the names are the keys, the values are the names of the attributes' types) with the column names in the proper order if you iterate over it. If flush is set, then the internal cache for attribute names will be flushed. This may be necessary after the database schema or the search path has been changed. By default, only a limited number of simple types will be returned. You can get the registered types after calling use_regtypes(True). z#The attnames cache has been flushedz!a.attnum OPERATOR(pg_catalog.>) 0z.(%s OR a.attname OPERATOR(pg_catalog.=) 'oid')rc3s(|] }|dj|ddfVqdS)rraNrB)r r}rErrrrz"DB.get_attnames..) rrrr7rrrrrrr)rOrrr,r.rrrr6rrqs"   zDB.get_attnamescCsH|dur|jjSt|}||jjkr@||j_|j|j|SdS)z;Use registered type names instead of simplified type names.N)rrrrr)rOZregtypesrrr use_regtypess   zDB.use_regtypesrcCs|j}|r||d|}z|||f}WnRtydtd|f}|j|||f}|| dk}||||f<Yn0|S)zCheck whether current user has specified table privilege. If flush is set, then the internal cache for table privileges will be flushed. This may be necessary after privileges have been changed. z%The privileges cache has been flushedz-SELECT pg_catalog.has_table_privilege(%s, $2)rT) rrrrr7rrrrr )rOrZ privileger,Z privilegesretrrrrhas_table_privileges  zDB.has_table_privilegec s>|dr|dd}||dvr4t|nd}|rLt|trL|f}|rvttrv|vrvdvrv|d<|sz||d}Wn:ty|rttrdvrd}n t d|Yn40ttrt | s|rdvrd}ntdttsBtt t fsgt|tkr4td tt||j}|j|j|rbd nd}d fd d |D}dvr|rd|<d=d||||f}||||j||}|} | s|dd}td||||f| dD]&\} } |r.| dkr.|} | | <qS)aGet a row from a database table or view. This method is the basic mechanism to get a single row. It assumes that the keyname specifies a unique row. It must be the name of a single column or a tuple of column names. If the keyname is not specified, then the primary key for the table is used. If row is a dictionary, then the value for the key is taken from it. Otherwise, the row must be a single value or a tuple of values corresponding to the passed keyname or primary key. The fetched row from the table will be returned as a new dictionary or used to replace the existing values when row was passed as a dictionary. The OID is also put into the dictionary if the table has one, but in order to allow the caller to work with multiple tables, it is munged as "oid(table)" using the actual name of the table. rNr\rTrr&z*Missing value in row for specified keynamez,Differing number of items in keyname and rowoid, *r1c3s,|]$}d|||fVqdSz%s OPERATOR(pg_catalog.=) %sNrr0rr.colrrrrszDB.get..z"SELECT %s FROM %s WHERE %s LIMIT 1zOPERATOR(pg_catalog.=)=z%No such record in %s where %s with %sr)r(rstriprrrrrr-r7rrissubsetrrurcrrr@rrr r rrr dictresultrrr r) rOrrkeynameqoidr?whatr3rr[r1rrr=rr_sp              zDB.getcKsX|dr|dd}|dur&i}||d|vr>|d=||}d|vrXt|nd}|j}|j}|j}gg} } |D]2} | |vr| || | ||| || q| st dd | d | } } |rdnd} d| || | | f} | | ||j| |} | }|rT|d D]&\} }|rH| dkrH|} ||| <q,|S) adInsert a row into a database table. This method inserts a row into a table. The name of the table must be passed as the first parameter. The other parameters are used for providing the data of the row that shall be inserted into the table. If a dictionary is supplied as the second parameter, it starts with that. Otherwise it uses a blank dictionary. Either way the dictionary is updated from the keywords. The dictionary is then reloaded with the values actually inserted in order to pick up values modified by rules, triggers, etc. rNr\rz$No column found that can be insertedr r;z,INSERT INTO %s (%s) VALUES (%s) RETURNING %sr)r(r@rrrrr@rrrrr r rrrrBr)rOrrrr.rDr?rr>rrr1r8rr[rrrrinsertsB        z DB.insertc s|dr|dd}||dvr4t|nd}durFindvrTd=||r~|vr~dvr~|d<|rdvrd}nFz||d}Wntytd|Yn0t| std|j }|j |j d fd d |D}dvr,|r&d|<d=g}t|}D]>} | vr<| |vr<|d | | | fq<|sSd |}|rdnd} d||||| f} || ||j| |} | } | r| dD]&\} } |r| dkr|} | | <qS)aUpdate an existing row in a database table. Similar to insert, but updates an existing row. The update is based on the primary key of the table or the OID value as munged by get() or passed as keyword. The OID will take precedence if provided, so that it is possible to update the primary key itself. The dictionary is then modified to reflect any changes caused by the update due to triggers, rules, default values, etc. rNr\rr:Tr&$Missing value for primary key in rowr1c3s,|]$}d|||fVqdSr<rr0r=rrrP szDB.update..%s = %sr r;z&UPDATE %s SET %s WHERE %s RETURNING %sr)r(r@rrrr-r7rrrArr@rrr rr rrrrBr)rOrrrrDrCr?r3rr1r8rr[rrr=rr- sd         (   z DB.updatec sp|dr|dd}|dur&i}d|vr4|d=d|vrB|d=||}d|vr\t|nd}|j}|j}|jgg}} |D]2} | |vr|| | ||| || qd |d | }} z| |d} Wn t yt d|Yn0d fdd | D} g} t | } | d|D]T} | | vr2|| | |v}|r2t|tsnd | }| d | |fq2| s|S| rd d | nd }|rdnd}d|||| | ||f}|||z|j||}Wn*ty|jdkrt dYn0|}|r`|dD]&\} }|rR| dkrR|} ||| <q6n ||||S)aInsert a row into a database table with conflict resolution This method inserts a row into a table, but instead of raising a ProgrammingError exception in case a row with the same primary key already exists, an update will be executed instead. This will be performed as a single atomic operation on the database, so race conditions can be avoided. Like the insert method, the first parameter is the name of the table and the second parameter can be used to pass the values to be inserted as a dictionary. Unlike the insert und update statement, keyword parameters are not used to modify the dictionary, but to specify which columns shall be updated in case of a conflict, and in which way: A value of False or None means the column shall not be updated, a value of True means the column shall be updated with the value that has been proposed for insertion, i.e. has been passed as value in the dictionary. Columns that are not specified by keywords but appear as keys in the dictionary are also updated like in the case keywords had been passed with the value True. So if in the case of a conflict you want to update every column that has been passed in the dictionary row, you would call upsert(table, row). If you don't want to do anything in case of a conflict, i.e. leave the existing row as it is, call upsert(table, row, **dict.fromkeys(row)). If you need more fine-grained control of what gets updated, you can also pass strings in the keyword parameters. These strings will be used as SQL expressions for the update columns. In these expressions you can refer to the value that already exists in the table by prefixing the column name with "included.", and to the value that has been proposed for insertion by prefixing the column name with the "excluded." The dictionary is modified in any case to reflect the values in the database after the operation has completed. Note: The method uses the PostgreSQL "upsert" feature which is only available since PostgreSQL 9.5. rNr\rr Tr&c3s|]}|VqdSrMrr0r>rrr rzDB.upsert..z excluded.%srHz update set %sZnothingr;zOINSERT INTO %s AS included (%s) VALUES (%s) ON CONFLICT (%s) DO %s RETURNING %siaz7Upsert operation is not supported by PostgreSQL versionr)r(r@rrrr@rrrr r-r7rrr_rrr rrrr!rrBr)rOrrrr.rDr?rrrr1rCtargetrrZdor8rr[rrIrupsertk sv,           z DB.upsertcCsp|dur i}||}|D]L\}}|dkr0q|j}|tjvrJd||<q|dkrb|d||<qd||<q|S)ahClear all the attributes to values determined by the types. Numeric types are set to 0, Booleans are set to false, and everything else is set to the empty string. If the row argument is present, it is used as the row dictionary and any entries matching attribute names are cleared with everything else left unchanged. NrrrFr)rrr)rrr )rOrrr.r1rrrrr s     zDB.clearc  s`|dr|dd}||dvr4t|nd}durFindvrTd=||r~|vr~dvr~|d<|rdvrd}nFz||d}Wntytd|Yn0t| std|j }|j |j d fd d |D}dvr,|r&d|<d=d |||f}||||j||} t| S) a#Delete an existing row in a database table. This method deletes the row from a table. It deletes based on the primary key of the table or the OID value as munged by get() or passed as keyword. The OID will take precedence if provided. The return value is the number of deleted rows (i.e. 0 if the row did not exist and 1 if the row was deleted). Note that if the row cannot be deleted because e.g. it is still referenced by another table, this method raises a ProgrammingError. rNr\rr:Tr&rGr1c3s,|]$}d|||fVqdSr<rr0r=rrr szDB.delete..zDELETE FROM %s WHERE %s)r(r@rrrr-r7rrrArr@rrr r rrrr) rOrrrrDrCr?r3rr[rr=rdelete sF           z DB.deletec Cst|tr||i}|g}n^t|ttfrTt|ttfrFtt||}qxt||}n$t|ttfrpt||}nt d|dust|t t fst d|dust|t t fst dg}|D]x}| |}|dust|t t fst d| dr|rtd|dd}||}|r*d |}||qd d |g}|rT|d |rd|d d|}|||j|S)aEmpty a table or set of tables. This method quickly removes all rows from the given table or set of tables. It has the same effect as an unqualified DELETE on each table, but since it does not actually scan the tables it is faster. Furthermore, it reclaims disk space immediately, rather than requiring a subsequent VACUUM operation. This is most useful on large tables. If restart is set to True, sequences owned by columns of the truncated table(s) are automatically restarted. If cascade is set to True, it also truncates all tables that have foreign-key references to any of the named tables. If the parameter only is not set to True, all the descendant tables (if any) will also be truncated. Optionally, a '*' can be specified after the table name to explicitly indicate that descendant tables are included. z'The table must be a string, list or setNz#Invalid type for the restart optionz#Invalid type for the cascade optionz Invalid type for the only optionrz)Contradictory table name and only optionsr\zONLY %sZTRUNCATEr zRESTART IDENTITYZCASCADErw)rrrurrrrHrrNrrrr_r(rFr@r rr rrr) rOrZrestartZcascadeonlyZtablesrurrrrtruncate sJ         z DB.truncatec Csv|s td|r.)rrrurr maprextendr-r7r!rrrrrZ namedresult) rOrrEr3orderlimitryscalarrr[rrr get_as_listS sH      zDB.get_as_listc  s|s td|sDz||d}Wn"ttfyBtd|Yn0t|trV|g}nt|ttfsltd|rt|ttfrd t t |}|dur|}nd}d|d |g} |rt|ttfrd t t |}| d |g|dur|}|rt|ttfrd t t |}| d |g|r0| d ||rD| d|d | } || |j| } | } |rvtnt} | s| St|| } | stdgg} t| D]"\}}|vr| n |qt| dk}t| }t || }|rddd}n tdk}|s.|r8t}ndfdd}d}t || }|sf|r|rztt||}|rfdd| D} tt|| }| t||S)a-Get a table as a dictionary. This method is similar to get_as_list(), but returns the table as a Python dict instead of a Python list, which can be even more convenient. The primary key column(s) of the table will be used as the keys of the dictionary, while the other column(s) will be the corresponding values. The keys will be named tuples if the table has a composite primary key. The rows will be also named tuples unless the 'scalar' option has been set to True. With the optional parameter 'keyname' you can specify an alternative set of columns to be used as the keys of the dictionary. It must be set as a string, list or a tuple. If the Python version supports it, the dictionary will be an OrderedDict using the order specified with the 'order' parameter or the key column(s) if not specified. You can set 'order' to False if you don't care about the ordering. In this case the returned dictionary will be an ordinary one. rPTr&z+The keyname must be a string, list or tupler NrrQrRr1rSrTrUrVrwzMissing keyname in rowraFrcs |fSrMrr()rowindrrgetrow szDB.get_as_dict..getrowcsg|]}|vr|qSrr)r r)keysetrrr rz"DB.get_as_dict..)rr-r7r!rrrrurr rWrrXrrrrrr@rrrrAr3rcrArrr)rOrrCrEr3rYrZryr[rr[rrZkeyindirZkeytupleZgetkeyrZrowtupler^Zrowsr)r_r]r get_as_dict s                zDB.get_as_dictcCst||||||S)z:Get notification handler that will run the given callback.)r)rOrrrrrrrrnotification_handler szDB.notification_handler)N)N)NF)NNF)N)N)FF)NF)F)TF)N)rF)N)N)N)N)N)N)FFF)NNNNNF)NNNNNNF)NNN)7rUrVrWrrrrrrPrTrrr rr r r+rrrrrrstartrendrabortrrrr rr!r"r#r$r%r-r/r4r5rr7r9r_rFrrKrrLrOr\rarbrrrrr:szE         : J  -    M . > g  1 8 B `r__main__zPyGreSQL versionr)rX)r __future__rr_pg ImportErrorerr r}sysenvironrGpathseppaths version_infor Zadd_dll_directoryabspathr5r6__all__rrrr9r7r8r:r;Zdecimalr<mathr=r> collectionsr?r@operatorrA functoolsrBrerCrrrDrrErrrFtypingrGrHrIrr NameErrorrrrrrrJrK_threadrLinspectrorprtrwutcrorrrrrrrrrr,rr5rrurrrrrPrRrSrWrYrfrirlrprxryrrrrrrr0r4r*rZ _re_fieldnamerrrrrrrrrrrr1r2r3rkrrrrUrrrrrsF     0          J  /  % ;" n   z L