....................................../////.===Shadow-Here===./////................................................ > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < ------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RIFF¤ WEBPVP8 ˜ ðÑ *ôô>‘HŸK¥¤"§£±¨àð enü¹%½_F‘åè¿2ºQú³íªú`N¿­3ÿƒügµJžaÿ¯ÿ°~¼ÎùnúîÞÖô•òíôÁÉß®Sm¥Ü/ ‡ó˜f£Ùà<˜„xëJ¢Ù€SO3x<ªÔ©4¿+ç¶A`q@Ì“Úñè™ÍÿJÌ´ª-˜ÆtÊÛL]Ïq*‘Ý”ì#ŸÌÏãY]@ê`¿ /ªfkØB4·®£ó z—Üw¥Pxù–ÞLШKÇN¾AkÙTf½è'‰g gÆv›Øuh~ a˜Z— ïj*á¥t d£“uÒ ¨`K˜¹ßþ]b>˜]_ÏÔ6W—è2r4x•íÖ…"ƒÖNîä!¦å Ú}ýxGøÌ —@ ;ÆÚŠ=ɾ1ý8lªË¥ô ^yf®Œ¢u&2©nÙÇ›ñÂñŒ³ aPo['½»øFùà­+4ê“$!lövlüÞ=;N®3ð‚õ›DÉKòÞ>ÄÍ ¥ˆuߤ#ˆ$6ù™¥îЇy’ÍB¼ çxÛ;X"WL£R÷͝*ó-¶Zu}º.s¸sšXqù–DþÿvªhüïwyŸ ¯é³lÀ:KCûÄ£Ëá\…­ ~—ýóî ¼ûûÜTÓüÇy…ŽÆvc»¾×U ñ¸žþоP÷¦ó:Ò¨¨5;Ð#&#ÖúñläÿÁœ GxÉ­/ñ‡áQðìYÉtÒw޼GÔ´zàÒò ð*ëzƒ•4~H]Ø‹f ñÓÈñ`NåWçs'ÆÏW^ø¹!XžµmQ5ÃËoLœÎ: ÞËÍ¥J ù…î èo£ßPÎñ¶ž8.Œ]ʵ~5›ÙË-ù*8ÙÖß±~ ©¹rÓê‚j¶d¸{^Q'˜±Crß ÚH—#¥¥QlÀ×ëã‡DÜ«èî þ&Çæžî;ŽÏºò6ÒLÃXy&ZŒ'j‚¢Ù€IßÚù+–MGi‰*jE€‘JcÜ ÓÌ EÏÚj]o˜ Þr <¾U ûŪæÍ/šÝH¥˜b”¼ ÁñßX GP›ï2›4WŠÏà×£…íÓk†¦H·ÅíMh–*nó÷à]ÁjCº€b7<ب‹¨5車bp2:Á[UªM„QŒçiNMa#<5›áËó¸HýÊ"…×Éw¹¦ì2º–x<›»a±¸3Weü®FÝ⑱ö–î–³|LPÈ~çð~Çå‡|º kD¢µÏàÆAI %1À% ¹Ò – ”ϝS¦‰4&¶£°à Öý”û_Ò Áw°A«Å€?mÇÛgHÉ/8)á¾ÛìáöŽP í¨PŸNÙµº¦‡§Ùš"ÿ«>+ªÕ`Ê÷‡‚ß Õû˜þãÇ-PÍ.¾XV‘€ dÜ"þ4¹ ±Oú‘©t¥¦FªÄÃÄ•b‚znýu½—#cDs˜ÃiÑOˆñ×QO=*IAÊ,¶ŽZƒ;‡wøXè%EÐk:F±Ú” .Ѽ+Áu&Ç`."pÈÉw o&¿dE6‘’EqTuK@Ì¥ã™À(Êk(h‰,H}RÀIXÛš3µ1©_OqÚÒJAñ$ÊÙÜ;D3çŒ[þùœh¬Ã³™ö6ç†NY".Ú‰ï[ªŸŒ '²Ð öø_¨ÂÉ9ué¶³ÒŠõTàîMØ#û¯gN‡bÙ놚X„ö …ÉeüÌ^J ‹€.œ$Æ)βÄeæW#óüßĺŸ€ ÀzwV 9oä»f4V*uB «Ë†¹ì¯žR霓æHXa=&“I4K;¯ç‹h×·"UŠ~<•╪Vêª&ÍSÃÆÅ?ÔqÎ*mTM ˜›µwêd#[C¡©§‘D<©àb†–ÁœøvH/,í:¯( ²£|4-„Æövv„Yͼ™^Á$ˆ„¢Û[6yB.åH*V¨æ?$=˜Ñ€•ñ·­(VlŸ‘ nÀt8W÷´Bûba?q9ú¶Xƒl«ÿ\ù¶’þòUÐj/õ¢Ìµ³g$ƒÎR!¸»|Oߍë’BhîÚÑ¢ñåŒJ„®„£2Ð3•ô02Nt…!£Í]Ïc½Qÿ?ˆ<&ÃA¾Ú,JˆijÌ#5yz„‰Î|ÊŽ5QÏ:‹ÐaóVÔxW—CpeÏzÐïíçôÿÅ_[hãsÐ_/ŽTÝ?BîˆííV$<¿i>²F¬_Eß¿ †bÊŒº­ÿ®Z H“C}”¬,Mp ý/Bá£w>˜YV°aƒúh+cŠ- r/[%|üUMHäQ°X»|û/@|°¥Ð !BÔ Ç¢Ä©š+Õì D«7ìN¶ŽðÔ " ƶ’ÖçtA‰Û×}{tþz­¾GÍ›k¹OEJR$ Â׃ «ëÁ"oÉôž$oUK(Ä)Ãz³Ê-‹êN[Ò3Œñbï8P 4ƒ×q¢bo|?<ÛX¬òÄͰL–±›(™ûG?ýË©ÚÄ–ÂDØÐ_Ç¡ô ¾–ÄÏø ×e8Ë©$ÄF¹Å‹ì[©óìl:F¾f´‹‹Xì²ï®\¬ôùƒ ÿat¥óèÒùHß0äe‚;ü×h:ÆWðHž=Ã8骣"kœ'Y?³}Tûè€>?0l›e1Lòñ„aæKÆw…hÖŠùW…ÈÆÄ0ši·›[pcwËþñiêíY/~-Á5˜!¿†A›™Mÿþ(±“t@â“ö2­´TG5yé]çå僳 .·ÍïçÝ7UÚ±Ð/Nè»,_Ï ùdj7\ï Wì4›„»c¸àešg#ÒÊ⥭áØo5‘?ÌdÝô¯ ¹kzsƒ=´#ëÉK›Ø´±-¥eW?‡çßtòTã…$Ý+qÿ±ƒ÷_3Ô¥í÷:æ–ž<·Ö‡‰Å¢ š‡%Ô—utÌÈìðžgÖÀz²À—ï÷Óîäõ{K'´È÷³yaÏÁjƒô}ž§®æÊydÕÈë5¯èˆõvÕ©ã*çD„ “z„Ó‡^^xÂ3M§A´JG‚öï 3W'ˆ.OvXè¡ÊÕª?5º7†˜(˜Ç¶#çê’¶!ÌdZK§æ 0fãaN]òY³RV ™î$®K2R¨`W!1Ôó\;Ý ýB%qæK•&ÓÈe9È0êI±žeŸß -ú@žQr¦ ö4»M¼Áè¹µmw 9 EÆE_°2ó„ŸXKWÁ×Hóì^´²GѝF©óäR†¦‰ç"V»eØ<3ùd3ÿÚ¤Žú“Gi" —‘_ÙËÎ~Üö¯¥½Î»üŸEÚŽåmÞþí ;ÞólËΦMzA"Âf(´òá;Éï(/7½ûñÌ­cïÕçлþÝz¾-ÍvÑ“pH­–ðÓj$¸Äû¤‚‘ãUBË-n“2åPkS5&‹Â|+g^œ®Ì͆d!OïäîU«c;{Û!ÅŽ«ëZ9Ókóˆ]¯ƒ›né `ÇÒ+tÆš (ØKá¾—=3œ®•vuMñg²\ï Ec€ 05±d™‡×iÇ×›UúvÌ¢£Èþ¡ÕØô¶ßÎA"ß±#Ö²ˆÊŸ¦*Ä~ij|àø.-¼'»Ú¥£h ofº¦‡VsR=N½„Î v˜Z*SÌ{=jÑB‹tê…;’HžH¯8–îDù8ñ¢|Q•bÛçš–‹m³“ê¨ åÏ^m¬Žãþ©ïêO‡½6] µÆ„Ooòü ²x}N¦Ë3ïé¿»€›HA˜m%çÞ/¿í7Fø“‹léUk)É°Œµ8Q8›:ÀŠeT*šõ~ôڝG6 ¢}`ùH­–”¡k ‰P1>š†®9z11!X wKfmÁ¦xÑ,N1Q”–æB¶M…ÒÃv6SMˆhU¬ÊPŽï‘öj=·CŒ¯u¹ƒVIЃsx4’ömÛýcå¡¶7ßŠß 57^\wÒÐÆ k§h,Œý î«q^R½3]J¸ÇðN ‚çU¬ôº^Áì} ³f©Õœ§ˆã:FÄÈ‚é(€™?àýÓüè1Gô£¼éj‚OÅñ  #>×—ßtà 0G¥Åa뀐kßhc™À_ÉñÞ#±)GD" YîäË-ÿÙ̪ ¹™a¯´¢E\ÝÒö‚;™„ë]_ p8‰o¡ñ+^÷ 3‘'dT4œŽ ðVë½° :¬víÑ«£tßÚS-3¶“þ2 †üüʨòrš¹M{É_¤`Û¨0ìjœøJ‡:÷ÃáZ˜†@GP&œÑDGÏs¡þ¦þDGú‘1Yá9Ôþ¼ ûø…§÷8&–ÜÑnÄ_m®^üÆ`;ÉVÁJ£?â€-ßê}suÍ2sõA NÌúA磸‘îÿÚ»ƒìö·á¿±tÑÐ"Tÿü˜[@/äj¬€uüªìù¥Ý˜á8Ý´sõj 8@rˆð äþZÇD®ÿUÏ2ùôõrBzÆÏÞž>Ì™xœ“ wiÎ×7_… ¸ \#€MɁV¶¥üÕÿPÔ9Z‡ø§É8#H:ƒ5ÀÝå9ÍIŒ5åKÙŠ÷qÄ>1AÈøžj"µÂд/ªnÀ qªã}"iŸBå˜ÓÛŽ¦…&ݧ;G@—³b¯“•"´4í¨ôM¨åñC‹ïùÉó¯ÓsSH2Ý@ßáM‡ˆKÀªÛUeø/4\gnm¥‹ŸŒ qÄ b9ÞwÒNÏ_4Ég³ú=܆‚´ •â¥õeíþkjz>éÚyU«Íӝ݃6"8/ø{=Ô¢»G¥ äUw°W«,ô—¿ãㆅү¢³xŠUû™yŒ (øSópÐ 9\åTâ»—*oG$/×ÍT†Y¿1¤Þ¢_‡ ¼ „±ÍçèSaÓ 3ÛMÁBkxs‰’R/¡¤ˆÙçª(*õ„üXÌ´ƒ E§´¬EF"Ù”R/ÐNyÆÂ^°?™6¡œïJ·±$§?º>ÖüœcNÌù¯G ‹ñ2ЁBB„^·úìaz¨k:#¨Æ¨8LÎõލ£^§S&cŒÐU€ü(‡F±Š¼&P>8ÙÁ ‰ p5?0ÊÆƒZl¸aô š¼¡}gÿ¶zÆC²¹¬ÎÖG*HB¡O<º2#ñŒAƒ–¡B˜´É$¥›É:FÀÔx¾u?XÜÏÓvN©RS{2ʈãk9rmP¼Qq̳ è¼ÐFׄ^¡Öì fE“F4A…!ì/…¦Lƒ… … $%´¾yã@CI¬ á—3PþBÏNÿ<ý°4Ü ËÃ#ØÍ~âW«rEñw‹eùMMHß²`¬Öó½íf³:‹k˜¯÷}Z!ã¿<¥,\#öµÀ¯aÒNÆIé,Ћ–lŽ#Àæ9ÀÒS·I’½-Ïp Äz¤Š Â* ­íÄ9­< h>׍3ZkËU¹§˜ŒŠ±f­’¤º³Q ÏB?‹#µíÃ¥®@(Gs«†vI¥Mµ‹Á©e~2ú³ÁP4ìÕi‚²Ê^ö@-DþÓàlÜOÍ]n"µã:žpsŽ¢:! Aõ.ç~ÓBûH÷JCÌ]õVƒd «ú´QÙEA–¯¯Œ!.ˆˆëQ±ù œ·Ì!Õâ )ùL„ÅÀlÚè5@B…o´Æ¸XÓ&Û…O«˜”_#‡ƒ„ûÈt!¤ÁÏ›ÎÝŠ?c9 â\>lÓÁVÄÑ™£eØY]:fÝ–—ù+p{™ðè û³”g±OƒÚSù£áÁÊ„ä,ï7š²G ÕÌBk)~ÑiCµ|h#u¤¶îK¨² #²vݯGãeÖ϶ú…¾múÀ¶þÔñ‚Š9'^($¤§ò “š½{éúp÷J›ušS¹áªCÂubÃH9™D™/ZöØÁ‡¦ÝÙŸ·kð*_”.C‹{áXó€‡c¡c€§/šò/&éš÷,àéJþ‰X›fµ“C¨œ®r¬"kL‰Â_q…Z–.ÉL~O µ›zn‚¹À¦Öª7\àHµšÖ %»ÇníV[¥*Õ;ƒ#½¾HK-ÖIÊdÏEÚ#=o÷Óò³´Š: Ç?{¾+9›–‘OEáU·S€˜j"ÄaÜ ŒÛWt› á–c#a»pÔZÞdŽtWê=9éöÊ¢µ~ ë ;Öe‡Œ®:bî3±ýê¢wà¼îpêñ¹¾4 zc¾ðÖÿzdêŒÑÒŝÀ‰s6¤í³ÎÙB¿OZ”+F¤á‡3@Ñëäg©·Ž ˆèª<ù@É{&S„œÕúÀA)‰h:YÀ5^ÂÓŒ°õäU\ ùËÍû#²?Xe¬tu‰^zÒÔãë¼ÛWtEtû …‚g¶Úüâî*moGè¨7%u!]PhÏd™Ý%Îx: VÒ¦ôÊD3ÀŽKÛËãvÆî…N¯ä>Eró–ð`5 Œ%u5XkñÌ*NU%¶áœÊ:Qÿú»“úzyÏ6å-၇¾ ´ ÒÊ]y žO‘w2Äøæ…H’²f±ÎÇ.ª|¥'gîV•Ü .̘¯€šòü¤U~Ù†*¢!?ò wý,}´°ÔÞnïoKq5µb!áÓ3"vAßH¡³¡·G(ÐÎ0Îò¼MG!/ài®@—¬04*`…«é8ªøøló“ˆÊ”èù¤…ßÊoÿé'ËuÌÖ5×È¡§ˆˆfŽë9}hìâ_!!¯  B&Ëö¶‰ÀAÙNVŸ Wh›¸®XÑJì¨ú“¿÷3uj²˜¨ÍÎìë±aúŠÝå¯ð*Ó¨ôJ“yºØ)m°WýOè68†ŸÏ2—‰Ïüꪫٚ¥‹l1 ø ÏÄFjêµvÌbü¦èÝx:X±¢H=MÐß—,ˆÉÇ´(9ú¾^ÅÚ4¿m‡$âX‘å%(AlZo@½¨UOÌÕ”1ø¸jÎÀÃÃ_ µ‘Ü.œº¦Ut: Æï’!=¯uwû#,“pþÇúŒø(é@?³ü¥‘Mo §—s@Œ#)§ŒùkL}NOÆêA›¸~r½¼ÙA—HJ«eˆÖ´*¡ÓpÌŸö.m<-"³ûÈ$¬_6­åf£ïÚâj1y§ÕJ½@dÞÁr&Í\Z%D£Íñ·AZ Û³øüd/ªAi†/Й~  ‡âĮҮÏh§°b—›Û«mJžòG'[ÈYýŒ¦9psl ýÁ ®±f¦x,‰½tN ‚Xª9 ÙÖH.«Lo0×?͹m¡å†Ѽ+›2ƒF ±Ê8 7Hցϓ²Æ–m9…òŸï]Â1äN†VLâCˆU .ÿ‰Ts +ÅÎx(%¦u]6AF Š ØF鈄‘ |¢¶c±soŒ/t[a¾–û:s·`i햍ê›ËchÈ…8ßÀUÜewŒðNOƒõD%q#éû\9¤x¹&UE×G¥ Í—™$ð E6-‡¼!ýpãÔM˜ Âsìe¯ñµK¢Ç¡ùôléœ4Ö£”À Š®Ðc ^¨À}ÙËŸ§›ºê{ÊuÉC ×Sr€¤’fÉ*j!úÓ’Gsùìoîßîn%ò· àc Wp÷$¨˜)û»H ×8ŽÒ€Zj¤3ÀÙºY'Ql¦py{-6íÔCeiØp‘‡XÊîÆUߢ܂ž£Xé¼Y8þ©ëgñß}é.ÎógÒ„ÃØËø¯»™§Xýy M%@NŠ À(~áÐvu7&•,Ù˜ó€uP‡^^®=_E„jt’ 403WebShell
403Webshell
Server IP : 198.54.126.4  /  Your IP : 216.73.216.163
Web Server : Apache
System : Linux host55.registrar-servers.com 4.18.0-513.18.1.lve.2.el8.x86_64 #1 SMP Sat Mar 30 15:36:11 UTC 2024 x86_64
User : aeaw ( 7508)
PHP Version : 8.1.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/hc_python/lib64/python3.12/site-packages/mysqlx/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/hc_python/lib64/python3.12/site-packages/mysqlx/expr.py
# MySQL Connector/Python - MySQL driver written in Python.
# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.

# MySQL Connector/Python is licensed under the terms of the GPLv2
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
# MySQL Connectors. There are special exceptions to the terms and
# conditions of the GPLv2 as it is applied to this software, see the
# FOSS License Exception
# <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

from .compat import STRING_TYPES, PY3
from .protobuf.mysqlx_datatypes_pb2 import Scalar
from .protobuf.mysqlx_expr_pb2 import ColumnIdentifier, DocumentPathItem, Expr
from .protobuf.mysqlx_crud_pb2 import Column, Order, Projection


if PY3:
    xrange = range


class TokenType:
    NOT = 1
    AND = 2
    OR = 3
    XOR = 4
    IS = 5
    LPAREN = 6
    RPAREN = 7
    LSQBRACKET = 8
    RSQBRACKET = 9
    BETWEEN = 10
    TRUE = 11
    NULL = 12
    FALSE = 13
    IN = 14
    LIKE = 15
    INTERVAL = 16
    REGEXP = 17
    ESCAPE = 18
    IDENT = 19
    LSTRING = 20
    LNUM = 21
    DOT = 22
    DOLLAR = 23
    COMMA = 24
    EQ = 25
    NE = 26
    GT = 27
    GE = 28
    LT = 29
    LE = 30
    BITAND = 31
    BITOR = 32
    BITXOR = 33
    LSHIFT = 34
    RSHIFT = 35
    PLUS = 36
    MINUS = 37
    MUL = 38
    DIV = 39
    HEX = 40
    BIN = 41
    NEG = 42
    BANG = 43
    MICROSECOND = 44
    SECOND = 45
    MINUTE = 46
    HOUR = 47
    DAY = 48
    WEEK = 49
    MONTH = 50
    QUARTER = 51
    YEAR = 52
    EROTEME = 53
    DOUBLESTAR = 54
    MOD = 55
    COLON = 56
    OROR = 57
    ANDAND = 58
    LCURLY = 59
    RCURLY = 60
    CAST = 61
    DOTSTAR = 62
    ORDERBY_ASC = 63
    ORDERBY_DESC = 64
    AS = 65

interval_units = set([
    TokenType.MICROSECOND,
    TokenType.SECOND,
    TokenType.MINUTE,
    TokenType.HOUR,
    TokenType.DAY,
    TokenType.WEEK,
    TokenType.MONTH,
    TokenType.QUARTER,
    TokenType.YEAR])

# map of reserved word to token type
reservedWords = {
    "and":      TokenType.AND,
    "or":       TokenType.OR,
    "xor":      TokenType.XOR,
    "is":       TokenType.IS,
    "not":      TokenType.NOT,
    "like":     TokenType.LIKE,
    "in":       TokenType.IN,
    "regexp":   TokenType.REGEXP,
    "between":  TokenType.BETWEEN,
    "interval": TokenType.INTERVAL,
    "escape":   TokenType.ESCAPE,
    "cast":     TokenType.CAST,
    "div":      TokenType.DIV,
    "hex":      TokenType.HEX,
    "bin":      TokenType.BIN,
    "true":     TokenType.TRUE,
    "false":    TokenType.FALSE,
    "null":     TokenType.NULL,
    "second":   TokenType.SECOND,
    "minute":   TokenType.MINUTE,
    "hour":     TokenType.HOUR,
    "day":      TokenType.DAY,
    "week":     TokenType.WEEK,
    "month":    TokenType.MONTH,
    "quarter":  TokenType.QUARTER,
    "year":     TokenType.YEAR,
    "microsecond": TokenType.MICROSECOND,
    "asc":      TokenType.ORDERBY_ASC,
    "desc":     TokenType.ORDERBY_DESC,
    "as":       TokenType.AS
}


class Token:
    def __init__(self, type, val, len=1):
        self.type = type
        self.val = val
        self.len = len

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        if self.type == TokenType.IDENT or self.type == TokenType.LNUM or \
           self.type == TokenType.LSTRING:
            return str(self.type) + "(" + self.val + ")"
        else:
            return str(self.type)


# static protobuf helper functions

def build_null_scalar():
    return Scalar(type=Scalar.V_NULL)


def build_double_scalar(d):
    return Scalar(type=Scalar.V_DOUBLE, v_double=d)


def build_int_scalar(i):
    return Scalar(type=Scalar.V_SINT, v_signed_int=i)


def build_string_scalar(s):
    if isinstance(s, STRING_TYPES):
        s = bytes(bytearray(s, "utf-8"))
    return Scalar(type=Scalar.V_STRING, v_string=Scalar.String(value=s))


def build_bool_scalar(b):
    s = Scalar()
    s.type = Scalar.V_BOOL
    s.v_bool = b
    return s


def build_literal_expr(anyval):
    e = Expr()
    e.type = Expr.LITERAL
    e.literal.CopyFrom(anyval)
    return e


def build_unary_op(name, param):
    e = Expr()
    e.type = Expr.OPERATOR
    e.operator.name = name
    e.operator.param.add().CopyFrom(param)
    return e


def escape_literal(string):
    return string.replace('"', '""')


class ExprParser:
    def __init__(self, string, allowRelational):
        self.string = string
        self.tokens = []
        self.pos = 0
        self._allowRelationalColumns = allowRelational
        self.placeholder_name_to_position = {}
        self.positional_placeholder_count = 0
        self.lex()

    # convencience checker for lexer
    def next_char_is(self, i, c):
        return i + 1 < len(self.string) and self.string[i + 1] == c

    def lex_number(self, pos):
        # numeric literal
        start = pos
        found_dot = False
        while pos < len(self.string) and (self.string[pos].isdigit() or
                                          self.string[pos] == "."):
            if self.string[pos] == ".":
                if found_dot is True:
                    raise ValueError("Invalid number. Found multiple '.'")
                found_dot = True
            # technically we allow more than one "." and let float()'s parsing
            # complain later
            pos = pos + 1
        val = self.string[start:pos]
        t = Token(TokenType.LNUM, val, len(val))
        return t

    def lex_alpha(self, i):
        start = i
        while i < len(self.string) and (self.string[i].isalnum() or
                                        self.string[i] == "_"):
            i = i + 1
        val = self.string[start:i]
        try:
            token = Token(reservedWords[val.lower()], val.upper(), len(val))
        except KeyError:
            token = Token(TokenType.IDENT, val, len(val))
        return token

    def lex_quoted_token(self, i):
        quote_char = self.string[i]
        val = ""
        i += 1
        start = i
        while i < len(self.string):
            c = self.string[i]
            if c == quote_char and i + 1 < len(self.string) and \
               self.string[i + 1] != quote_char:
                # break if we have a quote char that's not double
                break
            elif c == quote_char or c == "\\":
                # this quote char has to be doubled
                if i + 1 >= len(self.string):
                    break
                i = i + 1
                val = val + self.string[i]
            else:
                val = val + c
            i = i + 1
        if i >= len(self.string) or self.string[i] != quote_char:
            raise ValueError("Unterminated quoted string starting at {0}"
                             "".format(start))
        if quote_char == "`":
            return Token(TokenType.IDENT, val, len(val)+2)
        else:
            return Token(TokenType.LSTRING, val, len(val)+2)

    def lex(self):
        i = 0
        while i < len(self.string):
            c = self.string[i]
            if c.isspace():
                i += 1
                continue
            elif c.isdigit():
                token = self.lex_number(i)
            elif c.isalpha() or c == "_":
                token = self.lex_alpha(i)
            elif c == "?":
                token = Token(TokenType.EROTEME, c)
            elif c == ":":
                token = Token(TokenType.COLON, c)
            elif c == "{":
                token = Token(TokenType.LCURLY, c)
            elif c == "}":
                token = Token(TokenType.RCURLY, c)
            elif c == "+":
                token = Token(TokenType.PLUS, c)
            elif c == "-":
                Token(TokenType.MINUS, c)
            elif c == "*":
                if self.next_char_is(i, "*"):
                    token = Token(TokenType.DOUBLESTAR, "**")
                else:
                    token = Token(TokenType.MUL, c)
            elif c == "/":
                token = Token(TokenType.DIV, c)
            elif c == "$":
                token = Token(TokenType.DOLLAR, c)
            elif c == "%":
                token = Token(TokenType.MOD, c)
            elif c == "=":
                if self.next_char_is(i, "="):
                    token = Token(TokenType.EQ, "==", 2)
                else:
                    token = Token(TokenType.EQ, "==", 1)
            elif c == "&":
                if self.next_char_is(i, "&"):
                    token = Token(TokenType.ANDAND, c)
                else:
                    token = Token(TokenType.BITAND, c)
            elif c == "|":
                if self.next_char_is(i, "|"):
                    token = Token(TokenType.OROR, "||")
                else:
                    token = Token(TokenType.BITOR, c)
            elif c == "(":
                token = Token(TokenType.LPAREN, c)
            elif c == ")":
                token = Token(TokenType.RPAREN, c)
            elif c == "[":
                token = Token(TokenType.LSQBRACKET, c)
            elif c == "]":
                token = Token(TokenType.RSQBRACKET, c)
            elif c == "~":
                token = Token(TokenType.NEG, c)
            elif c == ",":
                token = Token(TokenType.COMMA, c)
            elif c == "!":
                if self.next_char_is(i, "="):
                    token = Token(TokenType.NE, "!=")
                else:
                    token = Token(TokenType.BANG, c)
            elif c == "<":
                if self.next_char_is(i, "<"):
                    token = Token(TokenType.LSHIFT, "<<")
                elif self.next_char_is(i, "="):
                    token = Token(TokenType.LE, "<=")
                else:
                    token = Token(TokenType.LT, c)
            elif c == ">":
                if self.next_char_is(i, ">"):
                    token = Token(TokenType.RSHIFT, ">>")
                elif self.next_char_is(i, "="):
                    token = Token(TokenType.GE, ">=")
                else:
                    token = Token(TokenType.GT, c)
            elif c == ".":
                if self.next_char_is(i, "*"):
                    token = Token(TokenType.DOTSTAR, ".*")
                elif i + 1 < len(self.string) and self.string[i + 1].isdigit():
                    token = self.lex_number(i)
                else:
                    token = Token(TokenType.DOT, c)
            elif c == '"' or c == "'" or c == "`":
                token = self.lex_quoted_token(i)
            else:
                raise ValueError("Unknown character at {0}".format(i))
            self.tokens.append(token)
            i += token.len

    def assert_cur_token(self, type):
        if self.pos >= len(self.tokens):
            raise ValueError("Expected token type {0} at pos {1} but no "
                             "tokens left".format(type, self.pos))
        if self.tokens[self.pos].type != type:
            raise ValueError("Expected token type {0} at pos {1} but found "
                             "type {2}".format(type, self.pos,
                                               self.tokens[self.pos]))

    def cur_token_type_is(self, type):
        return self.pos_token_type_is(self.pos, type)

    def next_token_type_is(self, type):
        return self.pos_token_type_is(self.pos + 1, type)

    def pos_token_type_is(self, pos, type):
        return pos < len(self.tokens) and self.tokens[pos].type == type

    def consume_token(self, type):
        self.assert_cur_token(type)
        v = self.tokens[self.pos].val
        self.pos = self.pos + 1
        return v

    def paren_expr_list(self):
        """Parse a paren-bounded expression list for function arguments or IN
        list and return a list of Expr objects.
        """
        exprs = []
        self.consume_token(TokenType.LPAREN)
        if not self.cur_token_type_is(TokenType.RPAREN):
            exprs.append(self.expr())
            while self.cur_token_type_is(TokenType.COMMA):
                self.pos = self.pos + 1
                exprs.append(self.expr())
        self.consume_token(TokenType.RPAREN)
        return exprs

    def identifier(self):
        self.assert_cur_token(TokenType.IDENT)
        id = Identifier()
        if self.next_token_type_is(TokenType.DOT):
            id.schema_name = self.consume_token(TokenType.IDENT)
            self.consume_token(TokenType.DOT)
        id.name = self.tokens[self.pos].val
        self.pos = self.pos + 1
        return id

    def function_call(self):
        e = Expr()
        e.type = Expr.FUNC_CALL
        e.function_call.name.CopyFrom(self.identifier())
        e.function_call.param.extend(self.paren_expr_list())
        return e

    def docpath_member(self):
        self.consume_token(TokenType.DOT)
        token = self.tokens[self.pos]

        if token.type == TokenType.IDENT:
            if token.val.startswith('`') and token.val.endswith('`'):
                raise ValueError("{0} is not a valid JSON/ECMAScript "
                                 "identifier".format(token.value))
            self.consume_token(TokenType.IDENT)
            memberName = token.val
        elif self.token.type == TokenType.LSTRING:
            self.consume_token(TokenType.LSTRING)
            memberName = token.val
        else:
            raise ValueError("Expected token type IDENT or LSTRING in JSON "
                             "path at token pos {0}".format(self.pos))
        item = DocumentPathItem(type=DocumentPathItem.MEMBER, value=memberName)
        return item

    def docpath_array_loc(self):
        self.consume_token(TokenType.LSQBRACKET)
        if self.cur_token_type_is(TokenType.MUL):
            self.consume_token(TokenType.RSQBRACKET)
            return DocumentPathItem(type=DocumentPathItem.ARRAY_INDEX_ASTERISK)
        elif self.cur_token_type_is(TokenType.LNUM):
            v = int(self.consume_token(TokenType.LNUM))
            if v < 0:
                raise IndexError("Array index cannot be negative at {0}"
                                 "".format(self.pos))
            self.consume_token(TokenType.RSQBRACKET)
            return DocumentPathItem(type=DocumentPathItem.ARRAY_INDEX, index=v)
        else:
            raise ValueError("Exception token type MUL or LNUM in JSON "
                             "path array index at token pos {0}"
                             "".format(self.pos))

    def document_field(self):
        col = ColumnIdentifier()
        if self.cur_token_type_is(TokenType.IDENT):
            col.document_path.extend([
                DocumentPathItem(type=DocumentPathItem.MEMBER,
                                 value=self.consume_token(TokenType.IDENT))])
        col.document_path.extend(self.document_path())
        return Expr(type=Expr.IDENT, identifier=col)

    def document_path(self):
        """Parse a JSON-style document path, like WL#7909, but prefix by @.
        instead of $. We parse this as a string because the protocol doesn't
        support it. (yet)
        """
        docpath = []
        while True:
            if self.cur_token_type_is(TokenType.DOT):
                docpath.append(self.docpath_member())
            elif self.cur_token_type_is(TokenType.DOTSTAR):
                self.consume_token(TokenType.DOTSTAR)
                docpath.append(DocumentPathItem(
                    type=DocumentPathItem.MEMBER_ASTERISK))
            elif self.cur_token_type_is(TokenType.LSQBRACKET):
                docpath.append(self.docpath_array_loc())
            elif self.cur_token_type_is(TokenType.DOUBLESTAR):
                self.consume_token(TokenType.DOUBLESTAR)
                docpath.append(DocumentPathItem(
                    type=DocumentPathItem.DOUBLE_ASTERISK))
            else:
                break
        items = len(docpath)
        if items > 0 and docpath[items-1].type == \
           DocumentPathItem.DOUBLE_ASTERISK:
            raise ValueError("JSON path may not end in '**' at {0}"
                             "".format(self.pos))
        return docpath

    def column_identifier(self):
        parts = []
        parts.append(self.consume_token(TokenType.IDENT))
        while self.cur_token_type_is(TokenType.DOT):
            self.consume_token(TokenType.DOT)
            parts.append(self.consume_token(TokenType.IDENT))
        if len(parts) > 3:
            raise ValueError("Too many parts to identifier at {0}"
                             "".format(self.pos))
        parts.reverse()
        colid = ColumnIdentifier()
        # clever way to apply them to the struct
        for i in xrange(0, len(parts)):
            if i == 0:
                colid.name = parts[0]
            elif i == 1:
                colid.table_name = parts[1]
            elif i == 2:
                colid.schema_name = parts[2]
        if self.cur_token_type_is(TokenType.DOLLAR):
            self.consume_token(TokenType.DOLLAR)
            colid.document_path = self.document_path()
        e = Expr()
        e.type = Expr.IDENT
        e.identifier.CopyFrom(colid)
        return e

    def next_token(self):
        if (self.pos >= len(self.tokens)):
            raise ValueError("Unexpected end of token stream")
        t = self.tokens[self.pos]
        self.pos += 1
        return t

    def expect_token(self, token_type):
        t = self.next_token()
        if t.type != token_type:
            raise ValueError("Expected token type {0}".format(token_type))

    def parse_json_doc(self):
        o = Object()

    def parse_place_holder(self, token):
        place_holder_name = ""
        if self.cur_token_type_is(TokenType.LNUM):
            place_holder_name = self.consume_token(TokenType.LNUM_INT)
        elif self.cur_token_type_is(TokenType.IDENT):
            place_holder_name = self.consume_token(TokenType.IDENT)
        elif token.type == TokenType.EROTEME:
            place_holder_name = str(self.positional_placeholder_count)
        else:
            raise ValueError("Invalid placeholder name at token pos {0}"
                             "".format(self.pos))

        place_holder_name = place_holder_name.lower()
        expr = Expr(type=Expr.PLACEHOLDER)
        if place_holder_name in self.placeholder_name_to_position:
            expr.position = \
                self.placeholder_name_to_position[place_holder_name]
        else:
            expr.position = self.positional_placeholder_count
            self.placeholder_name_to_position[place_holder_name] = \
                self.positional_placeholder_count
            self.positional_placeholder_count += 1
        return expr

    def atomic_expr(self):
        """Parse an atomic expression and return a protobuf Expr object"""
        token = self.next_token()

        if token.type in [TokenType.EROTEME, TokenType.COLON]:
            return self.parse_place_holder(token)
        elif token.type == TokenType.LCURLY:
            return self.parse_json_doc()
        elif token.type == TokenType.CAST:
            # TODO implement pass
            pass
        elif token.type == TokenType.LPAREN:
            e = self.expr()
            self.expect_token(TokenType.RPAREN)
            return e
        elif token.type in [TokenType.PLUS, TokenType.MINUS]:
            pass
        elif token.type in [TokenType.PLUS, TokenType.MINUS]:
            peek = self.peek_token()
            if peek.type == TokenType.LNUM:
                self.tokens[self.pos].val = token.val + peek.val
                return self.atomic_expr()
            return build_unary_op(token.val, self.atomic_expr())
        elif token.type in [TokenType.NOT, TokenType.NEG, TokenType.BANG]:
            return build_unary_op(token.val, self.atomic_expr())
        elif token.type == TokenType.LSTRING:
            return build_literal_expr(build_string_scalar(token.val))
        elif token.type == TokenType.NULL:
            return build_literal_expr(build_null_scalar())
        elif token.type == TokenType.LNUM:
            if "." in token.val:
                return build_literal_expr(
                    build_double_scalar(float(token.val)))
            else:
                return build_literal_expr(build_int_scalar(int(token.val)))
        elif token.type in [TokenType.TRUE, TokenType.FALSE]:
            return build_literal_expr(
                build_bool_scalar(token.type == TokenType.TRUE))
        elif token.type == TokenType.DOLLAR:
            return self.document_field()
        elif token.type == TokenType.MUL:
            return self.starOperator()
        elif token.type == TokenType.IDENT:
            self.pos = self.pos - 1  # stay on the identifier
            if self.next_token_type_is(TokenType.LPAREN) or \
               (self.next_token_type_is(TokenType.DOT) and
               self.pos_token_type_is(self.pos + 2, TokenType.IDENT) and
               self.pos_token_type_is(self.pos + 3, TokenType.LPAREN)):
                # Function call
                return self.function_call()
            else:
                return (self.document_field()
                        if not self._allowRelationalColumns
                        else self.column_identifier())

#        if t.type == TokenType.EROTEME:
#            return build_literal_expr(build_string_scalar("?"))
#        elif t.type == TokenType.INTERVAL:
#            e = Expr()
#            e.type = Expr.OPERATOR
#            e.operator.name = "INTERVAL"
#            e.operator.param.add().CopyFrom(self.expr())
#            # validate the interval units
#            if self.pos < len(self.tokens) and self.tokens[self.pos].type in interval_units:
#                pass
#            else:
#                raise StandardError("Expected interval units at " + str(self.pos))
#            e.operator.param.add().CopyFrom(build_literal_expr(build_string_scalar(self.tokens[self.pos].val)))
#            self.pos = self.pos + 1
#            return e
        raise ValueError("Unknown token type = {0}  when expecting atomic "
                         "expression at {1}".format(token.type, self.pos))

    def parse_left_assoc_binary_op_expr(self, types, inner_parser):
        """Given a `set' of types and an Expr-returning inner parser function,
        parse a left associate binary operator expression"""
        lhs = inner_parser()
        while (self.pos < len(self.tokens) and
               self.tokens[self.pos].type in types):
            e = Expr()
            e.type = Expr.OPERATOR
            e.operator.name = self.tokens[self.pos].val
            e.operator.param.add().CopyFrom(lhs)
            self.pos = self.pos + 1
            e.operator.param.add().CopyFrom(inner_parser())
            lhs = e
        return lhs

    # operator precedence is implemented here
    def mul_div_expr(self):
        return self.parse_left_assoc_binary_op_expr(
            set([TokenType.MUL, TokenType.DIV, TokenType.MOD]),
            self.atomic_expr)

    def add_sub_expr(self):
        return self.parse_left_assoc_binary_op_expr(
            set([TokenType.PLUS, TokenType.MINUS]), self.mul_div_expr)

    def shift_expr(self):
        return self.parse_left_assoc_binary_op_expr(
            set([TokenType.LSHIFT, TokenType.RSHIFT]), self.add_sub_expr)

    def bit_expr(self):
        return self.parse_left_assoc_binary_op_expr(
            set([TokenType.BITAND, TokenType.BITOR, TokenType.BITXOR]),
            self.shift_expr)

    def comp_expr(self):
        return self.parse_left_assoc_binary_op_expr(
            set([TokenType.GE, TokenType.GT, TokenType.LE, TokenType.LT,
                 TokenType.EQ, TokenType.NE]), self.bit_expr)

    def ilri_expr(self):
        lhs = self.comp_expr()
        is_not = False
        if self.cur_token_type_is(TokenType.NOT):
            is_not = True
            self.consume_token(TokenType.NOT)
        if self.pos < len(self.tokens):
            params = [lhs]
            op_name = self.tokens[self.pos].val
            if self.cur_token_type_is(TokenType.IS):
                self.consume_token(TokenType.IS)
                # for IS, NOT comes AFTER
                if self.cur_token_type_is(TokenType.NOT):
                    is_not = True
                    self.consume_token(TokenType.NOT)
                params.append(self.comp_expr())
            elif self.cur_token_type_is(TokenType.IN):
                self.consume_token(TokenType.IN)
                params.extend(self.paren_expr_list())
            elif self.cur_token_type_is(TokenType.LIKE):
                self.consume_token(TokenType.LIKE)
                params.append(self.comp_expr())
                if self.cur_token_type_is(TokenType.ESCAPE):
                    self.consume_token(TokenType.ESCAPE)
                    params.append(self.comp_expr())
            elif self.cur_token_type_is(TokenType.BETWEEN):
                self.consume_token(TokenType.BETWEEN)
                params.append(self.comp_expr())
                self.consume_token(TokenType.AND)
                params.append(self.comp_expr())
            elif self.cur_token_type_is(TokenType.REGEXP):
                self.consume_token(TokenType.REGEXP)
                params.append(self.comp_expr())
            else:
                if is_not:
                    raise ValueError("Unknown token after NOT as pos {0}"
                                     "".format(self.pos))
                op_name = None  # not an operator we're interested in
            if op_name:
                e = Expr()
                e.type = Expr.OPERATOR
                e.operator.name = op_name
                e.operator.param.extend(params)
                if is_not:
                    # wrap if `NOT'-prefixed
                    e = build_unary_op("NOT", e)
                lhs = e
        return lhs

    def and_expr(self):
        return self.parse_left_assoc_binary_op_expr(
            set([TokenType.AND, TokenType.ANDAND]), self.ilri_expr)

    def or_expr(self):
        return self.parse_left_assoc_binary_op_expr(
            set([TokenType.OR, TokenType.OROR]), self.and_expr)

    def expr(self):
        return self.or_expr()

    def parse_table_insert_field(self):
        return Column(name=self.consume_token(TokenType.IDENT))

    def parse_table_update_field(self):
        return self.column_identifier().identifier

    def parse_table_select_projection(self):
        project_expr = []
        first = True
        while self.pos < len(self.tokens):
            if not first:
                self.consume_token(TokenType.COMMA)
            first = False
            projection = Projection(source=self.expr())
            if self.cur_token_type_is(TokenType.AS):
                self.consume_token(TokenType.AS)
                projection.alias = self.consume_token(TokenType.IDENT)
            else:
                self.pos -= 1
                projection.alias = self.consume_token(TokenType.IDENT)
            project_expr.append(projection)
        return project_expr

    def parse_order_spec(self):
        order_specs = []
        first = True
        while self.pos < len(self.tokens):
            if not first:
                self.consume_token(TokenType.COMMA)
            first = False
            order = Order(expr=self.expr())
            if self.cur_token_type_is(TokenType.ORDERBY_ASC):
                order.direction = Order.ASC
                self.consume_token(TokenType.ORDERBY_ASC)
            elif self.cur_token_type_is(TokenType.ORDERBY_DESC):
                order.direction = Order.DESC
                self.consume_token(TokenType.ORDERBY_DESC)
            order_specs.append(order)
        return order_specs

    def parse_expr_list(self):
        expr_list = []
        first = True
        while self.pos < len(self.tokens):
            if not first:
                self.consume_token(TokenType.COMMA)
            first = False
            expr_list.append(self.expr())
        return expr_list


def parseAndPrintExpr(expr_string, allowRelational=True):
    print(">>>>>>> parsing:  {0}".format(expr_string))
    p = ExprParser(expr_string, allowRelational)
    print(p.tokens)
    e = p.expr()
    print(e)


def x_test():
    parseAndPrintExpr("name like :name")
    return
    parseAndPrintExpr("10+1")
    parseAndPrintExpr("(abc == 1)")
    parseAndPrintExpr("(func(abc)=1)")
    parseAndPrintExpr("(abc = \"jess\")")
    parseAndPrintExpr("(abc = \"with \\\"\")")
    parseAndPrintExpr("(abc != .10)")
    parseAndPrintExpr("(abc != \"xyz\")")
    parseAndPrintExpr("a + b * c + d")
    parseAndPrintExpr("(a + b) * c + d")
    parseAndPrintExpr("(field not in ('a',func('b', 2.0),'c'))")
    parseAndPrintExpr("jess.age between 30 and death")
    parseAndPrintExpr("a + b * c + d")
    parseAndPrintExpr("x > 10 and Y >= -20")
    parseAndPrintExpr("a is true and b is null and C + 1 > 40 and "
                      "(time = now() or hungry())")
    parseAndPrintExpr("a + b + -c > 2")
    parseAndPrintExpr("now () + b + c > 2")
    parseAndPrintExpr("now () + @b + c > 2")
    parseAndPrintExpr("now () - interval +2 day > some_other_time() or "
                      "something_else IS NOT NULL")
    parseAndPrintExpr("\"two quotes to one\"\"\"")
    parseAndPrintExpr("'two quotes to one'''")
    parseAndPrintExpr("'different quote \"'")
    parseAndPrintExpr("\"different quote '\"")
    parseAndPrintExpr("`ident`")
    parseAndPrintExpr("`ident```")
    parseAndPrintExpr("`ident\"'`")
    parseAndPrintExpr("now () - interval -2 day")
    parseAndPrintExpr("? > x and func(?, ?, ?)")
    parseAndPrintExpr("a > now() + interval (2 + x) MiNuTe")
    parseAndPrintExpr("a between 1 and 2")
    parseAndPrintExpr("a not between 1 and 2")
    parseAndPrintExpr("a in (1,2,a.b(3),4,5,x)")
    parseAndPrintExpr("a not in (1,2,3,4,5,@x)")
    parseAndPrintExpr("a like b escape c")
    parseAndPrintExpr("a not like b escape c")
    parseAndPrintExpr("(1 + 3) in (3, 4, 5)")
    parseAndPrintExpr("`a crazy \"function\"``'name'`(1 + 3) in (3, 4, 5)")
    parseAndPrintExpr("`a crazy \"function\"``'name'`(1 + 3) in (3, 4, 5)")
    parseAndPrintExpr("a@.b", False)
    parseAndPrintExpr("a@.b[0][0].c**.d.\"a weird\\\"key name\"", False)
    parseAndPrintExpr("a@.*", False)
    parseAndPrintExpr("a@[0].*", False)
    parseAndPrintExpr("a@**[0].*", False)

# x_test()

Youez - 2016 - github.com/yon3zu
LinuXploit