o
    }oi                     @  s  d dl mZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
mZ d d	lZd d
lmZ d dlmZ d d	lZd d	lZd d	lZd d	lZd d	lZd d	lZd dlmZ d dlmZ d d	lZd d	lZd dlmZ d dlmZ d dlmZ d dlmZ d dl m!Z! d dl"m#Z# d dl"m$Z$ d dl%m&Z& d dl'm(Z( d dl)m*Z* d dl+m,Z, d dl+m-Z- er
d d	l.m/Z0 d d	l1m2Z3 d d	l4m5Z6 d d	l7m8Z9 d d	l:Z:d d	l;m<  m=Z> d d	l?m<  m@ZA d d	lBm<  mCZD d d	lEmFZG d d	lHmIZJ d d	lKmL  mMZN d dlOmPZP n0edZ0edZ3edZ6edZ9edZ:ed Z>ed!ZAed"ZDed#ZGed$ZJed%ZNed&ZPejQeRZSe	'd8d9d.d/ZTG d0d1 d1e#e&ZUG d2d3 d3ZVd:d6d7ZWd	S );    )annotations)defaultdict)Callable)	Container)	Generator)Iterable)Sequence)contextmanagerN)datetime)	timedelta)Any)TYPE_CHECKING)distributions)version)warn_experimental_argument)_LazyImport)JSONSerializable)BaseStorage)DEFAULT_STUDY_NAME_PREFIX)BaseHeartbeat)FrozenStudy)StudyDirection)FrozenTrial)
TrialState)modelszalembic.commandzalembic.configzalembic.migrationzalembic.script
sqlalchemyzsqlalchemy.dialects.mysqlzsqlalchemy.dialects.postgresqlzsqlalchemy.dialects.sqlitezsqlalchemy.exczsqlalchemy.ormzsqlalchemy.sql.functionszoptuna.storages._rdb.modelsFscoped_session'sqlalchemy_orm.scoped_session'ignore_integrity_errorboolreturn/Generator['sqlalchemy_orm.Session', None, None]c              
   c  s    |  }z`z	|V  |   W nH tjy2 } z|  |r'td|d n W Y d }~n0d }~w tjyK } z|  d}tj	||d }~w t
yV   |   w W |  d S W |  d S |  w )Nz	Ignoring z. This happens due to a timing issue among threads/processes/nodes. Another one might have committed a record with the same key(s).zAn exception is raised during the commit. This typically happens due to invalid data in the commit, e.g. exceeding max length. )commitsqlalchemy_excIntegrityErrorrollback_loggerdebugSQLAlchemyErroroptuna
exceptionsStorageInternalError	Exceptionclose)r   r   sessionemessage r1   P/home/ubuntu/.local/lib/python3.10/site-packages/optuna/storages/_rdb/storage.py_create_scoped_sessionH   s8   
r3   c                   @  s&  e Zd ZdZ		dddddddddZdddZdddZ	ddd d!Zdd#d$Ze	dd'd(Z
dd,d-Zdd/d0Zdd1d2Zdd3d4Zdd6d7Zdd9d:Zdd;d<Zdd>d?Zdd@dAZddCdDZdddGdHZ	dddJdKZddMdNZddTdUZddXdYZ	dddZd[Zdd\d]Z	dddadbZddfdgZddjdkZddldmZddndoZ ddpdqZ!ddtduZ"ddwdxZ#ddydzZ$	{	ddddZ%dddZ&dddZ'dddZ(dddZ)e	dddZ*e	dddZ+dddZ,dddZ-dddZ.dddZ/dddZ0dddZ1dddZ2dddZ3dddZ4dS )
RDBStoragea\  Storage class for RDB backend.

    Note that library users can instantiate this class, but the attributes
    provided by this class are not supposed to be directly accessed by them.

    Example:

        Create an :class:`~optuna.storages.RDBStorage` instance with customized
        ``pool_size`` and ``timeout`` settings.

        .. testcode::

            import optuna


            def objective(trial):
                x = trial.suggest_float("x", -100, 100)
                return x**2


            storage = optuna.storages.RDBStorage(
                url="sqlite:///:memory:",
                engine_kwargs={"pool_size": 20, "connect_args": {"timeout": 10}},
            )

            study = optuna.create_study(storage=storage)
            study.optimize(objective, n_trials=10)

    Args:
        url:
            URL of the storage.
        engine_kwargs:
            A dictionary of keyword arguments that is passed to
            `sqlalchemy.engine.create_engine`_ function.
        skip_compatibility_check:
            Flag to skip schema compatibility check if set to :obj:`True`.
        heartbeat_interval:
            Interval to record the heartbeat. It is recorded every ``interval`` seconds.
            ``heartbeat_interval`` must be :obj:`None` or a positive integer.

            .. note::
                Heartbeat mechanism is experimental. API would change in the future.

            .. note::
                The heartbeat is supposed to be used with :meth:`~optuna.study.Study.optimize`.
                If you use :meth:`~optuna.study.Study.ask` and
                :meth:`~optuna.study.Study.tell` instead, it will not work.

        grace_period:
            Grace period before a running trial is failed from the last heartbeat.
            ``grace_period`` must be :obj:`None` or a positive integer.
            If it is :obj:`None`, the grace period will be `2 * heartbeat_interval`.
        failed_trial_callback:
            A callback function that is invoked after failing each stale trial.
            The function must accept two parameters with the following types in this order:
            :class:`~optuna.study.Study` and :class:`~optuna.trial.FrozenTrial`.

            .. note::
                The procedure to fail existing stale trials is called just before asking the
                study for a new trial.

        skip_table_creation:
            Flag to skip table creation if set to :obj:`True`.

    .. _sqlalchemy.engine.create_engine:
        https://docs.sqlalchemy.org/en/latest/core/engines.html#sqlalchemy.create_engine

    .. note::
        If you use MySQL, `pool_pre_ping`_ will be set to :obj:`True` by default to prevent
        connection timeout. You can turn it off with ``engine_kwargs['pool_pre_ping']=False``, but
        it is recommended to keep the setting if execution time of your objective function is
        longer than the `wait_timeout` of your MySQL configuration.

    .. _pool_pre_ping:
        https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine.params.
        pool_pre_ping

    .. note::
        We would never recommend SQLite3 for parallel optimization.
        Please see the FAQ :ref:`sqlite_concurrency` for details.

    .. note::
        Mainly in a cluster environment, running trials are often killed unexpectedly.
        If you want to detect a failure of trials, please use the heartbeat
        mechanism. Set ``heartbeat_interval``, ``grace_period``, and ``failed_trial_callback``
        appropriately according to your use case. For more details, please refer to the
        :ref:`tutorial <heartbeat_monitoring>` and `Example page
        <https://github.com/optuna/optuna-examples/blob/main/pytorch/pytorch_checkpoint.py>`__.

    .. seealso::
        You can use :class:`~optuna.storages.RetryFailedTrialCallback` to automatically retry
        failed trials detected by heartbeat.

    NF)heartbeat_intervalgrace_periodfailed_trial_callbackskip_table_creationurlstrengine_kwargsdict[str, Any] | Noneskip_compatibility_checkr   r5   
int | Noner6   r7   :Callable[['optuna.study.Study', FrozenTrial], None] | Noner8   r    Nonec          	   
   C  s
  |pi | _ | || _|| _|d ur|dkrtdtd |d ur*|dkr*td|| _|| _|| _| 	|| j  zt
jj| jfi | j | _W n tyZ } ztd|d }~ww ttj| jd| _|sptjj| j t| j| j| j| _|s| j  d S d S )Nr   z?The value of `heartbeat_interval` should be a positive integer.r5   z9The value of `grace_period` should be a positive integer.`Failed to import DB access module for the specified storage URL. Please install appropriate one.bind)r;   _fill_storage_url_templater9   r=   
ValueErrorr   r5   r6   r7   $_set_default_engine_kwargs_for_mysqlr   enginecreate_engineImportErrorsqlalchemy_ormr   sessionmakerr   	BaseModelmetadata
create_all_VersionManager_version_manager check_table_schema_compatibility)	selfr9   r;   r=   r5   r6   r7   r8   r/   r1   r1   r2   __init__   s@   
zRDBStorage.__init__dict[Any, Any]c                 C  s    | j  }|d= |d= |d= |S )Nr   rG   rP   )__dict__copy)rR   stater1   r1   r2   __getstate__   s
   
zRDBStorage.__getstate__rW   c              
   C  s   | j | ztjj| jfi | j| _W n ty& } ztd|d }~ww t	tj
| jd| _	tjj| j t| j| j| j	| _| jsN| j  d S d S )NrA   rB   )rU   updater   rG   rH   r9   r;   rI   rJ   r   rK   r   rL   rM   rN   rO   rP   r=   rQ   )rR   rW   r/   r1   r1   r2   __setstate__   s&   zRDBStorage.__setstate__
directionsSequence[StudyDirection]
study_name
str | Noneintc                 C  s   z5t | j&}|d u r| |}dd tt|D }|tj||d W d    n1 s/w   Y  W n tj	yG   t
jd| dw td|  | |S )Nc                 S  s   g | ]\}}t j||d qS ))	objective	direction)r   StudyDirectionModel).0r`   dr1   r1   r2   
<listcomp>  s    z/RDBStorage.create_new_study.<locals>.<listcomp>)r]   r[   zAnother study with name 'z' already exists. Please specify a different name, or reuse the existing one by setting `load_if_exists` (for Python API) or `--skip-if-exists` flag (for CLI).z&A new study created in RDB with name: )r3   r   _create_unique_study_name	enumeratelistaddr   
StudyModelr#   r$   r)   r*   DuplicatedStudyErrorr&   infoget_study_id_from_name)rR   r[   r]   r.   direction_modelsr1   r1   r2   create_new_study  s"   



zRDBStorage.create_new_studystudy_idc                 C  sJ   t | jd}tj||}|| W d    d S 1 sw   Y  d S NT)r3   r   r   rj   find_or_raise_by_iddelete)rR   rp   r.   studyr1   r1   r2   delete_study+  s   "zRDBStorage.delete_studyr.   'sqlalchemy_orm.Session'c                 C  s4   	 t t }t| }tj|| }|d u r	 |S qN)r:   uuiduuid4r   r   rj   find_by_name)r.   
study_uuidr]   rt   r1   r1   r2   rf   0  s   z$RDBStorage._create_unique_study_namekeyvaluer   c                 C     t | jd;}tj||}tj|||}|d u r+tj||t|d}|	| nt||_
W d    d S W d    d S 1 sDw   Y  d S NT)rp   r|   
value_json)r3   r   r   rj   rr   StudyUserAttributeModelfind_by_study_and_keyjsondumpsri   r   rR   rp   r|   r}   r.   rt   	attributer1   r1   r2   set_study_user_attr;     "zRDBStorage.set_study_user_attrr   c                 C  r~   r   )r3   r   r   rj   rr   StudySystemAttributeModelr   r   r   ri   r   r   r1   r1   r2   set_study_system_attrG  r   z RDBStorage.set_study_system_attrc                 C  D   t | j}tj||}|j}W d    |S 1 sw   Y  |S rw   )r3   r   r   rj   find_or_raise_by_namerp   )rR   r]   r.   rt   rp   r1   r1   r2   rm   S     
z!RDBStorage.get_study_id_from_namec                 C  r   rw   )r3   r   r   rj   rr   r]   )rR   rp   r.   rt   r]   r1   r1   r2   get_study_name_from_idZ  r   z!RDBStorage.get_study_name_from_idlist[StudyDirection]c                 C  sN   t | j}tj||}dd |jD }W d    |S 1 s w   Y  |S )Nc                 S     g | ]}|j qS r1   )ra   )rc   rd   r1   r1   r2   re   d      z3RDBStorage.get_study_directions.<locals>.<listcomp>)r3   r   r   rj   rr   r[   )rR   rp   r.   rt   r[   r1   r1   r2   get_study_directionsa  s   
zRDBStorage.get_study_directionsdict[str, Any]c                 C  Z   t | j}tj|| tj||}dd |D }W d    |S 1 s&w   Y  |S )Nc                 S     i | ]
}|j t|jqS r1   r|   r   loadsr   rc   attrr1   r1   r2   
<dictcomp>m      z3RDBStorage.get_study_user_attrs.<locals>.<dictcomp>)r3   r   r   rj   rr   r   where_study_id)rR   rp   r.   
attributes
user_attrsr1   r1   r2   get_study_user_attrsh     
zRDBStorage.get_study_user_attrsc                 C  r   )Nc                 S  r   r1   r   r   r1   r1   r2   r   v  r   z5RDBStorage.get_study_system_attrs.<locals>.<dictcomp>)r3   r   r   rj   rr   r   r   )rR   rp   r.   r   system_attrsr1   r1   r2   get_study_system_attrsq  r   z!RDBStorage.get_study_system_attrstrial_idc                 C  r   )Nc                 S  r   r1   r   r   r1   r1   r2   r     r   z3RDBStorage.get_trial_user_attrs.<locals>.<dictcomp>)r3   r   r   
TrialModelrr   TrialUserAttributeModelwhere_trial_id)rR   r   r.   r   r   r1   r1   r2   get_trial_user_attrsz     
zRDBStorage.get_trial_user_attrsc                 C  r   )Nc                 S  r   r1   r   r   r1   r1   r2   r     r   z5RDBStorage.get_trial_system_attrs.<locals>.<dictcomp>)r3   r   r   r   rr   TrialSystemAttributeModelr   )rR   r   r.   r   r   r1   r1   r2   get_trial_system_attrs  r   z!RDBStorage.get_trial_system_attrslist[FrozenStudy]c                 C  sF  t | j}|tjjtjjtjj }t	t
}|tj D ]}||j |j q#t	t
}|tj D ]
}||j | q;t	t
}|tj D ]
}||j | qRg }|D ].}	||	j }
||	jg }||	jg }|t|	jd |
dd |D dd |D |	jd qa|W  d    S 1 sw   Y  d S )Nc                 S  r   r1   r   rc   ir1   r1   r2   r     r   z.RDBStorage.get_all_studies.<locals>.<dictcomp>c                 S  r   r1   r   r   r1   r1   r2   r     r   )r]   ra   r[   r   r   rp   )r3   r   queryr   rj   rp   r]   order_byallr   rh   rb   appendra   r   r   getr   )rR   r.   studies_directionsdirection_model_user_attrsattribute_model_system_attrsfrozen_studiesrt   r[   r   r   r1   r1   r2   get_all_studies  sD   
	
$zRDBStorage.get_all_studiestemplate_trialFrozenTrial | Nonec                 C  s   |  ||jS rw   )_create_new_trial	_trial_id)rR   rp   r   r1   r1   r2   create_new_trial  s   zRDBStorage.create_new_trialr   c           	      C  s   ddd}d	}t d
|d
 D ]T}z/t| j }tjj||dd | |||}|||W  d   W   S 1 s9w   Y  W q tjj	yb } z||krO|t
t d  W Y d}~qd}~ww J d)aU  Create a new trial and returns a :class:`~optuna.trial.FrozenTrial`.

        Args:
            study_id:
                Study id.
            template_trial:
                A :class:`~optuna.trial.FrozenTrial` with default values for trial attributes.

        Returns:
            A :class:`~optuna.trial.FrozenTrial` instance.

        trial'models.TrialModel'r   r   r    r   c                 S  sR   |rt |}| j|_| j|_| j|_|S t| j| jd d | jd i i i i i | jdS )NnumberrW   r}   valuesdatetime_startdatetime_completeparamsr   r   r   intermediate_valuesr   )rV   deepcopyr   r   r   r   r   rW   )r   r   frozenr1   r1   r2   _create_frozen_trial  s(   
z:RDBStorage._create_new_trial.<locals>._create_frozen_trial      T
for_updateNg       @FzShould not be reached.)r   r   r   r   r    r   )ranger3   r   r   rj   rr   _get_prepared_new_trialr)   r*   r+   timesleeprandom)	rR   rp   r   r   MAX_RETRIES	n_retriesr.   r   r/   r1   r1   r2   r     s    
*zRDBStorage._create_new_trialr   c                 C  s  |d u rt j|d tjt d}ntj}t j|d ||j|jd}|| |	  |d ur|j
d urLt|j
dkrLt|j
D ]\}}| |||| q>n|jd urZ| ||d|j |j D ]\}}	|j| }
|
|	}| ||j|||
 q_|j D ]\}}| |t j|j|| q}|j D ]\}}| |t j|j|| q|j D ]\}}| ||j|| q|j|_|||_|| |S )N)rp   r   rW   r   )rp   r   rW   r   r   r   r   )r   r   r   RUNNINGr
   nowr   r   ri   flushr   lenrg   _set_trial_value_without_commitr}   r   itemsr   to_internal_repr_set_trial_param_without_commitr   r   _set_trial_attr_without_commitr   r   r   r   ,_set_trial_intermediate_value_without_commitrW   count_past_trialsr   )rR   rp   r   r.   r   
temp_stater`   r}   
param_nameparam_valuedistributionparam_value_in_internal_reprr|   stepintermediate_valuer1   r1   r2   r     s\   





z"RDBStorage._get_prepared_new_trialr   param_value_internalfloatr   distributions.BaseDistributionc                 C  s   |  ||||d  d S rw   )_set_trial_param)rR   r   r   r   r   r1   r1   r2   set_trial_paramC  s   zRDBStorage.set_trial_paramprevious_distribution%distributions.BaseDistribution | Nonec              	   C  sF   t | jd}| |||||| W d    d S 1 sw   Y  d S rq   )r3   r   r   )rR   r   r   r   r   r   r.   r1   r1   r2   r   L  s   "zRDBStorage._set_trial_paramc           
      C  s   t j||}| ||j |d u r7|t jt jt jj	|j	kt jj
|k }|d ur7t|j}|d urAt|| t j|||t|d}	||	 d S )N)r   r   r   distribution_json)r   r   rr   check_trial_is_updatablerW   r   TrialParamModeljoinfilterrp   r   firstr   json_to_distributionr    check_distribution_compatibilitydistribution_to_jsonri   )
rR   r.   r   r   r   r   r   r   previous_recordtrial_paramr1   r1   r2   r   ^  s,   	
z*RDBStorage._set_trial_param_without_commitc                 C  sT   t | j}tj||}tj|||}|j}W d    |S 1 s#w   Y  |S rw   )r3   r   r   r   rr   r   %find_or_raise_by_trial_and_param_namer   )rR   r   r   r.   r   r   r   r1   r1   r2   get_trial_param  s   
zRDBStorage.get_trial_paramr   r   Sequence[float] | Nonec                 C  s   zst | jc}tjj||dd}| ||j |d ur,t|D ]\}}| |||| q|t	j
krA|jt	jkrA	 W d    W dS ||_|t	j
krNt |_| r`t |_W d    W dS W d    W dS 1 slw   Y  W dS  tjy~   Y dS w )NTr   F)r3   r   r   r   rr   r   rW   rg   r   r   r   WAITINGr
   r   r   is_finishedr   r#   r$   )rR   r   rW   r   r.   r   r`   vr1   r1   r2   set_trial_state_values  s2   

z!RDBStorage.set_trial_state_valuesr   models.TrialModelr`   c                 C  sj   |  |j|j tj|\}}tj|||}|d u r-tj|j|||d}|| d S ||_||_	d S )N)r   r`   r}   
value_type)
r   r   rW   r   TrialValueModelvalue_to_stored_reprfind_by_trial_and_objectiveri   r}   r  )rR   r.   r   r`   r}   stored_valuer  trial_valuer1   r1   r2   r     s   
z*RDBStorage._set_trial_value_without_commitr   r   c                 C  sB   t | jd}| |||| W d    d S 1 sw   Y  d S rq   )r3   r   r   )rR   r   r   r   r.   r1   r1   r2   set_trial_intermediate_value  s
   "z'RDBStorage.set_trial_intermediate_valuec           	      C  st   t j||}| ||j t j|\}}t j|||}|d u r2t j||||d}|| d S ||_	||_
d S )N)r   r   r   intermediate_value_type)r   r   rr   r   rW   TrialIntermediateValueModel!intermediate_value_to_stored_reprfind_by_trial_and_stepri   r   r
  )	rR   r.   r   r   r   r   r  r  trial_intermediate_valuer1   r1   r2   r     s*   
z7RDBStorage._set_trial_intermediate_value_without_commitc                 C  F   t | jd}| |tj||| W d    d S 1 sw   Y  d S rq   )r3   r   r   r   r   rR   r   r|   r}   r.   r1   r1   r2   set_trial_user_attr     "zRDBStorage.set_trial_user_attrc                 C  r  rq   )r3   r   r   r   r   r  r1   r1   r2   set_trial_system_attr  r  z RDBStorage.set_trial_system_attr	model_clsGtype[models.TrialUserAttributeModel | models.TrialSystemAttributeModel]c                 C  s`  t j||}| ||j | jjdkr1t|j	||t
|d}|j|jjd}|| d S | jjdkratjdkrat|j	||t
|d}	|	j|j|jgt|	jjdd}
||
 d S | jjdkrt|j	||t
|d}|j|j|jgt|jjdd}|| d S ||||}|d u r|||t
|d}|| d S t
||_d S )Nmysql)r   r|   r   )r   sqlite)      r   )index_elementsset_
postgresql)r   r   rr   r   rW   rG   namesqlalchemy_dialects_mysqlinsertr   r   r   on_duplicate_key_updateinsertedr   executesqlite3sqlite_version_infosqlalchemy_dialects_sqliteon_conflict_do_updater   r|   dictexcludedsqlalchemy_dialects_postgresqlfind_by_trial_and_keyri   )rR   r.   r  r   r|   r}   r   mysql_insert_stmtmysql_upsert_stmtsqlite_insert_stmtsqlite_upsert_stmtpg_insert_stmtpg_upsert_stmtr   r1   r1   r2   r     sB   




z)RDBStorage._set_trial_attr_without_committrial_numberc                 C  s~   t | j0}|tjjtjj|ktjj|k	 }|d u r*t
d| d| d|d W  d    S 1 s8w   Y  d S )NzNo trial with trial number z exists in study with study_id .r   )r3   r   r   r   r   r   r   r   rp   one_or_noneKeyError)rR   rp   r1  r.   r   r1   r1   r2   'get_trial_id_from_study_id_trial_number'  s    

$z2RDBStorage.get_trial_id_from_study_id_trial_numberc                 C  sH   t | j}tj||}| |}W d    |S 1 sw   Y  |S rw   )r3   r   r   r   rr   $_build_frozen_trial_from_trial_model)rR   r   r.   trial_modelfrozen_trialr1   r1   r2   	get_trial8  s   
zRDBStorage.get_trialTr   statesContainer[TrialState] | Nonelist[FrozenTrial]c                 C  s$   |  ||t d}|rt|S |S )N)_get_trialssetrV   r   )rR   rp   r   r:  trialsr1   r1   r2   get_all_trials?  s   zRDBStorage.get_all_trialsincluded_trial_idsset[int]trial_id_greater_thanc                   s  t fdd D  tj}tj|| |tjt	
tjjt	
tjjt	
tjjt	
tjjt	
tjjtjj|k}|d urbt|tsXJ |tjj|}z8t dkrdkr|ttjj tjjk}ndkr|tjjk}n|}|tjj }W n/ tjy }	 z"td|	d |tjj } fdd|D }W Y d }	~	nd }	~	ww fd	d|D }
W d    |
S 1 sw   Y  |
S )
Nc                 3  s    | ]	}| kr|V  qd S rw   r1   )rc   r   )rD  r1   r2   	<genexpr>P  s    z)RDBStorage._get_trials.<locals>.<genexpr>r   r=  z!Caught an error from sqlalchemy: z'. Falling back to a slower alternative.c                   s$   g | ]}|j  v s|j kr|qS r1   r   )rc   t)rB  rD  r1   r2   re     s
    z*RDBStorage._get_trials.<locals>.<listcomp>c                   s   g | ]}  |qS r1   )r6  )rc   r   rR   r1   r2   re     s    ) r?  r3   r   r   rj   rr   r   r   optionsrJ   selectinloadr   r   user_attributessystem_attributesr   r   rp   
isinstancer   rW   in_r   r   or_r   r   r   r#   OperationalErrorr&   warning)rR   rp   r:  rB  rD  r.   r   _querytrial_modelsr/   r@  r1   )rB  rR   rD  r2   r>  I  sZ   




66zRDBStorage._get_trialsc                 C  s   |j rdd |j D }|j D ]}tj|j|j||j< qnd }t|jdd d}t	|j
|jd ||j|jdd |D dd |D d	d |jD d
d |jD dd |jD |jdS )Nc                 S  s   g | ]}d qS )r   r1   )rc   _r1   r1   r2   re     s    zCRDBStorage._build_frozen_trial_from_trial_model.<locals>.<listcomp>c                 S     | j S rw   )param_id)pr1   r1   r2   <lambda>  s    zARDBStorage._build_frozen_trial_from_trial_model.<locals>.<lambda>)r|   c                 S  s$   i | ]}|j t|j|jqS r1   )r   r   r   r   to_external_reprr   rc   rW  r1   r1   r2   r     s    zCRDBStorage._build_frozen_trial_from_trial_model.<locals>.<dictcomp>c                 S  r   r1   )r   r   r   r   rZ  r1   r1   r2   r     s    c                 S  r   r1   r   r   r1   r1   r2   r     r   c                 S  r   r1   r   r   r1   r1   r2   r     s    c                 S  s"   i | ]}|j tj|j|jqS r1   )r   r   r  !stored_repr_to_intermediate_valuer   r
  )rc   r   r1   r1   r2   r     s    
r   )r   r   r  stored_repr_to_valuer}   r  r`   sortedr   r   r   rW   r   r   rK  rL  r   r   )rR   r   r   value_modelr   r1   r1   r2   r6    s>   
z/RDBStorage._build_frozen_trial_from_trial_modelc                 C  s<   |  |}t|dkrtd|d }| ||}| |S )Nr   zBBest trial can be obtained only for single-objective optimization.r   )r   r   RuntimeError_get_best_trial_idr9  )rR   rp   r   ra   r   r1   r1   r2   get_best_trial  s   

zRDBStorage.get_best_trialra   r   c                 C  sf   t | j$}|tjkrtj|d|W  d    S tj|d|W  d    S 1 s,w   Y  d S )Nr   )r3   r   r   MAXIMIZEr   r   find_max_value_trial_idfind_min_value_trial_id)rR   rp   ra   r.   r1   r1   r2   r`    s   
$zRDBStorage._get_best_trial_idc                 C  s0   |  dsd S d|v rd S d|d< td d S )Nr  pool_pre_pingTzJpool_pre_ping=True was set to engine_kwargs to prevent connection timeout.)
startswithr&   r'   )r9   r;   r1   r1   r2   rF     s   
z/RDBStorage._set_default_engine_kwargs_for_mysqltemplatec                 C  s   | j tjdS )N)SCHEMA_VERSION)formatr   rh  )rg  r1   r1   r2   rD     s   z%RDBStorage._fill_storage_url_templatec                 C     | j   dS )a  Removes the current session.

        A session is stored in SQLAlchemy's ThreadLocalRegistry for each thread. This method
        closes and removes the session which is associated to the current thread. Particularly,
        under multi-thread use cases, it is important to call this method *from each thread*.
        Otherwise, all sessions and their associated DB connections are destructed by a thread
        that occasionally invoked the garbage collector. By default, it is not allowed to touch
        a SQLite connection from threads other than the thread that created the connection.
        Therefore, we need to explicitly close the connection from each thread.

        N)r   removerH  r1   r1   r2   remove_session  s   zRDBStorage.remove_sessionc                 C  rj  )zUpgrade the storage schema.N)rP   upgraderH  r1   r1   r2   rm    s   zRDBStorage.upgradec                 C  
   | j  S )z9Return the schema version currently used by this storage.)rP   get_current_versionrH  r1   r1   r2   ro       
zRDBStorage.get_current_versionc                 C  rn  )z!Return the latest schema version.)rP   get_head_versionrH  r1   r1   r2   rq    rp  zRDBStorage.get_head_version	list[str]c                 C  rn  )zReturn the schema version list.)rP   get_all_versionsrH  r1   r1   r2   rs    rp  zRDBStorage.get_all_versionsc                 C  s   t | jdA}tj||}|d u rtj|d}|| n!tj||d}|d us,J |tj	 
 |_W d    d S W d    d S 1 sJw   Y  d S )NTrF  )r3   r   r   TrialHeartbeatModelr   ri   r"  r   funcr   scalar	heartbeat)rR   r   r.   rw  r1   r1   r2   record_heartbeat   s   "zRDBStorage.record_heartbeat	list[int]c           	      C  s   | j d usJ | jd u rd| j  }n| j}g }t| jdi}|tj  }|d us.J |j	d d}|
tjttjjtjjtjktjj|k }|D ](}t|jdkr_qUt|jdkshJ |jd j}|| t|dkr}||j qUW d    |S 1 sw   Y  |S )N   T)tzinfor   r   )seconds)r5   r6   r3   r   r"  r   ru  r   rv  replacer   r   r   rI  rJ   rJ  
heartbeatsr   rW   r   r   rp   r   r   rw  r   r   r   )	rR   rp   r6   stale_trial_idsr.   current_heartbeatrunning_trialsr   rw  r1   r1   r2   _get_stale_trial_ids  s8   


zRDBStorage._get_stale_trial_idsc                 C  rU  rw   )r5   rH  r1   r1   r2   get_heartbeat_interval.  s   z!RDBStorage.get_heartbeat_intervalc                 C  rU  rw   )r7   rH  r1   r1   r2   get_failed_trial_callback1  s   z$RDBStorage.get_failed_trial_callback)NF)r9   r:   r;   r<   r=   r   r5   r>   r6   r>   r7   r?   r8   r   r    r@   )r    rT   )rW   rT   r    r@   rw   )r[   r\   r]   r^   r    r_   )rp   r_   r    r@   )r.   rv   r    r:   )rp   r_   r|   r:   r}   r   r    r@   )rp   r_   r|   r:   r}   r   r    r@   )r]   r:   r    r_   )rp   r_   r    r:   )rp   r_   r    r   )rp   r_   r    r   )r   r_   r    r   )r    r   )rp   r_   r   r   r    r_   )rp   r_   r   r   r    r   )rp   r_   r   r   r.   rv   r    r   )
r   r_   r   r:   r   r   r   r   r    r@   )r   r_   r   r:   r   r   r   r   r   r   r    r@   )r.   rv   r   r_   r   r:   r   r   r   r   r   r   r    r@   )r   r_   r   r:   r    r   )r   r_   rW   r   r   r   r    r   )
r.   rv   r   r  r`   r_   r}   r   r    r@   )r   r_   r   r_   r   r   r    r@   )
r.   rv   r   r_   r   r_   r   r   r    r@   )r   r_   r|   r:   r}   r   r    r@   )r   r_   r|   r:   r}   r   r    r@   )r.   rv   r  r  r   r_   r|   r:   r}   r   r    r@   )rp   r_   r1  r_   r    r_   )r   r_   r    r   )TN)rp   r_   r   r   r:  r;  r    r<  )
rp   r_   r:  r;  rB  rC  rD  r_   r    r<  )r   r   r    r   )rp   r_   r    r   )rp   r_   ra   r   r    r_   )r9   r:   r;   r   r    r@   )rg  r:   r    r:   r    r@   r    r:   r    rr  )r   r_   r    r@   )rp   r_   r    ry  )r    r>   )r    r?   )5__name__
__module____qualname____doc__rS   rX   rZ   ro   ru   staticmethodrf   r   r   rm   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r	  r   r  r  r   r5  r9  rA  r>  r6  ra  r`  rF   rD   rl  rm  ro  rq  rs  rx  r  r  r  r1   r1   r1   r2   r4   j   s    b
-









	
	



)
@
I
	
%








.




C
+









!r4   c                   @  s   e Zd Zd)d	d
Zd*ddZd*ddZd+ddZd*ddZd,ddZd,ddZ	d,ddZ
d-ddZd*ddZd.d d!Zd/d#d$Zd0d&d'Zd(S )1rO   r9   r:   rG   'sqlalchemy.engine.Engine'r   r   r    r@   c                 C  s&   || _ || _|| _|   |   d S rw   )r9   rG   r   _init_version_info_model_init_alembic)rR   r9   rG   r   r1   r1   r2   rS   8  s
   z_VersionManager.__init__c                 C  st   t | jd*}tj|}|d ur	 W d    d S tjtjtjd}|| W d    d S 1 s3w   Y  d S )NT)schema_versionlibrary_version)	r3   r   r   VersionInfoModelfindrh  r   __version__ri   rR   r.   version_infor1   r1   r2   r  D  s   "z(_VersionManager._init_version_info_modelc                 C  s   t dt j | j ,}tj|}|	 d u}|r&	 W d    d S | 
 r/|  }n|  }W d    n1 s=w   Y  | | d S )Nalembic)logging	getLoggersetLevelWARNrG   connectalembic_migrationMigrationContext	configureget_current_revision_is_alembic_supportedrq  _get_base_version_set_alembic_revision)rR   
connectioncontextis_initializedrevisionr1   r1   r2   r  P  s   
z_VersionManager._init_alembicr  c              	   C  s   | j  5}tj|}|  |  }||| W d    n1 s%w   Y  W d    d S W d    d S 1 s=w   Y  d S rw   )rG   r  r  r  r  begin_create_alembic_scriptstamp)rR   r  r  r  scriptr1   r1   r2   r  c  s   
"z%_VersionManager._set_alembic_revisionc                 C  s   t | j8}tj|}|d usJ |  }|  }||kr'	 W d    d S dtj d|j	 d}| 
 }W d    n1 s@w   Y  ||v rQ|d7 }t||d7 }t|)NzThe runtime optuna version zA is no longer compatible with the table schema (set up by optuna z). z[Please execute `$ optuna storage upgrade --storage $STORAGE_URL` for upgrading the storage.zNPlease try updating optuna to the latest version by `$ pip install -U optuna`.)r3   r   r   r  r  ro  rq  r   r  r  rs  r_  )rR   r.   r  current_versionhead_versionr0   known_versionsr1   r1   r2   rQ   j  s.   

	z0_VersionManager.check_table_schema_compatibilityc                 C  sN   | j  }tj|}| }W d    n1 sw   Y  |d us%J |S rw   )rG   r  r  r  r  r  )rR   r  r  r   r1   r1   r2   ro    s   
z#_VersionManager.get_current_versionc                 C  s    |   }| }|d usJ |S rw   )r  get_current_head)rR   r  current_headr1   r1   r2   rq    s   z _VersionManager.get_head_versionc                 C  s$   |   }| }|d usJ d|S )Nz0There should be exactly one base, i.e. v0.9.0.a.)r  get_base)rR   r  baser1   r1   r2   r    s   z!_VersionManager._get_base_versionrr  c                 C  s   |   }dd | D S )Nc                 S  r   r1   )r  )rc   rr1   r1   r2   re     r   z4_VersionManager.get_all_versions.<locals>.<listcomp>)r  walk_revisions)rR   r  r1   r1   r2   rs    s   z _VersionManager.get_all_versionsc                 C  sn   |   }t|d t| jd}tj|}|d usJ tj|_	t
j|_W d    d S 1 s0w   Y  d S )NheadT)_create_alembic_configalembic_commandrm  r3   r   r   r  r  rh  r  r   r  r  )rR   configr.   r  r1   r1   r2   rm    s   
"z_VersionManager.upgrader   c                 C  s`   t | j!}tj|}|d u r	 W d    dS |jtjkW  d    S 1 s)w   Y  d S rq   )r3   r   r   r  r  r  rh  r  r1   r1   r2   r    s   
$z%_VersionManager._is_alembic_supported 'alembic_script.ScriptDirectory'c                 C  s   |   }tj|}|S rw   )r  alembic_scriptScriptDirectoryfrom_config)rR   r  r  r1   r1   r2   r    s   z&_VersionManager._create_alembic_script'alembic_config.Config'c                 C  sX   t jt jtd}tt jt jtd}|dt| |dt| j	 |S )Nr  zalembic.iniscript_locationzsqlalchemy.url)
ospathr   dirname__file__alembic_configConfigset_main_optionescape_alembic_config_valuer9   )rR   alembic_dirr  r1   r1   r2   r    s
   z&_VersionManager._create_alembic_configN)r9   r:   rG   r  r   r   r    r@   r  )r  r:   r    r@   r  r  )r    r   )r    r  )r    r  )r  r  r  rS   r  r  r  rQ   ro  rq  r  rs  rm  r  r  r  r1   r1   r1   r2   rO   7  s    





 







rO   r}   r:   c                 C  s   |  ddS )N%z%%)r}  )r}   r1   r1   r2   r    s   r  )F)r   r   r   r   r    r!   )r}   r:   r    r:   )X
__future__r   collectionsr   collections.abcr   r   r   r   r   
contextlibr	   rV   r
   r   r   r  r  r   r#  r   typingr   r   rx   r)   r   r   optuna._experimentalr   optuna._importsr   optuna._typingr   optuna.storages._baser   r   optuna.storages._heartbeatr   optuna.study._frozenr   optuna.study._study_directionr   optuna.trialr   r   alembic.commandcommandr  alembic.configr  r  alembic.migration	migrationr  alembic.scriptr  r  r   sqlalchemy.dialects.mysqldialectsr  r  sqlalchemy.dialects.postgresqlr  r)  sqlalchemy.dialects.sqliter  r%  sqlalchemy.excexcr#   sqlalchemy.ormormrJ   sqlalchemy.sql.functionssql	functionssqlalchemy_sql_functionsoptuna.storages._rdbr   
get_loggerr  r&   r3   r4   rO   r  r1   r1   r1   r2   <module>   s    !       T 