o k`AS@sdddlZddlZddlZddlmZddlmZmZddlm Z ddl Tddl m Z ddl mZmZmZmZmZddlmZmZdd lmZmZdd lmZdd lmZdd lmZmZdd l m!Z!e"dZ#zddl$Z$Wn e%yzdZ$dZ&Ynwee$'de$j(Z&Gddde$j)j*Z+Gddde+Z,dddZ-ddZ.Gddde/Z0GdddeeZ1dS)N)closing)PopenPIPE)IEnvironmentSetupParticipant)*)Option)ConnectionBaseDatabaseManagerIDatabaseConnectorget_column_namesparse_connection_uri)ConnectionWrapperIterableCursor)as_int get_pkginfo)Markup) close_fds)exception_to_unicode to_unicode)_z([/_%])versioncs6eZdZdfdd ZfddZfddZZS) MySQLUnicodeCursorNcs$|r tdd|D}t||S)Ncs&|]}t|tr t|n|VqdSN isinstancerstr.0argr 7/usr/lib/python3/dist-packages/trac/db/mysql_backend.py 0z-MySQLUnicodeCursor.execute..)tuplesuperexecuteselfqueryargs __class__r r!r&.s zMySQLUnicodeCursor.executecs |r dd|D}t||S)NcSsg|] }tdd|DqS)csrrr)ritemr r r!r"6r#z..)r$rr r r! 6s  z2MySQLUnicodeCursor.executemany..)r% executemanyr'r+r r!r/4s zMySQLUnicodeCursor.executemanycsttSr)listr%fetchallr(r+r r!r1;zMySQLUnicodeCursor.fetchallr)__name__ __module__ __qualname__r&r/r1 __classcell__r r r+r!r-s rc@seZdZdddZdS)MySQLSilentCursorNcCdSrr )r(connr r r!_show_warnings?z MySQLSilentCursor._show_warningsr)r4r5r6r;r r r r!r8>sr8bigint mediumtext)int64textcCsd|ddS)Nz`%s``z``)replace) identifierr r r!_quoteJsrDc@seZdZdZeeedZeddddZ ddZ d d Z d d d d d ifd d Z ddZ d d d d d d ifddZd d d d d ifddZd d d d d ifddZddZdZddZd/ddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)Zd*d+Zd,Zd-d.Zd S)0MySQLConnectoraDatabase connector for MySQL version 4.1 and greater. Database URLs should be of the form:: {{{ mysql://user[:password]@host[:port]/database[?param1=value¶m2=value] }}} The following parameters are supported: * `compress`: Enable compression (0 or 1) * `init_command`: Command to run once the connection is created * `named_pipe`: Use a named pipe to connect on Windows (0 or 1) * `read_default_file`: Read default client values from the given file * `read_default_group`: Configuration group to use from the default file * `unix_socket`: Use a Unix socket at the given path to connect Ftracmysqldump_path mysqldumpz0Location of mysqldump for MySQL database backupscCs(trdttf|_dSd|_dS)Nz6server: (not-connected), client: "%s", thread-safe: %s)pymysqlget_client_info thread_safe_mysql_versionr2r r r!__init__fs  zMySQLConnector.__init__ccs dVdS)N)mysqlr r2r r r!get_supported_schemesps z$MySQLConnector.get_supported_schemesNc CsBt|||||||}|jsd|jttf|_d|_|S)Nz+server: "%s", client: "%s", thread-safe: %sT)MySQLConnectionrequiredcnxget_server_inforIrJrKrL r(pathloguserpasswordhostportparamsrSr r r!get_connectionsszMySQLConnector.get_connectioncCstSr)rIr2r r r!get_exceptions~r<zMySQLConnector.get_exceptionsc  Cs||||||||} || || } | } |dur#ddlm}|D]} |j| | dD] } |j| | | q.q%| | | dS)Nrschema max_bytes) r]_verify_variables _max_bytescursortrac.db_defaultr`to_sqlrWdebugr&_verify_table_statuscommit)r(rVr`rWrXrYrZr[r\rSrbretablestmtr r r!init_dbs       zMySQLConnector.init_dbc Cs:||||||||}|D]} || q|dSr)r]get_table_names drop_tablerj) r(rVrWrXrYrZr[r\rS table_namer r r! destroy_dbs    zMySQLConnector.destroy_dbc Cs"||||||||}t|Sr)r]boolrnrUr r r! db_existss zMySQLConnector.db_existscCsl|dur+t|j\}}t|jdi| }|j}Wdn1s%wYn|j}|dkr4dSdS)Nutf8mb4r )r env get_connectorrr]charset)r(rS connectorr*ryr r r!rdszMySQLConnector._max_bytesi c sg}d|}t|j|t||}|D]@t}ttfdd|j}t|dkrO|djdkrO|dj durI|dt|dj |7}n|d |7}| |qd |S) zTake a list of columns and impose limits on each so that indexing works properly. Some Versions of MySQL limit each index prefix to 3072 bytes total, with a max of 767 bytes per column. ics |jkSrname)xcr r!s z)MySQLConnector._collist..rOrr@Nz(%d)z(%s),) min_max_key_lengthlenrDr0filtercolumnstypelowerkey_sizeappendjoin) r(rkrrbcols limit_collimitr| table_colr r~r!_collists   zMySQLConnector._collistc cs|dur |d}dt|jg}g}|jD]}|j}t||}|jr*d}d|_|dt|j|fqt |j dkrL|d|j ||j |d|d |d d |V|j D])}|jrfd nd }d |jd |jf} d|t| t|j|j ||j|dfVq_dS)NzCREATE TABLE %s (z$INT UNSIGNED NOT NULL AUTO_INCREMENTintz %s %srz PRIMARY KEY (%s)raz, z ) UNIQUEz %s_%s_idxrzCREATE %s INDEX %s ON %s (%s))rdrDr|rr _type_mapgetauto_incrementrrkeyrrindicesunique) r(rkrbsqlcoldefscolumnctypeindexridxnamer r r!rgs:      zMySQLConnector.to_sqlccstg}t|D]\}\}}t||}|t||kr$|||fq |r8d|ddd|DfVdSdS)zYield SQL statements altering the type of one or more columns of a table. Type changes are specified as a `columns` dict mapping column names to `(from, to)` SQL type tuples. zALTER TABLE %s %s, css|]}d|VqdS)z MODIFY %s %sNr )reachr r r!r"sz4MySQLConnector.alter_column_types..N)sorteditemsrrrr)r(rkr alterationsr|from_tor r r!alter_column_typess   z!MySQLConnector.alter_column_typesc Cs|jjdd}t|\}}|di}tj|d}|jdg}d|vr.| d|dgd|vr=| d t |dgd |vrJ| d |d g| D]H\}} |d krat | d ra| dqN|dkrpt | d rp| dqN|dkr}|dd| qN|dkr| dd| gqN|dvr|jd|qN| d||gtj} d|vrt |d| d<z t|| ttd} Wnty} z ttd|jt| dd} ~ ww| d} | jd krttdt| d tj|sttd!|S)"NrFdatabaser\rVz --no-defaultsrZz-hr[z-PrXz-ucompressrz --compress named_pipez--protocol=piperead_default_filerOz--defaults-file= unix_socketz--protocol=socketz --socket=) init_commandread_default_group(Invalid connection string parameter '%s'z-rrY MYSQL_PWD)rwstderrrzUnable to run %(path)s: %(msg)s)rVmsgzmysqldump failed: %(msg)s)rzNo destination file created)rwconfigrr setdefaultosrVbasenamerGextendrrrrinsertrWwarningenvironcopyrrrOSError TracErrorrr communicate returncoderstripexists)r( dest_filedb_urlschemedb_prop db_paramsdb_namer*r|valuerpeerrmsgr r r!backups\           zMySQLConnector.backupccsd|jfVtjtfVdS)NMySQL)rLrIr4pymsql_versionr2r r r!get_system_infos zMySQLConnector.get_system_infocCr9rr r2r r r!environment_created!r<z"MySQLConnector.environment_createdcCsH|jr"|jj}||||WddS1swYdS)NF)rRrwdb_queryrirc)r(dbr r r!environment_needs_upgrade$s    z(MySQLConnector.environment_needs_upgradecCr9rr r2r r r!upgrade_environment+r<z"MySQLConnector.upgrade_environment)MyISAMEXAMPLEARCHIVECSVISAMcsddlm}dd|D}|}|dddt||t|fdd|D}fd d|D}|rCttd d |d d d|D}|rWttdd |d dS)Nrr_cSsg|]}|jqSr r{)rtr r r!r.2sz7MySQLConnector._verify_table_status..z$SHOW TABLE STATUS WHERE name IN (%s)r)z%scsg|] }tt|qSr )dictziprrow)rr r!r.8scs"g|] }|djvr|dqS)EngineName)UNSUPPORTED_ENGINESrr2r r!r.:szAll tables must be created as InnoDB or NDB storage engine to support transactions. The following tables have been created as storage engine which doesn't support transactions: %(tables)sr)tablescSs g|] }|ddvr|dqS) Collation)utf8_bin utf8mb4_binNrr rr r r!r.Cs zAll tables must be created with utf8_bin or utf8mb4_bin as collation. The following tables don't have the collations: %(tables)s) rfr`rer&rrr rr)r(rr`rrerowsengines non_utf8binr )rr(r!ri0s, z#MySQLConnector._verify_table_status))utf8r)rtrcCs|}|ddd|D}|dp|d}||jvr'ttd|d|d}||jvr9ttd |d|d }|d }||f|jvrUttd ||t|jd dS)NzSHOW VARIABLES WHERE variable_name IN ('default_storage_engine','storage_engine','default_tmp_storage_engine','character_set_database','collation_database')cSsi|] }|d|dqS)rrO)rrr r r! Tsz4MySQLConnector._verify_variables..default_storage_enginestorage_enginezjThe current storage engine is %(engine)s. It must be InnoDB or NDB storage engine to support transactions.)enginedefault_tmp_storage_enginezThe current storage engine for TEMPORARY tables is %(engine)s. It must be InnoDB or NDB storage engine to support transactions.character_set_databasecollation_databasezThe charset and collation of database are '%(charset)s' and '%(collation)s'. The database must be created with one of %(supported)s.)ry collation supported)rer&rrrrSUPPORTED_COLLATIONSrepr)r(rrevarsr tmp_engineryrr r r!rcNs0     z MySQLConnector._verify_variablesr)r4r5r6__doc__ implementsr rrRrrGrMrPr]r^rmrqrsrdrrrgrrrrrrrrirrcr r r r!rENsH         , rEc@seZdZdZdZddddifddZddZdd Zd d Zd d Z ddZ ddZ ddZ ddZ d-ddZddZddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)d*Zd-d+d,ZdS).rQzConnection wrapper for MySQL.TNc Csv|dr |dd}|durd}|durd}ddi}|D]L\} } | dkr,| || <q| dkr5| || <q| d vr>| || <q| d vrJt| d || <q| dkrd| } | d vr[| || <q|jd | | q|jd| qtjd|||||d|} | } | d| d|_ | |j |dkr| |j |d<tjd|||||d|} ||_ t|| |d|_dS)N/rOri ryrrr)rr)rrr)rrtz+Invalid connection string parameter '%s=%s'r)rrXpasswdrZr[z.r&r`r(rkrr r r!r sz MySQLConnection.get_column_namesidcCs|jSr) lastrowidr(rerkrr r r! get_last_idszMySQLConnection.get_last_idcCsgSrr r2r r r!get_sequence_namesr<z"MySQLConnection.get_sequence_namescCs|d|jf}dd|DS)Nzl SELECT table_name FROM information_schema.tables WHERE table_schema=%s cSrrr rr r r!r.rz3MySQLConnection.get_table_names..r)r(rr r r!rnszMySQLConnection.get_table_namescCs"|d|j|f}t|ddS)Nz SELECT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema=%s AND table_name=%s) r)r&r`rrrr r r! has_tableszMySQLConnection.has_tablecCs d|jS)Nz)LIKE %%s COLLATE %s_general_ci ESCAPE '/')ryr2r r r!likes zMySQLConnection.likecCs td|S)Nz/\1)_like_escape_resub)r(r@r r r! like_escapes zMySQLConnection.like_escapecCsrg}|js|S|}|d|jf|D]\}}||||}|s/|d|q|d|q|S)Naz SELECT t.table_name, EXISTS (SELECT * FROM information_schema.columns AS c WHERE c.table_schema=t.table_schema AND c.table_name=t.table_name AND extra='auto_increment') FROM information_schema.tables AS t WHERE t.table_schema=%s zDELETE FROM %szTRUNCATE TABLE %s)r`rer&r1rr)r( table_namesrerk has_autoincquotedr r r! reset_tabless  zMySQLConnection.reset_tablescCsdS)NzLIKE %s ESCAPE '/'r r2r r r! prefix_matchr<zMySQLConnection.prefix_matchcCs||dS)N%)r!)r(prefixr r r!prefix_match_valuer3z"MySQLConnection.prefix_match_valuecCst|S)zReturn the quoted identifier.)rD)r(rCr r r!rszMySQLConnection.quotecCr9rr rr r r!update_sequenceszMySQLConnection.update_sequence)r)r4r5r6rpoolablerMrerrrr rror rrrnrrr!r%r&r)rr*r r r r!rQns2 , rQ)2rresys contextlibr subprocessrrtrac.apir trac.core trac.configr trac.db.apirr r r r trac.db.utilr r trac.utilrrtrac.util.htmlrtrac.util.compatrtrac.util.textrrtrac.util.translationrcompilerrI ImportErrorrr __version__r rrr8rrD ComponentrErQr r r r!sB         "