From 43233fe469fd85d7c64978f01ed68de3288d43cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vicen=C8=9Biu=20Ciorbaru?= Date: Fri, 10 Jan 2025 10:08:24 +0200 Subject: [PATCH 001/118] Fix -DBUILD_CONFIG=mysql_release to keep standard cmake flags -DCMAKE_BUILD_TYPE=xxx sets some C compiler flags according to the build type. -DBUILD_CONFIG was completely overwriting them in some compiler / arch combinations and not in others. Make it consistently "append-only", not overwrite. Also, enforce the same set of flags for Release and RelWithDebInfo. This reverts ff1f611a0d84b84a06b100a3b6901fc6d8957ff5 as it is no longer necessary. Avoid assert() By default, CMAKE_BUILD_TYPE RelWithDebInfo or Release implies -DNDEBUG, which disables the assert() macro. MariaDB is deviating from that. Let us be explicit to use assert() only in debug builds. --- .../build_configurations/mysql_release.cmake | 104 ++++++++++++------ storage/innobase/include/trx0trx.h | 8 +- 2 files changed, 73 insertions(+), 39 deletions(-) diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index 096b0afd6aa..8a34b0a6071 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -187,30 +187,40 @@ IF(UNIX) # Default GCC flags IF(CMAKE_COMPILER_IS_GNUCC) SET(COMMON_C_FLAGS "-g -fno-omit-frame-pointer -fno-strict-aliasing -Wno-uninitialized") - SET(CMAKE_C_FLAGS_DEBUG "-O ${COMMON_C_FLAGS}") - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_DEBUG " ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELEASE " ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " ${COMMON_C_FLAGS}") + # MariaDB uses -O3 for release builds + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") ENDIF() IF(CMAKE_COMPILER_IS_GNUCXX) SET(COMMON_CXX_FLAGS "-g -fno-omit-frame-pointer -fno-strict-aliasing -Wno-uninitialized") - SET(CMAKE_CXX_FLAGS_DEBUG "-O ${COMMON_CXX_FLAGS}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_DEBUG " ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " ${COMMON_CXX_FLAGS}") + # MariaDB uses -O3 for release builds + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") ENDIF() # IBM Z flags IF(CMAKE_SYSTEM_PROCESSOR MATCHES "s390x") IF(RPM MATCHES "(rhel|centos)6" OR RPM MATCHES "(suse|sles)11") - SET(z_flags "-funroll-loops -march=z9-109 -mtune=z10 ") + SET(z_flags "-funroll-loops -march=z9-109 -mtune=z10") ELSEIF(RPM MATCHES "(rhel|centos)7" OR RPM MATCHES "(suse|sles)12") - SET(z_flags "-funroll-loops -march=z196 -mtune=zEC12 ") + SET(z_flags "-funroll-loops -march=z196 -mtune=zEC12") ELSE() SET(z_flags "") ENDIF() IF(CMAKE_COMPILER_IS_GNUCC) - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${z_flags}${CMAKE_C_FLAGS_RELWITHDEBINFO}") + STRING(APPEND CMAKE_C_FLAGS_RELEASE " ${z_flags}") + STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " ${z_flags}") ENDIF() IF(CMAKE_COMPILER_IS_GNUCXX) - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${z_flags}${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " ${z_flags}") + STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " ${z_flags}") ENDIF() UNSET(z_flags) ENDIF() @@ -221,11 +231,13 @@ IF(UNIX) IF(CMAKE_SYSTEM_PROCESSOR MATCHES "ia64") SET(COMMON_C_FLAGS "+DSitanium2 -mt -AC99") SET(COMMON_CXX_FLAGS "+DSitanium2 -mt -Aa") - SET(CMAKE_C_FLAGS_DEBUG "+O0 -g ${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_DEBUG "+O0 -g ${COMMON_CXX_FLAGS}") - # We have seen compiler bugs with optimisation and -g, so disabled for now - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "+O2 ${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "+O2 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_DEBUG " +O0 -g ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_DEBUG " +O0 -g ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELEASE " +O0 -g ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " +O0 -g ${COMMON_CXX_FLAGS}") + # We have seen compiler bugs with optimisation and -g, so disabled for now + STRING(APPEND CMAKE_C_FLAGS_RELEASE " +O2 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " +O2 ${COMMON_CXX_FLAGS}") ENDIF() ENDIF() SET(WITH_SSL no) @@ -240,10 +252,18 @@ IF(UNIX) SET(COMMON_C_FLAGS "${COMMON_C_FLAGS} -no-ftz -no-prefetch") SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -no-ftz -no-prefetch") ENDIF() - SET(CMAKE_C_FLAGS_DEBUG "${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_DEBUG "${COMMON_CXX_FLAGS}") - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -unroll2 -ip ${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -unroll2 -ip ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_DEBUG " ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_DEBUG " ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELEASE " -unroll2 -ip ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " -unroll2 -ip ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -unroll2 -ip ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -unroll2 -ip ${COMMON_CXX_FLAGS}") + + # MariaDB uses -O3 for release builds. + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") SET(WITH_SSL no) ENDIF() ENDIF() @@ -251,13 +271,21 @@ IF(UNIX) # Default Clang flags IF(CMAKE_C_COMPILER_ID MATCHES "Clang") SET(COMMON_C_FLAGS "-g -fno-omit-frame-pointer -fno-strict-aliasing -Wno-parentheses-equality -Wno-string-plus-int") - SET(CMAKE_C_FLAGS_DEBUG "${COMMON_C_FLAGS}") - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_DEBUG " ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELEASE " ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " ${COMMON_C_FLAGS}") + # MariaDB uses -O3 for release builds. + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") ENDIF() IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang") SET(COMMON_CXX_FLAGS "-g -fno-omit-frame-pointer -fno-strict-aliasing -Wno-parentheses-equality -Wno-string-plus-int") - SET(CMAKE_CXX_FLAGS_DEBUG "${COMMON_CXX_FLAGS}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_DEBUG " ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " ${COMMON_CXX_FLAGS}") + # MariaDB uses -O3 for release builds. + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") + STRING(REGEX REPLACE "-O2" "-O3" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") ENDIF() # Solaris flags @@ -270,27 +298,33 @@ IF(UNIX) IF(CMAKE_SYSTEM_PROCESSOR MATCHES "i386") SET(COMMON_C_FLAGS "-g -mt -fsimple=1 -ftrap=%none -nofstore -xbuiltin=%all -xlibmil -xlibmopt -xtarget=generic") SET(COMMON_CXX_FLAGS "-g0 -mt -fsimple=1 -ftrap=%none -nofstore -xbuiltin=%all -features=no%except -xlibmil -xlibmopt -xtarget=generic") - SET(CMAKE_C_FLAGS_DEBUG "-xO1 ${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_DEBUG "-xO1 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_DEBUG " -xO1 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_DEBUG " -xO1 ${COMMON_CXX_FLAGS}") IF(32BIT) - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-xO2 ${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-xO2 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELEASE " -xO2 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " -xO2 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -xO2 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -xO2 ${COMMON_CXX_FLAGS}") ELSEIF(64BIT) - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-xO3 ${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-xO3 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELEASE " -xO3 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " -xO3 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -xO3 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -xO3 ${COMMON_CXX_FLAGS}") ENDIF() - ELSE() + ELSE() # Assume !x86 is SPARC SET(COMMON_C_FLAGS "-g -Xa -xstrconst -mt") SET(COMMON_CXX_FLAGS "-g0 -noex -mt") IF(32BIT) - SET(COMMON_C_FLAGS "${COMMON_C_FLAGS} -xarch=sparc") - SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -xarch=sparc") - ENDIF() - SET(CMAKE_C_FLAGS_DEBUG "${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_DEBUG "${COMMON_CXX_FLAGS}") - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-xO3 ${COMMON_C_FLAGS}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-xO3 ${COMMON_CXX_FLAGS}") + STRING(APPEND COMMON_C_FLAGS " -xarch=sparc") + STRING(APPEND COMMON_CXX_FLAGS " -xarch=sparc") + ENDIF() + STRING(APPEND CMAKE_C_FLAGS_DEBUG " ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_DEBUG " ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELEASE " -xO3 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " -xO3 ${COMMON_CXX_FLAGS}") + STRING(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -xO3 ${COMMON_C_FLAGS}") + STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -xO3 ${COMMON_CXX_FLAGS}") ENDIF() ENDIF() ENDIF() diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 7a3df5cf125..9a1c5edd43f 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -618,14 +618,14 @@ public: { ut_ad(!mutex_is_owner()); mutex.wr_lock(); - ut_d(assert(!mutex_owner.exchange(pthread_self(), - std::memory_order_relaxed))); + assert(!mutex_owner.exchange(pthread_self(), + std::memory_order_relaxed)); } /** Release the mutex */ void mutex_unlock() { - ut_d(assert(mutex_owner.exchange(0, std::memory_order_relaxed) == - pthread_self())); + assert(mutex_owner.exchange(0, std::memory_order_relaxed) == + pthread_self()); mutex.wr_unlock(); } #ifndef SUX_LOCK_GENERIC From f60a8a680e717a53d78e873f29f7d70f8e60635e Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 9 Jan 2025 17:27:29 +1100 Subject: [PATCH 002/118] MDEV-35554 runtime error: call to function show_cached_thread_count() through pointer to incorrect function type. The argument is void* rather than char* and was missing system_status_var * as an argument. This shows up with UBSAN testing under clang. Reviewer: Brandon Nesterenko --- sql/mysqld.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c48f94e6601..c798956910f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7363,8 +7363,8 @@ static int show_threadpool_threads(THD *, SHOW_VAR *var, void *buff, #endif -static int show_cached_thread_count(THD *thd, SHOW_VAR *var, char *buff, - enum enum_var_type scope) +static int show_cached_thread_count(THD *thd, SHOW_VAR *var, void *buff, + system_status_var *, enum enum_var_type scope) { var->type= SHOW_LONG; var->value= buff; From d7f27d717287a385bc73a5d5950cc22f957fc152 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 9 Jan 2025 18:15:41 +1100 Subject: [PATCH 003/118] MDEV-33158: UBSAN via MYSQL_THDVAR_U{INT,LONG{,LONG}} In plugins, use the correct resolver for ULONG and ULONGLONG types. InnoDB has a UINT type as evidenced by "Unknown variable type code 0x182 in plugin 'InnoDB'." so the implementation for UNSIGNED INT was added. Any InnoDB mtr test that changes lock_wait_timeout, spider_param_force_commit and some MyRocks unsigned thread server variables can verify this change is correct. Reviewer: Brandon Nesterenko --- sql/sql_plugin.cc | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 56c7b3332a2..360dc650334 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -3227,6 +3227,11 @@ static int *mysql_sys_var_int(THD* thd, int offset) return (int *) intern_sys_var_ptr(thd, offset, true); } +static unsigned int *mysql_sys_var_uint(THD* thd, int offset) +{ + return (unsigned int *) intern_sys_var_ptr(thd, offset, true); +} + static long *mysql_sys_var_long(THD* thd, int offset) { return (long *) intern_sys_var_ptr(thd, offset, true); @@ -3897,19 +3902,28 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, continue; if (!(register_var(plugin_name_ptr, opt->name, opt->flags))) continue; - switch (opt->flags & PLUGIN_VAR_TYPEMASK) { + switch (opt->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_UNSIGNED)) { case PLUGIN_VAR_BOOL: ((thdvar_bool_t *) opt)->resolve= mysql_sys_var_char; break; case PLUGIN_VAR_INT: ((thdvar_int_t *) opt)->resolve= mysql_sys_var_int; break; + case PLUGIN_VAR_INT | PLUGIN_VAR_UNSIGNED: + ((thdvar_uint_t *) opt)->resolve= mysql_sys_var_uint; + break; case PLUGIN_VAR_LONG: ((thdvar_long_t *) opt)->resolve= mysql_sys_var_long; break; + case PLUGIN_VAR_LONG | PLUGIN_VAR_UNSIGNED: + ((thdvar_ulong_t *) opt)->resolve= mysql_sys_var_ulong; + break; case PLUGIN_VAR_LONGLONG: ((thdvar_longlong_t *) opt)->resolve= mysql_sys_var_longlong; break; + case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_UNSIGNED: + ((thdvar_ulonglong_t *) opt)->resolve= mysql_sys_var_ulonglong; + break; case PLUGIN_VAR_STR: ((thdvar_str_t *) opt)->resolve= mysql_sys_var_str; break; From c3fd0f189a512b8775b72f2b3622bf7bea3a90aa Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 12 Jan 2025 12:33:34 +1100 Subject: [PATCH 004/118] MDEV-33158: UBSAN - plugin.cc partial move to C++ casts There were too many C casts rather than C++ casts here. Started a partial conversion covering within-file scoped changes. Suggested by Brandon Nesterenko --- sql/sql_plugin.cc | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 360dc650334..b773c8ec954 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -3186,14 +3186,14 @@ void sync_dynamic_session_variables(THD* thd, bool global_lock) If required, will sync with global variables if the requested variable has not yet been allocated in the current thread. */ -static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) +static void *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) { DBUG_ENTER("intern_sys_var_ptr"); DBUG_ASSERT(offset >= 0); DBUG_ASSERT((uint)offset <= global_system_variables.dynamic_variables_head); if (!thd) - DBUG_RETURN((uchar*) global_system_variables.dynamic_variables_ptr + offset); + DBUG_RETURN(global_system_variables.dynamic_variables_ptr + offset); /* dynamic_variables_head points to the largest valid offset @@ -3205,7 +3205,7 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) sync_dynamic_session_variables(thd, global_lock); mysql_prlock_unlock(&LOCK_system_variables_hash); } - DBUG_RETURN((uchar*)thd->variables.dynamic_variables_ptr + offset); + DBUG_RETURN(thd->variables.dynamic_variables_ptr + offset); } @@ -3219,47 +3219,47 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) static char *mysql_sys_var_char(THD* thd, int offset) { - return (char *) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } static int *mysql_sys_var_int(THD* thd, int offset) { - return (int *) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } static unsigned int *mysql_sys_var_uint(THD* thd, int offset) { - return (unsigned int *) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } static long *mysql_sys_var_long(THD* thd, int offset) { - return (long *) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } static unsigned long *mysql_sys_var_ulong(THD* thd, int offset) { - return (unsigned long *) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } static long long *mysql_sys_var_longlong(THD* thd, int offset) { - return (long long *) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } static unsigned long long *mysql_sys_var_ulonglong(THD* thd, int offset) { - return (unsigned long long *) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } static char **mysql_sys_var_str(THD* thd, int offset) { - return (char **) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } static double *mysql_sys_var_double(THD* thd, int offset) { - return (double *) intern_sys_var_ptr(thd, offset, true); + return static_cast(intern_sys_var_ptr(thd, offset, true)); } void plugin_thdvar_init(THD *thd) @@ -3520,7 +3520,7 @@ uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) const if (type == OPT_GLOBAL) thd= NULL; - return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false); + return (uchar*) intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false); } return *(uchar**) (plugin_var+1); } @@ -3529,8 +3529,8 @@ uchar* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type) const bool sys_var_pluginvar::session_is_default(THD *thd) { uchar *value= plugin_var->flags & PLUGIN_VAR_THDLOCAL - ? intern_sys_var_ptr(thd, *(int*) (plugin_var+1), true) - : *(uchar**) (plugin_var+1); + ? static_cast(intern_sys_var_ptr(thd, *(int*) (plugin_var+1), true)) + : *reinterpret_cast(plugin_var+1); real_value_ptr(thd, OPT_SESSION); @@ -3772,27 +3772,27 @@ void plugin_opt_set_limits(struct my_option *options, break; case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL: options->var_type= GET_ENUM; - options->typelib= ((thdvar_enum_t*) opt)->typelib; - options->def_value= ((thdvar_enum_t*) opt)->def_val; + options->typelib= reinterpret_cast(opt)->typelib; + options->def_value= reinterpret_cast(opt)->def_val; options->min_value= options->block_size= 0; options->max_value= options->typelib->count - 1; break; case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL: options->var_type= GET_SET; - options->typelib= ((thdvar_set_t*) opt)->typelib; - options->def_value= ((thdvar_set_t*) opt)->def_val; + options->typelib= reinterpret_cast(opt)->typelib; + options->def_value= reinterpret_cast(opt)->def_val; options->min_value= options->block_size= 0; options->max_value= (1ULL << options->typelib->count) - 1; break; case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL: options->var_type= GET_BOOL; - options->def_value= ((thdvar_bool_t*) opt)->def_val; + options->def_value= reinterpret_cast(opt)->def_val; options->typelib= &bool_typelib; break; case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL: options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ? GET_STR_ALLOC : GET_STR); - options->def_value= (intptr) ((thdvar_str_t*) opt)->def_val; + options->def_value= reinterpret_cast(reinterpret_cast(opt)->def_val); break; default: DBUG_ASSERT(0); @@ -3831,7 +3831,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, size_t plugin_name_len= strlen(plugin_name); size_t optnamelen; const int max_comment_len= 255; - char *comment= (char *) alloc_root(mem_root, max_comment_len + 1); + char *comment= static_cast(alloc_root(mem_root, max_comment_len + 1)); char *optname; int index= 0, UNINIT_VAR(offset); @@ -3843,7 +3843,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, DBUG_ENTER("construct_options"); - plugin_name_ptr= (char*) alloc_root(mem_root, plugin_name_len + 1); + plugin_name_ptr= static_cast(alloc_root(mem_root, plugin_name_len + 1)); safe_strcpy(plugin_name_ptr, plugin_name_len + 1, plugin_name); my_casedn_str(&my_charset_latin1, plugin_name_ptr); convert_underscore_to_dash(plugin_name_ptr, plugin_name_len); From cb26d41d8129b156e5ad4b0344790bd802a722c9 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 10 Jan 2025 12:59:01 +1100 Subject: [PATCH 005/118] MDEV-35735: UBSAN: spider udf functions mismatch with UDF defination The mismatch occurs on the function calls as in the sql/sql_udf.h the types of "error" and "is_null" are unsigned char rather than char. This is corrected for the udf functions: * spider_direct_sql * spider_direct_bg_sql * spider_flush_table_mon_cache * spider_copy_tables * spider_ping_table Reviewer: Yuchen Pei --- storage/spider/spd_copy_tables.cc | 4 ++-- storage/spider/spd_direct_sql.cc | 4 ++-- storage/spider/spd_ping_table.cc | 4 ++-- storage/spider/spd_udf.cc | 28 ++++++++++++++-------------- storage/spider/spd_udf.h | 12 ++++++------ 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/storage/spider/spd_copy_tables.cc b/storage/spider/spd_copy_tables.cc index 4c361df0562..d9cf32b3923 100644 --- a/storage/spider/spd_copy_tables.cc +++ b/storage/spider/spd_copy_tables.cc @@ -714,8 +714,8 @@ int spider_udf_bg_copy_exec_sql( long long spider_copy_tables_body( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { int error_num, roop_count, all_link_cnt = 0, use_table_charset; SPIDER_COPY_TABLES *copy_tables = NULL; diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index 7c7f9aa7558..5aabb5c07fc 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -1225,8 +1225,8 @@ void spider_udf_free_direct_sql_alloc( long long spider_direct_sql_body( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error, + unsigned char *is_null, + unsigned char *error, my_bool bg ) { int error_num, roop_count; diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc index 2795f8a3bb6..8e4f8a2214b 100644 --- a/storage/spider/spd_ping_table.cc +++ b/storage/spider/spd_ping_table.cc @@ -1071,8 +1071,8 @@ int spider_ping_table_cache_compare( long long spider_ping_table_body( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { int error_num = 0, link_idx, flags, full_mon_count, current_mon_count, success_count, fault_count, tmp_error_num = 0; diff --git a/storage/spider/spd_udf.cc b/storage/spider/spd_udf.cc index 023285cb4f1..fc7ca93c85b 100644 --- a/storage/spider/spd_udf.cc +++ b/storage/spider/spd_udf.cc @@ -22,8 +22,8 @@ extern "C" { long long spider_direct_sql( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { return spider_direct_sql_body(initid, args, is_null, error, FALSE); } @@ -46,8 +46,8 @@ void spider_direct_sql_deinit( long long spider_bg_direct_sql( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { return spider_direct_sql_bg_end(initid); } @@ -68,8 +68,8 @@ void spider_bg_direct_sql_deinit( void spider_bg_direct_sql_clear( UDF_INIT *initid, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { spider_direct_sql_bg_start(initid); } @@ -77,8 +77,8 @@ void spider_bg_direct_sql_clear( void spider_bg_direct_sql_add( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { spider_direct_sql_body(initid, args, is_null, error, TRUE); } @@ -87,8 +87,8 @@ void spider_bg_direct_sql_add( long long spider_ping_table( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { return spider_ping_table_body(initid, args, is_null, error); } @@ -110,8 +110,8 @@ void spider_ping_table_deinit( long long spider_flush_table_mon_cache( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { return spider_flush_table_mon_cache_body(); } @@ -132,8 +132,8 @@ void spider_flush_table_mon_cache_deinit( long long spider_copy_tables( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ) { return spider_copy_tables_body(initid, args, is_null, error); } diff --git a/storage/spider/spd_udf.h b/storage/spider/spd_udf.h index d00a6151894..a297640d945 100644 --- a/storage/spider/spd_udf.h +++ b/storage/spider/spd_udf.h @@ -16,8 +16,8 @@ long long spider_direct_sql_body( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error, + unsigned char *is_null, + unsigned char *error, my_bool bg ); @@ -45,8 +45,8 @@ long long spider_direct_sql_bg_end( long long spider_ping_table_body( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ); my_bool spider_ping_table_init_body( @@ -64,8 +64,8 @@ long long spider_flush_table_mon_cache_body(); long long spider_copy_tables_body( UDF_INIT *initid, UDF_ARGS *args, - char *is_null, - char *error + unsigned char *is_null, + unsigned char *error ); my_bool spider_copy_tables_init_body( From 6e86fe006399ca7f0a67cc5d4e0b9cfcf3cf63bb Mon Sep 17 00:00:00 2001 From: Xiaochuan Cui Date: Fri, 29 Nov 2024 13:52:19 -0800 Subject: [PATCH 006/118] MDEV-35528: mariadb-binlog cannot process more than 1 logfiles when --stop-datetime is specified Fix regression introduced by commits 9588526 which attempted to address MDEV-27037. With the regression, mariadb-binlog cannot process multiple log files when --stop-datetime is specified. The change is to keep recording timestamp of last processed event, and after all log files are processed, if the last recorded timestamp has not reached specified --stop-datetime, it will emit a warning. This applies when processing local log files, or log files from remote servers. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc. Co-authored-by: Brandon Nesterenko Reviewed-by: Brandon Nesterenko --- client/mysqlbinlog.cc | 23 ++- ...nlog_mysqlbinlog_warn_stop_datetime.result | 136 +++++++++++++++--- ...nlog_mysqlbinlog_warn_stop_position.result | 76 ++++++++-- .../binlog_mysqlbinlog_warn_stop_datetime.inc | 106 ++++++++++++++ ...binlog_mysqlbinlog_warn_stop_datetime.test | 108 +++++++++----- .../binlog_mysqlbinlog_warn_stop_position.inc | 115 +++++++++++++++ ...binlog_mysqlbinlog_warn_stop_position.test | 93 +++++++++--- 7 files changed, 559 insertions(+), 98 deletions(-) create mode 100644 mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_datetime.inc create mode 100644 mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_position.inc diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 5762e3965b5..8e3ce812993 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -148,6 +148,8 @@ static const longlong stop_position_default= (longlong)(~(my_off_t)0); static char *start_datetime_str, *stop_datetime_str; static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX; +static my_time_t last_processed_datetime= MY_TIME_T_MAX; + static ulonglong rec_count= 0; static MYSQL* mysql = NULL; static const char* dirname_for_local_load= 0; @@ -1011,6 +1013,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, DBUG_ENTER("process_event"); Exit_status retval= OK_CONTINUE; IO_CACHE *const head= &print_event_info->head_cache; + my_time_t ev_when= ev->when; /* Bypass flashback settings to event */ ev->is_flashback= opt_flashback; @@ -1458,6 +1461,7 @@ err: retval= ERROR_STOP; end: rec_count++; + last_processed_datetime= ev_when; DBUG_PRINT("info", ("end event processing")); /* @@ -2847,7 +2851,6 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, IO_CACHE cache,*file= &cache; uchar tmp_buff[BIN_LOG_HEADER_SIZE]; Exit_status retval= OK_CONTINUE; - my_time_t last_ev_when= MY_TIME_T_MAX; if (logname && strcmp(logname, "-") != 0) { @@ -2953,21 +2956,8 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, "end of input", stop_position); } - /* - Emit a warning in the event that we finished processing input - before reaching the boundary indicated by --stop-datetime. - */ - if (stop_datetime != MY_TIME_T_MAX && - stop_datetime > last_ev_when) - { - retval = OK_STOP; - warning("Did not reach stop datetime '%s' " - "before end of input", stop_datetime_str); - } - goto end; } - last_ev_when= ev->when; if ((retval= process_event(print_event_info, ev, old_off, logname)) != OK_CONTINUE) goto end; @@ -3143,6 +3133,11 @@ int main(int argc, char** argv) start_position= BIN_LOG_HEADER_SIZE; } + if (stop_datetime != MY_TIME_T_MAX && + stop_datetime > last_processed_datetime) + warning("Did not reach stop datetime '%s' before end of input", + stop_datetime_str); + /* If enable flashback, need to print the events from the end to the beginning diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_warn_stop_datetime.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_warn_stop_datetime.result index 6ce0f2d63e5..88a3c6cc8ac 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_warn_stop_datetime.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_warn_stop_datetime.result @@ -1,23 +1,115 @@ - -# MDEV-27037 mysqlbinlog emits a warning when reaching EOF before stop-datetime - -set timestamp=1000000000; -CREATE TABLE t1(word VARCHAR(20)); -set timestamp=1000000010; -INSERT INTO t1 VALUES ("abirvalg"); -set timestamp=1000000020; -INSERT INTO t1 SELECT * FROM t1; -flush logs; -Case: Default, must not see warning. -# MYSQL_BINLOG --short-form MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file -Case: Stop datetime before EOF, must not see warning. -# MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:50' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file -Case: Stop datetime between records, must not see warning. -# MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file -Case: Stop datetime at EOF, must not see warning. -# MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file -Case: Stop datetime after EOF, must see warning. -# MYSQL_BINLOG --short-form --stop-datetime='2035-01-19 03:14:05' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file -WARNING: Did not reach stop datetime '2035-01-19 03:14:05' before end of input -DROP TABLE t1; +SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-01 10:20:30.123456'); +# +# Clear the existing binary log state, and start fresh using +# the timestamp variable set above +# +RESET MASTER; +create table t1 (a int); +insert into t1 values (1); +SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-02 10:20:30.123456'); +insert into t1 values (2); +SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-03 10:20:30.123456'); +flush binary logs; +SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-04 10:20:30.123456'); +insert into t1 values (3); +insert into t1 values (4); +SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-05 10:20:30.123456'); +insert into t1 values (5); +insert into t1 values (6); +insert into t1 values (7); +SET TIMESTAMP=UNIX_TIMESTAMP('2024-12-06 10:20:30.123456'); +flush binary logs; +drop table t1; +# Ensuring binary log order is correct +# +# +# Test using --read-from-remote-server +# +connection default; +# +# --stop-datetime tests +# Note: MDEV-35528 reported that mysqlbinlog would fail on tests cases +# 2.a, 2.b, and 2.c. +# +# Case 1.a) With one binlog file, a --stop-datetime before the end of +# the file should not result in a warning +# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-02 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +# +# Case 1.b) With one binlog file, a --stop-datetime at the end of the +# file should not result in a warning +# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-03 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +# +# Case 1.c) With one binlog file, a --stop-datetime beyond the end of +# the file should(!) result in a warning +# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-04 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +WARNING: Did not reach stop datetime '2024-12-04 10:20:30.123456' before end of input +# +# Case 2.a) With two binlog files, a --stop-datetime within the +# timespan of binlog 2 should: +# 1) not provide any warnings +# 2) not prevent binlog 1 or 2 from outputting the desired events +# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-04 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +include/assert_grep.inc [Ensure all intended GTIDs are present] +include/assert_grep.inc [Ensure the next GTID binlogged is _not_ present] +# +# Case 2.b) With two binlog files, a --stop-datetime at the end of +# binlog 2 should: +# 1) not provide any warnings +# 2) not prevent binlog 1 or 2 from outputting all events +# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-06 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +include/assert_grep.inc [Ensure a GTID exists for each transaction] +# +# Case 2.c) With two binlog files, a --stop-datetime beyond the end of +# binlog 2 should: +# 1) provide a warning that the stop datetime was not reached +# 2) not prevent binlog 1 or 2 from outputting all events +# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-07 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +WARNING: Did not reach stop datetime '2024-12-07 10:20:30.123456' before end of input +include/assert_grep.inc [Ensure a GTID exists for each transaction] +# +# +# Test using local binlog files +# +connection default; +# +# --stop-datetime tests +# Note: MDEV-35528 reported that mysqlbinlog would fail on tests cases +# 2.a, 2.b, and 2.c. +# +# Case 1.a) With one binlog file, a --stop-datetime before the end of +# the file should not result in a warning +# MYSQL_BINLOG --stop-datetime='2024-12-02 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +# +# Case 1.b) With one binlog file, a --stop-datetime at the end of the +# file should not result in a warning +# MYSQL_BINLOG --stop-datetime='2024-12-03 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +# +# Case 1.c) With one binlog file, a --stop-datetime beyond the end of +# the file should(!) result in a warning +# MYSQL_BINLOG --stop-datetime='2024-12-04 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +WARNING: Did not reach stop datetime '2024-12-04 10:20:30.123456' before end of input +# +# Case 2.a) With two binlog files, a --stop-datetime within the +# timespan of binlog 2 should: +# 1) not provide any warnings +# 2) not prevent binlog 1 or 2 from outputting the desired events +# MYSQL_BINLOG --stop-datetime='2024-12-04 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +include/assert_grep.inc [Ensure all intended GTIDs are present] +include/assert_grep.inc [Ensure the next GTID binlogged is _not_ present] +# +# Case 2.b) With two binlog files, a --stop-datetime at the end of +# binlog 2 should: +# 1) not provide any warnings +# 2) not prevent binlog 1 or 2 from outputting all events +# MYSQL_BINLOG --stop-datetime='2024-12-06 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +include/assert_grep.inc [Ensure a GTID exists for each transaction] +# +# Case 2.c) With two binlog files, a --stop-datetime beyond the end of +# binlog 2 should: +# 1) provide a warning that the stop datetime was not reached +# 2) not prevent binlog 1 or 2 from outputting all events +# MYSQL_BINLOG --stop-datetime='2024-12-07 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1 +WARNING: Did not reach stop datetime '2024-12-07 10:20:30.123456' before end of input +include/assert_grep.inc [Ensure a GTID exists for each transaction] +# # End of binlog_mysqlbinlog_warn_stop_datetime.test diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_warn_stop_position.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_warn_stop_position.result index 5b99d30bd84..1517fd765ac 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_warn_stop_position.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_warn_stop_position.result @@ -1,13 +1,65 @@ - -# MDEV-27037 mysqlbinlog emits a warning when reaching EOF before stop-condition - -Case: Default stop position, WARNING must not appear -# MYSQL_BINLOG --short-form --start-position=4 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1 -Case: Stop position before EOF, WARNING must not appear -# MYSQL_BINLOG --short-form --start-position=4 --stop-position=97 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1 -Case: Stop position at EOF, WARNING must not appear -# MYSQL_BINLOG --short-form --start-position=4 --stop-position=98 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1 -Case: Stop position after EOF, WARNING must appear -# MYSQL_BINLOG --short-form --start-position=4 --stop-position=99 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1 -WARNING: Did not reach stop position 99 before end of input +# +# Clear the existing binary log state. +# +RESET MASTER; +create table t1 (a int); +insert into t1 values (1); +insert into t1 values (2); +flush binary logs; +insert into t1 values (3); +# Tag binlog_f2_mid +insert into t1 values (4); +insert into t1 values (5); +insert into t1 values (6); +insert into t1 values (7); +flush binary logs; +drop table t1; +# Ensuring binary log order is correct +# Ensuring file offset of binlog_f2_mid < binlog_f1_end +# +# +# Test using local binlog files +# +connection default; +# +# --stop-position tests +# +# Case 1.a) With one binlog file, a --stop-position before the end of +# the file should not result in a warning +# MYSQL_BINLOG --stop-position=binlog_f1_pre_rotate binlog_f1_full --result-file=tmp/warn_position_test_file.out 2>&1 +# +# Case 1.b) With one binlog file, a --stop-position at the exact end of +# the file should not result in a warning +# MYSQL_BINLOG --stop-position=binlog_f1_end binlog_f1_full --result-file=tmp/warn_position_test_file.out 2>&1 +# +# Case 1.c) With one binlog file, a --stop-position past the end of the +# file should(!) result in a warning +# MYSQL_BINLOG --short-form --stop-position=binlog_f1_over_eof binlog_f1_full --result-file=tmp/warn_position_test_file.out 2>&1 +WARNING: Did not reach stop position before end of input +# +# Case 2.a) With two binlog files, a --stop-position targeting b2 which +# exists in the size of b1 should: +# 1) not provide any warnings +# 2) not prevent b2 from outputting its desired events before the +# stop position +# MYSQL_BINLOG --stop-position=binlog_f2_mid binlog_f1_full binlog_f2_full --result-file=tmp/warn_position_test_file.out 2>&1 +include/assert_grep.inc [Ensure all intended GTIDs are present] +include/assert_grep.inc [Ensure the next GTID binlogged is _not_ present] +# +# Case 2.b) With two binlog files, a --stop-position targeting the end +# of binlog 2 should: +# 1) not provide any warnings +# 2) not prevent b2 from outputting its entire binary log +# MYSQL_BINLOG --stop-position=binlog_f2_end binlog_f1_full binlog_f2_full --result-file=tmp/warn_position_test_file.out 2>&1 +include/assert_grep.inc [Ensure a GTID exists for each transaction] +include/assert_grep.inc [Ensure the last GTID binlogged is present] +# +# Case 2.c) With two binlog files, a --stop-position targeting beyond +# the eof of binlog 2 should: +# 1) provide a warning that the stop position was not reached +# 2) not prevent b2 from outputting its entire binary log +# MYSQL_BINLOG --stop-position=binlog_f2_over_eof binlog_f1_full binlog_f2_full --result-file=tmp/warn_position_test_file.out 2>&1 +WARNING: Did not reach stop position before end of input +include/assert_grep.inc [Ensure a GTID exists for each transaction] +# # End of binlog_mysqlbinlog_warn_stop_position.test diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_datetime.inc b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_datetime.inc new file mode 100644 index 00000000000..839e506551c --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_datetime.inc @@ -0,0 +1,106 @@ +# +# Helper file that ensures mysqlbinlog --stop-datetime behavior for local +# files or a remote server +# +# Parameters: +# read_from_remote_server (bool): A boolean that changes which source to use +# for mysqlbinlog. When true, reads remotely; when false, uses local files. +# + +--connection default +--let $MYSQLD_DATADIR= `select @@datadir` + +# PARAM_READ_FROM_REMOTE is used as a parameter to mysqlbinlog (_OUT suffix is +# output in echo commands). If using local files, they are blank; if reading +# from remote server, it is overridden to the correct values. +--let $PARAM_READ_FROM_REMOTE= +# Used in echo statements to remove potentially changing values +--let $PARAM_READ_FROM_REMOTE_OUT= + +if ($read_from_remote_server) +{ + --let $PARAM_READ_FROM_REMOTE= --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT + --let $PARAM_READ_FROM_REMOTE_OUT= --read-from-remote-server + # binlog files in --read-from-remote-server don't use file system path + --let $binlog_f1_full= $binlog_f1 + --let $binlog_f2_full= $binlog_f2 +} +if (!$read_from_remote_server) +{ + # If using local files, file system path to the binlog files is needed + --let $binlog_f1_full= $MYSQLD_DATADIR/$binlog_f1 + --let $binlog_f2_full= $MYSQLD_DATADIR/$binlog_f2 +} + +--echo # +--echo # --stop-datetime tests +--echo # Note: MDEV-35528 reported that mysqlbinlog would fail on tests cases +--echo # 2.a, 2.b, and 2.c. +--echo # + +--echo # Case 1.a) With one binlog file, a --stop-datetime before the end of +--echo # the file should not result in a warning +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b1_timestamp2' binlog_f1_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b1_timestamp2' $binlog_f1_full --result-file=$binlog_out 2>&1 + +--echo # +--echo # Case 1.b) With one binlog file, a --stop-datetime at the end of the +--echo # file should not result in a warning +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b1_timestamp3' binlog_f1_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b1_timestamp3' $binlog_f1_full --result-file=$binlog_out 2>&1 + +--echo # +--echo # Case 1.c) With one binlog file, a --stop-datetime beyond the end of +--echo # the file should(!) result in a warning +--let $future_timestamp= 2035-12-06 10:20:30.123456 +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b2_timestamp1' binlog_f1_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b2_timestamp1' $binlog_f1_full --result-file=$binlog_out 2>&1 + +--echo # +--echo # Case 2.a) With two binlog files, a --stop-datetime within the +--echo # timespan of binlog 2 should: +--echo # 1) not provide any warnings +--echo # 2) not prevent binlog 1 or 2 from outputting the desired events + +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b2_timestamp1' binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b2_timestamp1' $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1 + +--let $server_id= `SELECT @@GLOBAL.server_id` +--let $domain_id= `SELECT @@GLOBAL.gtid_domain_id` +--let $assert_file= $binlog_out +--let $assert_text= Ensure all intended GTIDs are present +--let $assert_select= GTID $domain_id-$server_id- +--let $assert_count= 3 +--source include/assert_grep.inc + +--let $assert_text= Ensure the next GTID binlogged is _not_ present +--let $assert_select= GTID $binlog_f2_gtid_after_midpoint +--let $assert_count= 0 +--source include/assert_grep.inc + +--echo # +--echo # Case 2.b) With two binlog files, a --stop-datetime at the end of +--echo # binlog 2 should: +--echo # 1) not provide any warnings +--echo # 2) not prevent binlog 1 or 2 from outputting all events +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b2_timestamp3' binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b2_timestamp3' $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1 + +--let $assert_text= Ensure a GTID exists for each transaction +--let $assert_select= GTID $domain_id-$server_id- +--let $assert_count= 8 +--source include/assert_grep.inc + +--echo # +--echo # Case 2.c) With two binlog files, a --stop-datetime beyond the end of +--echo # binlog 2 should: +--echo # 1) provide a warning that the stop datetime was not reached +--echo # 2) not prevent binlog 1 or 2 from outputting all events +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b2_timestamp_not_reached' binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b2_timestamp_not_reached' $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1 + +--let $assert_text= Ensure a GTID exists for each transaction +--let $assert_select= GTID $domain_id-$server_id- +--let $assert_count= 8 +--source include/assert_grep.inc + diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_datetime.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_datetime.test index 9d30544c5f4..f862f0e7887 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_datetime.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_datetime.test @@ -1,42 +1,86 @@ ---echo ---echo # MDEV-27037 mysqlbinlog emits a warning when reaching EOF before stop-datetime ---echo +# +# Test ensures that --stop-datetime work correctly for mysqlbinlog. This high +# level test sets up the binary log (and tags certain locations for comparison), +# and the helper file binlog_mysqlbinlog_warn_stop_datetime.inc performs the +# actual tests. +# +# References: +# MDEV-27037: mysqlbinlog emits a warning when reaching EOF before +# stop-condition +# MDEV-35528: mariadb-binlog cannot process more than 1 logfiles when +# --stop-datetime is specified +# +--source include/have_log_bin.inc ---source include/have_binlog_format_statement.inc +--let $binlog_out_relpath= tmp/warn_datetime_test_file.out +--let $binlog_out= $MYSQLTEST_VARDIR/$binlog_out_relpath ---let ignored_output_file= $MYSQLTEST_VARDIR/tmp/warn_pos_test_file.out +--let $b1_timestamp1= 2024-12-01 10:20:30.123456 +--let $b1_timestamp2= 2024-12-02 10:20:30.123456 +--let $b1_timestamp3= 2024-12-03 10:20:30.123456 +--let $b2_timestamp1= 2024-12-04 10:20:30.123456 +--let $b2_timestamp2= 2024-12-05 10:20:30.123456 +--let $b2_timestamp3= 2024-12-06 10:20:30.123456 +--let $b2_timestamp_not_reached= 2024-12-07 10:20:30.123456 -set timestamp=1000000000; -CREATE TABLE t1(word VARCHAR(20)); -set timestamp=1000000010; -INSERT INTO t1 VALUES ("abirvalg"); -set timestamp=1000000020; -INSERT INTO t1 SELECT * FROM t1; ---let MYSQLD_DATADIR= `select @@datadir;` -flush logs; +--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b1_timestamp1') ---echo Case: Default, must not see warning. ---echo # MYSQL_BINLOG --short-form MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file ---exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1 +--echo # +--echo # Clear the existing binary log state, and start fresh using +--echo # the timestamp variable set above +--echo # +RESET MASTER; ---echo Case: Stop datetime before EOF, must not see warning. ---echo # MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:50' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file ---exec $MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:50' $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1 +--let $binlog_f1= query_get_value(SHOW MASTER STATUS, File, 1) +create table t1 (a int); +insert into t1 values (1); +--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b1_timestamp2') +insert into t1 values (2); +--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b1_timestamp3') +flush binary logs; +--let $binlog_f2= query_get_value(SHOW MASTER STATUS, File, 1) +--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b2_timestamp1') +insert into t1 values (3); +insert into t1 values (4); +--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b2_timestamp2') +--let $binlog_f2_gtid_after_midpoint= `SELECT @@GLOBAL.gtid_binlog_pos` +insert into t1 values (5); +insert into t1 values (6); +insert into t1 values (7); +--let $binlog_f2_last_gtid= `SELECT @@GLOBAL.gtid_binlog_pos` +--eval SET TIMESTAMP=UNIX_TIMESTAMP('$b2_timestamp3') +flush binary logs; +drop table t1; ---echo Case: Stop datetime between records, must not see warning. ---echo # MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file ---exec $MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1 +--echo # Ensuring binary log order is correct +--let $binlog_f1_show= query_get_value(SHOW BINARY LOGS, Log_name, 1) +if (`SELECT strcmp('$binlog_f1','$binlog_f1_show') != 0`) +{ + --echo # Real binlog_f1: $binlog_f1 + --echo # First binlog in SHOW BINLOG FILES: $binlog_f1_show + --die Wrong order of binary log files in SHOW BINARY LOGS +} +--let $binlog_f2_show= query_get_value(SHOW BINARY LOGS, Log_name, 2) +if (`SELECT strcmp('$binlog_f2','$binlog_f2_show') != 0`) +{ + --echo # Real binlog_f2: $binlog_f2 + --echo # First binlog in SHOW BINLOG FILES: $binlog_f2_show + --die Wrong order of binary log files in SHOW BINARY LOGS +} ---echo Case: Stop datetime at EOF, must not see warning. ---echo # MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file ---exec $MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1 +--echo # +--echo # +--echo # Test using --read-from-remote-server +--echo # +--let $read_from_remote_server= 1 +--source binlog_mysqlbinlog_warn_stop_datetime.inc ---echo Case: Stop datetime after EOF, must see warning. ---echo # MYSQL_BINLOG --short-form --stop-datetime='2035-01-19 03:14:05' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file ---exec $MYSQL_BINLOG --short-form --stop-datetime='2035-01-19 03:14:05' $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1 - -DROP TABLE t1; - ---remove_file $ignored_output_file +--echo # +--echo # +--echo # Test using local binlog files +--echo # +--let $read_from_remote_server= 0 +--source binlog_mysqlbinlog_warn_stop_datetime.inc +--echo # --echo # End of binlog_mysqlbinlog_warn_stop_datetime.test diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_position.inc b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_position.inc new file mode 100644 index 00000000000..2c3c565d692 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_position.inc @@ -0,0 +1,115 @@ +# +# Helper file that ensures mysqlbinlog --stop-position behavior for local +# files or a remote server +# +# Parameters: +# read_from_remote_server (bool): A boolean that changes which source to use +# for mysqlbinlog. When true, reads remotely; when false, uses local files. +# + +--connection default +--let $MYSQLD_DATADIR= `select @@datadir` + +# PARAM_READ_FROM_REMOTE is used as a parameter to mysqlbinlog (_OUT suffix is +# output in echo commands). If using local files, they are blank; if reading +# from remote server, it is overridden to the correct values. +--let $PARAM_READ_FROM_REMOTE= +# Used in echo statements to remove potentially changing values +--let $PARAM_READ_FROM_REMOTE_OUT= + +if ($read_from_remote_server) +{ + --let $PARAM_READ_FROM_REMOTE= --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT + --let $PARAM_READ_FROM_REMOTE_OUT= --read-from-remote-server + # binlog files in --read-from-remote-server don't use file system path + --let $binlog_f1_full= $binlog_f1 + --let $binlog_f2_full= $binlog_f2 +} +if (!$read_from_remote_server) +{ + # If using local files, file system path to the binlog files is needed + --let $binlog_f1_full= $MYSQLD_DATADIR/$binlog_f1 + --let $binlog_f2_full= $MYSQLD_DATADIR/$binlog_f2 +} + +--echo # +--echo # --stop-position tests +--echo # + +--echo # Case 1.a) With one binlog file, a --stop-position before the end of +--echo # the file should not result in a warning +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f1_pre_rotate binlog_f1_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f1_pre_rotate $binlog_f1_full --result-file=$binlog_out 2>&1 + +--echo # +--echo # Case 1.b) With one binlog file, a --stop-position at the exact end of +--echo # the file should not result in a warning +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f1_end binlog_f1_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f1_end $binlog_f1_full --result-file=$binlog_out 2>&1 + +--echo # +--echo # Case 1.c) With one binlog file, a --stop-position past the end of the +--echo # file should(!) result in a warning +--let $binlog_f1_over_eof= `SELECT $binlog_f1_end + 1` +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --short-form --stop-position=binlog_f1_over_eof binlog_f1_full --result-file=$binlog_out_relpath 2>&1 +--replace_result $binlog_f1_over_eof +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --short-form --stop-position=$binlog_f1_over_eof $binlog_f1_full --result-file=$binlog_out 2>&1 + +--echo # +--echo # Case 2.a) With two binlog files, a --stop-position targeting b2 which +--echo # exists in the size of b1 should: +--echo # 1) not provide any warnings +--echo # 2) not prevent b2 from outputting its desired events before the +--echo # stop position +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f2_mid binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f2_mid $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1 + +--let $server_id= `SELECT @@GLOBAL.server_id` +--let $domain_id= `SELECT @@GLOBAL.gtid_domain_id` +--let $assert_file= $binlog_out +--let $assert_text= Ensure all intended GTIDs are present +--let $assert_select= GTID $domain_id-$server_id- +--let $assert_count= 4 +--source include/assert_grep.inc + +--let $assert_text= Ensure the next GTID binlogged is _not_ present +--let $assert_select= GTID $binlog_f2_gtid_after_midpoint +--let $assert_count= 0 +--source include/assert_grep.inc + +--echo # +--echo # Case 2.b) With two binlog files, a --stop-position targeting the end +--echo # of binlog 2 should: +--echo # 1) not provide any warnings +--echo # 2) not prevent b2 from outputting its entire binary log +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f2_end binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1 +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f2_end $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1 + +--let $server_id= `SELECT @@GLOBAL.server_id` +--let $domain_id= `SELECT @@GLOBAL.gtid_domain_id` +--let $assert_text= Ensure a GTID exists for each transaction +--let $assert_select= GTID $domain_id-$server_id- +--let $assert_count= 8 +--source include/assert_grep.inc + +--let $assert_text= Ensure the last GTID binlogged is present +--let $assert_select= GTID $binlog_f2_last_gtid +--let $assert_count= 1 +--source include/assert_grep.inc + +--echo # +--echo # Case 2.c) With two binlog files, a --stop-position targeting beyond +--echo # the eof of binlog 2 should: +--echo # 1) provide a warning that the stop position was not reached +--echo # 2) not prevent b2 from outputting its entire binary log +--let $binlog_f2_over_eof= `SELECT $binlog_f2_end + 1` +--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f2_over_eof binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1 +--replace_result $binlog_f2_over_eof +--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f2_over_eof $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1 + +--let $server_id= `SELECT @@GLOBAL.server_id` +--let $domain_id= `SELECT @@GLOBAL.gtid_domain_id` +--let $assert_text= Ensure a GTID exists for each transaction +--let $assert_select= GTID $domain_id-$server_id- +--let $assert_count= 8 +--source include/assert_grep.inc diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_position.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_position.test index 97fabfc6513..a9179297220 100644 --- a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_position.test +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_warn_stop_position.test @@ -1,26 +1,83 @@ ---echo ---echo # MDEV-27037 mysqlbinlog emits a warning when reaching EOF before stop-condition ---echo +# +# Test ensures that --stop-position work correctly for mysqlbinlog. This high +# level test sets up the binary log (and tags certain locations for comparison), +# and the helper file binlog_mysqlbinlog_warn_stop_position.inc performs the +# actual tests. +# +# References: +# MDEV-27037: mysqlbinlog emits a warning when reaching EOF before +# stop-condition +# +--source include/have_log_bin.inc ---let assert_file= $MYSQLTEST_VARDIR/tmp/warn_pos_test_file.out ---let data_file= $MYSQLTEST_VARDIR/std_data/master-bin.000001 +--let $binlog_out_relpath= tmp/warn_position_test_file.out +--let $binlog_out= $MYSQLTEST_VARDIR/$binlog_out_relpath ---echo Case: Default stop position, WARNING must not appear ---echo # MYSQL_BINLOG --short-form --start-position=4 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1 ---exec $MYSQL_BINLOG --short-form --start-position=4 $data_file --result-file=$assert_file 2>&1 +--echo # +--echo # Clear the existing binary log state. +--echo # +RESET MASTER; ---echo Case: Stop position before EOF, WARNING must not appear ---echo # MYSQL_BINLOG --short-form --start-position=4 --stop-position=97 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1 ---exec $MYSQL_BINLOG --short-form --start-position=4 --stop-position=97 $data_file --result-file=$assert_file 2>&1 +--let $binlog_f1= query_get_value(SHOW MASTER STATUS, File, 1) +create table t1 (a int); +insert into t1 values (1); +insert into t1 values (2); +--let $binlog_f1_pre_rotate= query_get_value(SHOW MASTER STATUS, Position, 1) +flush binary logs; +--let $binlog_f2= query_get_value(SHOW MASTER STATUS, File, 1) +insert into t1 values (3); +--echo # Tag binlog_f2_mid +--let $binlog_f2_mid= query_get_value(SHOW MASTER STATUS, Position, 1) +insert into t1 values (4); +--let $binlog_f2_gtid_after_midpoint= `SELECT @@GLOBAL.gtid_binlog_pos` +insert into t1 values (5); +insert into t1 values (6); +insert into t1 values (7); +--let $binlog_f2_last_gtid= `SELECT @@GLOBAL.gtid_binlog_pos` +--let $binlog_f2_pre_rot= query_get_value(SHOW MASTER STATUS, Position, 1) +flush binary logs; +drop table t1; ---echo Case: Stop position at EOF, WARNING must not appear ---echo # MYSQL_BINLOG --short-form --start-position=4 --stop-position=98 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1 ---exec $MYSQL_BINLOG --short-form --start-position=4 --stop-position=98 $data_file --result-file=$assert_file 2>&1 +--echo # Ensuring binary log order is correct +--let $binlog_f1_show= query_get_value(SHOW BINARY LOGS, Log_name, 1) +--let $binlog_f1_end= query_get_value(SHOW BINARY LOGS, File_size, 1) +if (`SELECT strcmp('$binlog_f1','$binlog_f1_show') != 0`) +{ + --echo # Real binlog_f1: $binlog_f1 + --echo # First binlog in SHOW BINLOG FILES: $binlog_f1_show + --die Wrong order of binary log files in SHOW BINARY LOGS +} +--let $binlog_f2_show= query_get_value(SHOW BINARY LOGS, Log_name, 2) +--let $binlog_f2_end= query_get_value(SHOW BINARY LOGS, File_size, 2) +if (`SELECT strcmp('$binlog_f2','$binlog_f2_show') != 0`) +{ + --echo # Real binlog_f2: $binlog_f2 + --echo # First binlog in SHOW BINLOG FILES: $binlog_f2_show + --die Wrong order of binary log files in SHOW BINARY LOGS +} ---echo Case: Stop position after EOF, WARNING must appear ---echo # MYSQL_BINLOG --short-form --start-position=4 --stop-position=99 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1 ---exec $MYSQL_BINLOG --short-form --start-position=4 --stop-position=99 $data_file --result-file=$assert_file 2>&1 +--echo # Ensuring file offset of binlog_f2_mid < binlog_f1_end +if ($binlog_f2_mid > $binlog_f1_end) +{ + --echo # Binlog 1 end: $binlog_f1:$binlog_f1_end + --echo # Binlog 2 stop point: $binlog_f2:$binlog_f2_mid + --die Mid point chosen to end in binlog 2 does not exist in earlier binlog +} ---remove_file $assert_file +#--echo # +#--echo # +#--echo # Test using --read-from-remote-server +#--echo # +#--let $read_from_remote_server= 1 +#--emit warning is not supported by --read-from-remote-server now +#--source binlog_mysqlbinlog_warn_stop_position.inc +--echo # +--echo # +--echo # Test using local binlog files +--echo # +--let $read_from_remote_server= 0 +--source binlog_mysqlbinlog_warn_stop_position.inc + +--echo # --echo # End of binlog_mysqlbinlog_warn_stop_position.test From 04408fff40447f9aab12aed1957356e65e1c8b15 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sun, 12 Jan 2025 13:20:56 +1100 Subject: [PATCH 007/118] MDEV-35687 Various UBSAN function-type-mismatch debug_sync and myisam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit storage/maria/ma_open.c:352:7: runtime error: call to function debug_sync(THD*, char const*, unsigned long) through pointer to incorrect function type 'void (*)(void *, const char *, unsigned long)' The THD argument is a void *. Because of the way myisam is .c files the function prototype is mismatched. As Marko pointed out the MYSQL_THD is declared as void * in C. Thanks Jimmy Hรบ for noting that struct THD is the equalivalant in C to the class THD. The C NULL was also different to the C++ nullptr. Corrected the definations of MYSQL_THD and DEBUG_SYNC_C to be C and C++ compatible. --- include/mysql/plugin.h | 3 ++- include/mysql/service_debug_sync.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index d9aef6ac11c..87efbefde68 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -44,7 +44,8 @@ class THD; class Item; #define MYSQL_THD THD* #else -#define MYSQL_THD void* +struct THD; +typedef struct THD* MYSQL_THD; #endif typedef char my_bool; diff --git a/include/mysql/service_debug_sync.h b/include/mysql/service_debug_sync.h index 0bd49a13458..f7fdbf04832 100644 --- a/include/mysql/service_debug_sync.h +++ b/include/mysql/service_debug_sync.h @@ -351,7 +351,11 @@ extern void (*debug_sync_C_callback_ptr)(MYSQL_THD, const char *, size_t); #endif /* defined(ENABLED_DEBUG_SYNC) */ /* compatibility macro */ +#ifdef __cplusplus +#define DEBUG_SYNC_C(name) DEBUG_SYNC(nullptr, name) +#else #define DEBUG_SYNC_C(name) DEBUG_SYNC(NULL, name) +#endif #ifdef __cplusplus } From f862fe8b2bb359e0bbeb48d0d38047a95dc0e43c Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Mon, 16 Dec 2024 10:26:21 +1100 Subject: [PATCH 008/118] MDEV-35641 bring call to use_all_columns() forward when reading from mysql.servers TABLE::use_all_columns turn on all bits of read_set, which is interpreted by innodb as a request to read all columns. Without doing so before calling init_read_record(), innodb will not retrieve any columns if mysql.servers table has been altered to use innodb as the engine, and any foreign servers stored in the table are "lost". --- mysql-test/main/servers.result | 7 +++++++ mysql-test/main/servers.test | 9 +++++++++ sql/sql_servers.cc | 6 +++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/servers.result b/mysql-test/main/servers.result index d660aff1bd2..a02c3d6ac74 100644 --- a/mysql-test/main/servers.result +++ b/mysql-test/main/servers.result @@ -43,3 +43,10 @@ ERROR HY000: Can't read record in system table drop table mysql.servers; rename table mysql.servers_save to mysql.servers; drop server s1; +# +# MDEV-35641 foreign server "disappears" after ALTERing the servers system table to use innodb and FLUSH PRIVILEGES +# +CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS (HOST '127.0.0.1'); +ALTER TABLE mysql.servers ENGINE=innodb; +FLUSH PRIVILEGES; +drop server s1; diff --git a/mysql-test/main/servers.test b/mysql-test/main/servers.test index 1a58d5849f8..f46041bb21c 100644 --- a/mysql-test/main/servers.test +++ b/mysql-test/main/servers.test @@ -41,3 +41,12 @@ create server s2 foreign data wrapper foo options(user 'a'); drop table mysql.servers; rename table mysql.servers_save to mysql.servers; drop server s1; + +--echo # +--echo # MDEV-35641 foreign server "disappears" after ALTERing the servers system table to use innodb and FLUSH PRIVILEGES +--echo # +--source include/have_innodb.inc +CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS (HOST '127.0.0.1'); +ALTER TABLE mysql.servers ENGINE=innodb; +FLUSH PRIVILEGES; +drop server s1; diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 59a4679847b..ecf411ab313 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -283,7 +283,7 @@ end: static bool servers_load(THD *thd, TABLE_LIST *tables) { - TABLE *table; + TABLE *table= tables[0].table; READ_RECORD read_record_info; bool return_val= TRUE; DBUG_ENTER("servers_load"); @@ -292,7 +292,8 @@ static bool servers_load(THD *thd, TABLE_LIST *tables) free_root(&mem, MYF(0)); init_sql_alloc(key_memory_servers, &mem, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); - if (init_read_record(&read_record_info,thd,table=tables[0].table, NULL, NULL, + table->use_all_columns(); + if (init_read_record(&read_record_info,thd,table, NULL, NULL, 1,0, FALSE)) DBUG_RETURN(1); while (!(read_record_info.read_record())) @@ -405,7 +406,6 @@ get_server_from_table_to_cache(TABLE *table) FOREIGN_SERVER *server= (FOREIGN_SERVER *)alloc_root(&mem, sizeof(FOREIGN_SERVER)); DBUG_ENTER("get_server_from_table_to_cache"); - table->use_all_columns(); /* get each field into the server struct ptr */ ptr= get_field(&mem, table->field[0]); From faca9500fb3c1e5c56d9626f606df8de67513bc1 Mon Sep 17 00:00:00 2001 From: ParadoxV5 Date: Sat, 11 Jan 2025 12:09:47 -0700 Subject: [PATCH 009/118] MDEV-35430: Add cast to semi-sync wait skip msg This came after I prepared #3493. --- sql/semisync_master.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 437b9bb99b4..3e33cff06f6 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -938,8 +938,8 @@ int Repl_semi_sync_master::commit_trx(const char *trx_wait_binlog_name, sql_print_information( "Skipping semi-sync wait for transaction at pos %s, %lu. This " "should be because semi-sync turned off and on during the " - "lifetime of this transaction.", - trx_wait_binlog_name, trx_wait_binlog_pos);); + "lifetime of this transaction.", trx_wait_binlog_name, + static_cast(trx_wait_binlog_pos));); /* The only known reason for a missing entry at this point is if * semi-sync was turned off then on, so on debug builds, we track From d5a417b9d55ac2744b600463a1abaf065772d678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 13 Jan 2025 09:14:30 +0200 Subject: [PATCH 010/118] MDEV-35827 The generic MY_RELAX_CPU is expensive MY_RELAX_CPU(): On GCC and compatible compilers (including clang and its derivatives), let us use a null inline assembler block as the fallback. This should benefit s390x and LoongArch, for example. Also, let us remove the generic fallback block that does exactly the opposite of what this function aims to achieve: avoid hogging the memory bus so that other threads will have a chance to let our spin loop to proceed. On RISC-V, we will use __builtin_riscv_pause() which is a valid instruction encoding in all ISA versions according to https://gcc.gnu.org/pipermail/gcc-patches/2021-January/562936.html --- include/my_cpu.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/my_cpu.h b/include/my_cpu.h index 003087dd94d..67da4f93946 100644 --- a/include/my_cpu.h +++ b/include/my_cpu.h @@ -101,13 +101,11 @@ static inline void MY_RELAX_CPU(void) /* Changed from __ppc_get_timebase for musl compatibility */ __builtin_ppc_get_timebase(); #endif -#elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) +#elif defined __GNUC__ && defined __riscv + __builtin_riscv_pause(); +#elif defined __GNUC__ /* Mainly, prevent the compiler from optimizing away delay loops */ __asm__ __volatile__ ("":::"memory"); -#else - int32 var, oldval = 0; - my_atomic_cas32_strong_explicit(&var, &oldval, 1, MY_MEMORY_ORDER_RELAXED, - MY_MEMORY_ORDER_RELAXED); #endif } From 0d35fe6e5761cbee731ffcac55f2bf8eaf2a6a8f Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Mon, 23 Dec 2024 22:36:01 +0100 Subject: [PATCH 011/118] MDEV-35326: Memory Leak in init_io_cache_ext upon SHUTDOWN The problems were that: 1) resources was freed "asimetric" normal execution in send_eof, in case of error in destructor. 2) destructor was not called in case of SP for result objects. (so if the last SP execution ended with error resorces was not freeded on reinit before execution (cleanup() called before next execution) and destructor also was not called due to lack of delete call for the object) Result cleanup() renamed to reset_for_next_ps_execution() to better reflect function(). All result method revised and freeing resources made "symetric". Destructor of result object called for SP. Added skipped invalidation in case of error in insert. Removed misleading naming of reset(thd) (could be mixed with with reset()). --- sql/item_subselect.cc | 6 +- sql/sp_head.cc | 11 ++++ sql/sp_head.h | 11 +--- sql/sql_class.cc | 56 +++++++++++-------- sql/sql_class.h | 48 ++++++++-------- sql/sql_delete.cc | 14 +++++ sql/sql_insert.cc | 24 +++++++- sql/sql_prepare.cc | 2 +- sql/sql_union.cc | 10 ++-- sql/sql_update.cc | 14 +++++ .../spider/bugfix/r/mdev_35326.result | 14 +++++ .../spider/bugfix/t/mdev_35326.test | 21 +++++++ 12 files changed, 162 insertions(+), 69 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_35326.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_35326.test diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c0ac4022cd9..8da808ca3a0 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -3753,7 +3753,7 @@ void subselect_single_select_engine::cleanup() DBUG_ENTER("subselect_single_select_engine::cleanup"); prepared= executed= 0; join= 0; - result->cleanup(); + result->reset_for_next_ps_execution(); select_lex->uncacheable&= ~UNCACHEABLE_DEPENDENT_INJECTED; DBUG_VOID_RETURN; } @@ -3763,7 +3763,7 @@ void subselect_union_engine::cleanup() { DBUG_ENTER("subselect_union_engine::cleanup"); unit->reinit_exec_mechanism(); - result->cleanup(); + result->reset_for_next_ps_execution(); unit->uncacheable&= ~UNCACHEABLE_DEPENDENT_INJECTED; for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) sl->uncacheable&= ~UNCACHEABLE_DEPENDENT_INJECTED; @@ -5436,7 +5436,7 @@ void subselect_hash_sj_engine::cleanup() } DBUG_ASSERT(lookup_engine->engine_type() == UNIQUESUBQUERY_ENGINE); lookup_engine->cleanup(); - result->cleanup(); /* Resets the temp table as well. */ + result->reset_for_next_ps_execution(); /* Resets the temp table as well. */ DBUG_ASSERT(tmp_table); free_tmp_table(thd, tmp_table); tmp_table= NULL; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 506e755c2fd..c751636fbf7 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3665,6 +3665,17 @@ int sp_lex_keeper::cursor_reset_lex_and_exec_core(THD *thd, uint *nextp, return res; } +sp_lex_keeper::~sp_lex_keeper() +{ + if (m_lex_resp) + { + /* Prevent endless recursion. */ + m_lex->sphead= NULL; + delete m_lex->result; + lex_end(m_lex); + delete m_lex; + } +} /* sp_instr class functions diff --git a/sql/sp_head.h b/sql/sp_head.h index 3de8e843753..ba677053e87 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -1273,16 +1273,7 @@ public: { lex->sp_lex_in_use= TRUE; } - virtual ~sp_lex_keeper() - { - if (m_lex_resp) - { - /* Prevent endless recursion. */ - m_lex->sphead= NULL; - lex_end(m_lex); - delete m_lex; - } - } + virtual ~sp_lex_keeper(); /** Prepare execution of instruction using LEX, if requested check whenever diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 73e182edd0f..8cb5b4954aa 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -3066,7 +3066,7 @@ void Item_change_list::rollback_item_tree_changes() ** Functions to provide a interface to select results *****************************************************************************/ -void select_result::cleanup() +void select_result::reset_for_next_ps_execution() { /* do nothing */ } @@ -3135,6 +3135,7 @@ void select_send::abort_result_set() */ thd->spcont->end_partial_result_set= TRUE; } + reset_for_next_ps_execution(); DBUG_VOID_RETURN; } @@ -3145,7 +3146,7 @@ void select_send::abort_result_set() stored procedure statement. */ -void select_send::cleanup() +void select_send::reset_for_next_ps_execution() { is_result_set_started= FALSE; } @@ -3183,7 +3184,7 @@ bool select_send::send_eof() if (unlikely(thd->is_error())) return TRUE; ::my_eof(thd); - is_result_set_started= 0; + reset_for_next_ps_execution(); return FALSE; } @@ -3192,10 +3193,22 @@ bool select_send::send_eof() Handling writing to file ************************************************************************/ +bool select_to_file::free_recources() +{ + if (file >= 0) + { + (void) end_io_cache(&cache); + bool error= mysql_file_close(file, MYF(MY_WME)); + file= -1; + return error; + } + return FALSE; +} + bool select_to_file::send_eof() { - int error= MY_TEST(end_io_cache(&cache)); - if (unlikely(mysql_file_close(file, MYF(MY_WME))) || + int error= false; + if (unlikely(free_recources()) || unlikely(thd->is_error())) error= true; @@ -3203,20 +3216,19 @@ bool select_to_file::send_eof() { ::my_ok(thd,row_count); } - file= -1; return error; } +void select_to_file::abort_result_set() +{ + select_result_interceptor::abort_result_set(); + free_recources(); +} -void select_to_file::cleanup() +void select_to_file::reset_for_next_ps_execution() { /* In case of error send_eof() may be not called: close the file here. */ - if (file >= 0) - { - (void) end_io_cache(&cache); - mysql_file_close(file, MYF(0)); - file= -1; - } + free_recources(); path[0]= '\0'; row_count= 0; } @@ -3224,12 +3236,8 @@ void select_to_file::cleanup() select_to_file::~select_to_file() { - if (file >= 0) - { // This only happens in case of error - (void) end_io_cache(&cache); - mysql_file_close(file, MYF(0)); - file= -1; - } + DBUG_ASSERT(file < 0); + free_recources(); // just in case } /*************************************************************************** @@ -3716,9 +3724,9 @@ int select_singlerow_subselect::send_data(List &items) } -void select_max_min_finder_subselect::cleanup() +void select_max_min_finder_subselect::reset_for_next_ps_execution() { - DBUG_ENTER("select_max_min_finder_subselect::cleanup"); + DBUG_ENTER("select_max_min_finder_subselect::reset_for_next_ps_execution"); cache= 0; DBUG_VOID_RETURN; } @@ -3943,7 +3951,7 @@ bool select_dumpvar::check_simple_select() const } -void select_dumpvar::cleanup() +void select_dumpvar::reset_for_next_ps_execution() { row_count= 0; } @@ -4372,10 +4380,10 @@ void select_materialize_with_stats::reset() } -void select_materialize_with_stats::cleanup() +void select_materialize_with_stats::reset_for_next_ps_execution() { reset(); - select_unit::cleanup(); + select_unit::reset_for_next_ps_execution(); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 28aef92c31e..032d0bc2606 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5585,7 +5585,8 @@ public: */ virtual int send_data(List &items)=0; virtual ~select_result_sink() = default; - void reset(THD *thd_arg) { thd= thd_arg; } + // Used in cursors to initialize and reset + void reinit(THD *thd_arg) { thd= thd_arg; } }; class select_result_interceptor; @@ -5659,15 +5660,11 @@ public: */ virtual bool check_simple_select() const; virtual void abort_result_set() {} - /* - Cleanup instance of this class for next execution of a prepared - statement/stored procedure. - */ - virtual void cleanup(); + virtual void reset_for_next_ps_execution(); void set_thd(THD *thd_arg) { thd= thd_arg; } - void reset(THD *thd_arg) + void reinit(THD *thd_arg) { - select_result_sink::reset(thd_arg); + select_result_sink::reinit(thd_arg); unit= NULL; } #ifdef EMBEDDED_LIBRARY @@ -5773,9 +5770,9 @@ public: elsewhere. (this is used by ANALYZE $stmt feature). */ void disable_my_ok_calls() { suppress_my_ok= true; } - void reset(THD *thd_arg) + void reinit(THD *thd_arg) { - select_result::reset(thd_arg); + select_result::reinit(thd_arg); suppress_my_ok= false; } protected: @@ -5827,7 +5824,7 @@ private: {} void reset(THD *thd_arg) { - select_result_interceptor::reset(thd_arg); + select_result_interceptor::reinit(thd_arg); spvar_list= NULL; field_count= 0; } @@ -5871,7 +5868,7 @@ public: void reset(THD *thd_arg, sp_lex_keeper *lex_keeper) { sp_cursor_statistics::reset(); - result.reset(thd_arg); + result.reinit(thd_arg); m_lex_keeper= lex_keeper; server_side_cursor= NULL; } @@ -5899,7 +5896,7 @@ public: bool send_eof() override; bool check_simple_select() const override { return FALSE; } void abort_result_set() override; - void cleanup() override; + void reset_for_next_ps_execution() override; select_result_interceptor *result_interceptor() override { return NULL; } }; @@ -5934,7 +5931,9 @@ public: { path[0]=0; } ~select_to_file(); bool send_eof() override; - void cleanup() override; + void abort_result_set() override; + void reset_for_next_ps_execution() override; + bool free_recources(); }; @@ -6011,7 +6010,7 @@ class select_insert :public select_result_interceptor { bool send_eof() override; void abort_result_set() override; /* not implemented: select_insert is never re-used in prepared statements */ - void cleanup() override; + void reset_for_next_ps_execution() override; }; @@ -6231,7 +6230,7 @@ public: int delete_record(); bool send_eof() override; virtual bool flush(); - void cleanup() override; + void reset_for_next_ps_execution() override; virtual bool create_result_table(THD *thd, List *column_types, bool is_distinct, ulonglong options, const LEX_CSTRING *alias, @@ -6406,9 +6405,10 @@ class select_union_recursive :public select_unit */ List rec_table_refs; /* - The count of how many times cleanup() was called with cleaned==false - for the unit specifying the recursive CTE for which this object was created - or for the unit specifying a CTE that mutually recursive with this CTE. + The count of how many times reset_for_next_ps_execution() was called with + cleaned==false for the unit specifying the recursive CTE for which this + object was created or for the unit specifying a CTE that mutually + recursive with this CTE. */ uint cleanup_count; long row_counter; @@ -6427,7 +6427,7 @@ class select_union_recursive :public select_unit bool create_table, bool keep_row_order, uint hidden) override; - void cleanup() override; + void reset_for_next_ps_execution() override; }; /** @@ -6497,7 +6497,7 @@ public: { result->abort_result_set(); /* purecov: inspected */ } - void cleanup() override + void reset_for_next_ps_execution() override { send_records= 0; } @@ -6600,7 +6600,7 @@ public: uint hidden) override; bool init_result_table(ulonglong select_options); int send_data(List &items) override; - void cleanup() override; + void reset_for_next_ps_execution() override; ha_rows get_null_count_of_col(uint idx) { DBUG_ASSERT(idx < table->s->fields); @@ -6633,7 +6633,7 @@ public: bool mx, bool all): select_subselect(thd_arg, item_arg), cache(0), fmax(mx), is_all(all) {} - void cleanup() override; + void reset_for_next_ps_execution() override; int send_data(List &items) override; bool cmp_real(); bool cmp_int(); @@ -7049,7 +7049,7 @@ public: int send_data(List &items) override; bool send_eof() override; bool check_simple_select() const override; - void cleanup() override; + void reset_for_next_ps_execution() override; }; /* Bits in sql_command_flags */ diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 25b3aef3ebe..fa677feb551 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1422,6 +1422,13 @@ void multi_delete::abort_result_set() { DBUG_ENTER("multi_delete::abort_result_set"); + /**************************************************************************** + + NOTE: if you change here be aware that almost the same code is in + multi_delete::send_eof(). + + ***************************************************************************/ + /* the error was handled or nothing deleted and no side effects return */ if (error_handled || (!thd->transaction->stmt.modified_non_trans_table && !deleted)) @@ -1622,6 +1629,13 @@ bool multi_delete::send_eof() /* reset used flags */ THD_STAGE_INFO(thd, stage_end); + /**************************************************************************** + + NOTE: if you change here be aware that almost the same code is in + multi_delete::abort_result_set(). + + ***************************************************************************/ + if (thd->transaction->stmt.modified_non_trans_table) thd->transaction->all.modified_non_trans_table= TRUE; thd->transaction->all.m_unsafe_rollback_flags|= diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e1d87e29869..000695c5399 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4131,7 +4131,7 @@ int select_insert::prepare2(JOIN *) } -void select_insert::cleanup() +void select_insert::reset_for_next_ps_execution() { /* select_insert/select_create are never re-used in prepared statement */ DBUG_ASSERT(0); @@ -4245,6 +4245,13 @@ bool select_insert::prepare_eof() DBUG_PRINT("enter", ("trans_table: %d, table_type: '%s'", trans_table, table->file->table_type())); + /**************************************************************************** + + NOTE: if you change here be aware that almost the same code is in + select_insert::abort_result_set(). + + ****************************************************************************/ + #ifdef WITH_WSREP error= (thd->wsrep_cs().current_error()) ? -1 : (thd->locked_tables_mode <= LTM_LOCK_TABLES) ? @@ -4377,6 +4384,12 @@ void select_insert::abort_result_set() */ if (table && table->file->is_open()) { + /**************************************************************************** + + NOTE: if you change here be aware that almost the same code is in + select_insert::prepare_eof(). + + ****************************************************************************/ bool changed, transactional_table; /* If we are not in prelocked mode, we end the bulk insert started @@ -4404,7 +4417,14 @@ void select_insert::abort_result_set() If table creation failed, the number of rows modified will also be zero, so no check for that is made. */ - changed= (info.copied || info.deleted || info.updated); + if ((changed= (info.copied || info.deleted || info.updated))) + { + /* + We must invalidate the table in the query cache before binlog writing + and ha_autocommit_or_rollback. + */ + query_cache_invalidate3(thd, table, 1); + } transactional_table= table->file->has_transactions_and_rollback(); if (thd->transaction->stmt.modified_non_trans_table || thd->log_current_statement) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 93e81b2025d..9d53d7cf543 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3194,7 +3194,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) if (lex->result) { - lex->result->cleanup(); + lex->result->reset_for_next_ps_execution(); lex->result->set_thd(thd); } lex->allow_sum_func.clear_all(); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 53e604bfa92..09dc045b543 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -547,7 +547,7 @@ int select_unit::delete_record() tables of JOIN - exec_tmp_table_[1 | 2]. */ -void select_unit::cleanup() +void select_unit::reset_for_next_ps_execution() { table->file->extra(HA_EXTRA_RESET_STATE); table->file->ha_delete_all_rows(); @@ -902,11 +902,11 @@ bool select_unit_ext::send_eof() return (MY_TEST(error)); } -void select_union_recursive::cleanup() +void select_union_recursive::reset_for_next_ps_execution() { if (table) { - select_unit::cleanup(); + select_unit::reset_for_next_ps_execution(); free_tmp_table(thd, table); } @@ -2194,7 +2194,7 @@ bool st_select_lex_unit::exec() if (uncacheable || !item || !item->assigned() || describe) { if (!fake_select_lex && !(with_element && with_element->is_recursive)) - union_result->cleanup(); + union_result->reset_for_next_ps_execution(); for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select()) { ha_rows records_at_start= 0; @@ -2636,7 +2636,7 @@ bool st_select_lex_unit::cleanup() { if (union_result) { - ((select_union_recursive *) union_result)->cleanup(); + ((select_union_recursive *) union_result)->reset_for_next_ps_execution(); delete union_result; union_result= 0; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 4a13d83d52f..9dfb681b119 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2743,6 +2743,13 @@ void multi_update::abort_result_set() (!thd->transaction->stmt.modified_non_trans_table && !updated))) return; + /**************************************************************************** + + NOTE: if you change here be aware that almost the same code is in + multi_update::send_eof(). + + ***************************************************************************/ + /* Something already updated so we have to invalidate cache */ if (updated) query_cache_invalidate3(thd, update_tables, 1); @@ -3072,6 +3079,13 @@ bool multi_update::send_eof() killed_status= (local_error == 0) ? NOT_KILLED : thd->killed; THD_STAGE_INFO(thd, stage_end); + /**************************************************************************** + + NOTE: if you change here be aware that almost the same code is in + multi_update::abort_result_set(). + + ***************************************************************************/ + /* We must invalidate the query cache before binlog writing and ha_autocommit_... */ diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_35326.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_35326.result new file mode 100644 index 00000000000..41481447a6c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_35326.result @@ -0,0 +1,14 @@ +for master_1 +for child2 +for child3 +CREATE TABLE t (c INT) ENGINE=Spider; +CREATE PROCEDURE p() CONTAINS SQL READS SQL DATA SELECT * FROM t INTO OUTFILE 'foo.txt'; +Warnings: +Warning 1287 ' INTO FROM...' instead +CALL p(); +ERROR HY000: Unable to connect to foreign data source: localhost +drop procedure p; +drop table t; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_35326.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_35326.test new file mode 100644 index 00000000000..1ce8e1aa780 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_35326.test @@ -0,0 +1,21 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +let $MYSQLD_DATADIR= `select @@datadir`; + +CREATE TABLE t (c INT) ENGINE=Spider; +CREATE PROCEDURE p() CONTAINS SQL READS SQL DATA SELECT * FROM t INTO OUTFILE 'foo.txt'; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +CALL p(); +remove_file $MYSQLD_DATADIR/test/foo.txt; +drop procedure p; +drop table t; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log From 14f42e12a42e5c5e787b101b2c4600e44ac90cab Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 13 Jan 2025 16:29:11 +0400 Subject: [PATCH 012/118] MDEV-35596 Assertion `type_handler()->result_type() == value.type_handler()->result_type()' failed in virtual bool Item_param::get_date(THD*, MYSQL_TIME*, date_mode_t) This is a cleanup for MDEV-25593. When binding from NULL, IGNORE or DEFAULT, value.type_handler should be set to &type_handler_null, to satisfy the DBUG_ASSERT in Item_param::get_date(). --- sql/item.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sql/item.cc b/sql/item.cc index dd9a9063e55..44bd4bbfbba 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4168,6 +4168,7 @@ void Item_param::set_null() max_length= 0; decimals= 0; state= NULL_VALUE; + value.set_handler(&type_handler_null); DBUG_VOID_RETURN; } @@ -4981,7 +4982,10 @@ void Item_param::set_default(bool set_type_handler_null) */ null_value= true; if (set_type_handler_null) + { + value.set_handler(&type_handler_null); set_handler(&type_handler_null); + } } void Item_param::set_ignore(bool set_type_handler_null) @@ -4990,7 +4994,10 @@ void Item_param::set_ignore(bool set_type_handler_null) state= IGNORE_VALUE; null_value= true; if (set_type_handler_null) + { + value.set_handler(&type_handler_null); set_handler(&type_handler_null); + } } /** From 1327f40f9649f399fec14d1dff0f2bbc55da749a Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 13 Jan 2025 17:51:51 +0400 Subject: [PATCH 013/118] MDEV-35596 Assertion `type_handler()->result_type() == value.type_handler()->result_type()' failed in virtual bool Item_param::get_date(THD*, MYSQL_TIME*, date_mode_t) Adding mtr tests forgotten in the previous commit. --- mysql-test/main/ps_11bugs.result | 35 ++++++++++++++++++++++++++++++++ mysql-test/main/ps_11bugs.test | 34 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/mysql-test/main/ps_11bugs.result b/mysql-test/main/ps_11bugs.result index 87a3487141b..985654eb283 100644 --- a/mysql-test/main/ps_11bugs.result +++ b/mysql-test/main/ps_11bugs.result @@ -245,4 +245,39 @@ NULL DEALLOCATE PREPARE stmt; SET timestamp=DEFAULT; SET time_zone=DEFAULT; +# +# MDEV-35596 Assertion `type_handler()->result_type() == value.type_handler()->result_type()' failed in virtual bool Item_param::get_date(THD*, MYSQL_TIME*, date_mode_t) +# +CREATE TABLE t (c TIMESTAMP); +PREPARE s FROM 'DELETE FROM t WHERE c=?'; +EXECUTE s USING 1; +INSERT INTO t (c) VALUES (now()); +EXECUTE s USING NULL; +DROP TABLE t; +CREATE TABLE t (c TIMESTAMP); +INSERT INTO t (c) VALUES ('2001-01-01 10:20:30'); +PREPARE s FROM 'DELETE FROM t WHERE c=?'; +EXECUTE s USING 1; +Warnings: +Warning 1292 Truncated incorrect datetime value: '1' +EXECUTE s USING NULL; +DROP TABLE t; +CREATE TABLE t (c TIMESTAMP); +INSERT INTO t (c) VALUES ('2001-01-01 10:20:30'); +PREPARE s FROM 'DELETE FROM t WHERE c=?'; +EXECUTE s USING 1; +Warnings: +Warning 1292 Truncated incorrect datetime value: '1' +EXECUTE s USING DEFAULT; +ERROR HY000: Default/ignore value is not supported for such parameter usage +DROP TABLE t; +CREATE TABLE t (c TIMESTAMP); +INSERT INTO t (c) VALUES ('2001-01-01 10:20:30'); +PREPARE s FROM 'DELETE FROM t WHERE c=?'; +EXECUTE s USING 1; +Warnings: +Warning 1292 Truncated incorrect datetime value: '1' +EXECUTE s USING IGNORE; +ERROR HY000: Default/ignore value is not supported for such parameter usage +DROP TABLE t; # End of 10.5 tests diff --git a/mysql-test/main/ps_11bugs.test b/mysql-test/main/ps_11bugs.test index 7a0843e9352..7cb5708d062 100644 --- a/mysql-test/main/ps_11bugs.test +++ b/mysql-test/main/ps_11bugs.test @@ -254,4 +254,38 @@ DEALLOCATE PREPARE stmt; SET timestamp=DEFAULT; SET time_zone=DEFAULT; +--echo # +--echo # MDEV-35596 Assertion `type_handler()->result_type() == value.type_handler()->result_type()' failed in virtual bool Item_param::get_date(THD*, MYSQL_TIME*, date_mode_t) +--echo # + +CREATE TABLE t (c TIMESTAMP); +PREPARE s FROM 'DELETE FROM t WHERE c=?'; +EXECUTE s USING 1; +INSERT INTO t (c) VALUES (now()); +EXECUTE s USING NULL; +DROP TABLE t; + +CREATE TABLE t (c TIMESTAMP); +INSERT INTO t (c) VALUES ('2001-01-01 10:20:30'); +PREPARE s FROM 'DELETE FROM t WHERE c=?'; +EXECUTE s USING 1; +EXECUTE s USING NULL; +DROP TABLE t; + +CREATE TABLE t (c TIMESTAMP); +INSERT INTO t (c) VALUES ('2001-01-01 10:20:30'); +PREPARE s FROM 'DELETE FROM t WHERE c=?'; +EXECUTE s USING 1; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE s USING DEFAULT; +DROP TABLE t; + +CREATE TABLE t (c TIMESTAMP); +INSERT INTO t (c) VALUES ('2001-01-01 10:20:30'); +PREPARE s FROM 'DELETE FROM t WHERE c=?'; +EXECUTE s USING 1; +--error ER_INVALID_DEFAULT_PARAM +EXECUTE s USING IGNORE; +DROP TABLE t; + --echo # End of 10.5 tests From fe2f2377688cdf4862baff753f04f390aec17793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 13 Jan 2025 17:43:58 +0200 Subject: [PATCH 014/118] MDEV-35808 Test case to handle undo tablespace truncation in Mariabackup This is the test case from commit 46aaf328ce424aededdb61e59a48db05630563d5 (MDEV-35830) to cover backup_undo_trunc() in the regression tests of earlier major versions of mariadb-backup. --- .../mariabackup/undo_truncate.combinations | 4 ++ .../suite/mariabackup/undo_truncate.opt | 6 ++ .../suite/mariabackup/undo_truncate.result | 39 ++++++++++++ .../suite/mariabackup/undo_truncate.test | 59 +++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 mysql-test/suite/mariabackup/undo_truncate.combinations create mode 100644 mysql-test/suite/mariabackup/undo_truncate.opt create mode 100644 mysql-test/suite/mariabackup/undo_truncate.result create mode 100644 mysql-test/suite/mariabackup/undo_truncate.test diff --git a/mysql-test/suite/mariabackup/undo_truncate.combinations b/mysql-test/suite/mariabackup/undo_truncate.combinations new file mode 100644 index 00000000000..fe6a3ba58fd --- /dev/null +++ b/mysql-test/suite/mariabackup/undo_truncate.combinations @@ -0,0 +1,4 @@ +[clear] +--innodb-encrypt-log=OFF +[crypt] +--innodb-encrypt-log=ON diff --git a/mysql-test/suite/mariabackup/undo_truncate.opt b/mysql-test/suite/mariabackup/undo_truncate.opt new file mode 100644 index 00000000000..9b4f76ab5de --- /dev/null +++ b/mysql-test/suite/mariabackup/undo_truncate.opt @@ -0,0 +1,6 @@ +--innodb-undo-tablespaces=2 +--plugin-load-add=$FILE_KEY_MANAGEMENT_SO +--loose-file-key-management +--loose-file-key-management-filekey=FILE:$MTR_SUITE_DIR/filekeys-data.key +--loose-file-key-management-filename=$MTR_SUITE_DIR/filekeys-data.enc +--loose-file-key-management-encryption-algorithm=aes_cbc diff --git a/mysql-test/suite/mariabackup/undo_truncate.result b/mysql-test/suite/mariabackup/undo_truncate.result new file mode 100644 index 00000000000..a3bfb182dd8 --- /dev/null +++ b/mysql-test/suite/mariabackup/undo_truncate.result @@ -0,0 +1,39 @@ +SET GLOBAL innodb_undo_log_truncate = 0; +create table t1 (keyc int primary key default 0, c char(6)) engine=innodb; +create table t2 (keyc int primary key default 0, c char(6)) engine=innodb; +CREATE PROCEDURE p(t VARCHAR(64)) +BEGIN +DECLARE i TEXT DEFAULT 'insert into t1 select seq,repeat(chr(48),6) + from seq_1_to_20000'; +DECLARE u1 TEXT DEFAULT 'update t1 set c=repeat(chr(32),6)'; +DECLARE u2 TEXT DEFAULT 'update t1 set c=repeat(chr(64),6)'; +EXECUTE IMMEDIATE REPLACE(i,'t1', t); +EXECUTE IMMEDIATE REPLACE(u1,'t1', t); +EXECUTE IMMEDIATE REPLACE(u2,'t1', t); +END; +$$ +connect con1,localhost,root,,; +begin; +call p('t1'); +connection default; +call p('t2'); +connection con1; +commit; +disconnect con1; +connection default; +DROP PROCEDURE p; +SET GLOBAL innodb_undo_log_truncate = 1; +SET GLOBAL innodb_max_undo_log_size=DEFAULT; +SET GLOBAL innodb_max_purge_lag_wait=0; +# Prepare full backup +# shutdown server +# remove datadir +# xtrabackup move back +# restart +select count(*) from t1; +count(*) +20000 +select count(*) from t2; +count(*) +20000 +DROP TABLE t1,t2; diff --git a/mysql-test/suite/mariabackup/undo_truncate.test b/mysql-test/suite/mariabackup/undo_truncate.test new file mode 100644 index 00000000000..a23c9cf64ff --- /dev/null +++ b/mysql-test/suite/mariabackup/undo_truncate.test @@ -0,0 +1,59 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +--source include/have_sequence.inc +--source include/have_file_key_management.inc + +SET GLOBAL innodb_undo_log_truncate = 0; + +# +# Perform DML action using multiple clients and multiple undo tablespace. +# + +create table t1 (keyc int primary key default 0, c char(6)) engine=innodb; +create table t2 (keyc int primary key default 0, c char(6)) engine=innodb; + +DELIMITER $$; +CREATE PROCEDURE p(t VARCHAR(64)) +BEGIN + DECLARE i TEXT DEFAULT 'insert into t1 select seq,repeat(chr(48),6) + from seq_1_to_20000'; + DECLARE u1 TEXT DEFAULT 'update t1 set c=repeat(chr(32),6)'; + DECLARE u2 TEXT DEFAULT 'update t1 set c=repeat(chr(64),6)'; + EXECUTE IMMEDIATE REPLACE(i,'t1', t); + EXECUTE IMMEDIATE REPLACE(u1,'t1', t); + EXECUTE IMMEDIATE REPLACE(u2,'t1', t); +END; +$$ +DELIMITER ;$$ + +connect (con1,localhost,root,,); +begin; +send call p('t1'); + +connection default; +call p('t2'); + +connection con1; +reap; +commit; +disconnect con1; +connection default; +DROP PROCEDURE p; + +SET GLOBAL innodb_undo_log_truncate = 1; +SET GLOBAL innodb_max_undo_log_size=DEFAULT; +SET GLOBAL innodb_max_purge_lag_wait=0; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; + +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --throttle=1000; +--echo # Prepare full backup +exec $XTRABACKUP --prepare --target-dir=$targetdir; +--enable_result_log + +source include/restart_and_restore.inc; +select count(*) from t1; +select count(*) from t2; +# Cleanup +rmdir $targetdir; +DROP TABLE t1,t2; From 133e26fd7dc454c5b154495ab876c76bbcfd1715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 11 Dec 2024 09:34:18 +0200 Subject: [PATCH 015/118] MDEV-34924 : gtid_slave_pos table neven been deleted on non replica nodes (wsrep_gtid_mode = 1) Problem was caused by MDEV-31413 commit 277968aa where mysql.gtid_slave_pos table was replicated by Galera. However, as not all nodes in Galera cluster are replica nodes, rows were not deleted from table. In this fix this is corrected so that mysql.gtid_slave_pos table is not replicated by Galera. Instead when Galera node receives GTID event and wsrep_gtid_mode=1, this event is stored to mysql.gtid_slave_pos table. Added test case galera_2primary_replica for 2 async primaries replicating to galera cluster. Added test case galera_circular_replication where async primary replicates to galera cluster and one of the galera cluster nodes is master to async replica. Modified test case galera_restart_replica to monitor gtid positions and rows in mysql.gtid_pos_table. --- .../galera_2nodes_as_replica_2primary.cnf | 70 ++++++ .../galera/r/galera_2primary_replica.result | 95 +++++++ .../r/galera_circular_replication.result | 138 +++++++++++ .../galera/r/galera_restart_replica.result | 191 ++++++++------ .../galera/t/galera_2primary_replica.cnf | 22 ++ .../galera/t/galera_2primary_replica.test | 170 +++++++++++++ .../galera/t/galera_circular_replication.cnf | 25 ++ .../galera/t/galera_circular_replication.test | 234 ++++++++++++++++++ .../galera/t/galera_restart_replica.test | 197 ++++++++++----- sql/rpl_gtid.cc | 50 +--- sql/wsrep_applier.cc | 5 + sql/wsrep_schema.cc | 80 +++++- sql/wsrep_schema.h | 14 +- 13 files changed, 1110 insertions(+), 181 deletions(-) create mode 100644 mysql-test/suite/galera/galera_2nodes_as_replica_2primary.cnf create mode 100644 mysql-test/suite/galera/r/galera_2primary_replica.result create mode 100644 mysql-test/suite/galera/r/galera_circular_replication.result create mode 100644 mysql-test/suite/galera/t/galera_2primary_replica.cnf create mode 100644 mysql-test/suite/galera/t/galera_2primary_replica.test create mode 100644 mysql-test/suite/galera/t/galera_circular_replication.cnf create mode 100644 mysql-test/suite/galera/t/galera_circular_replication.test diff --git a/mysql-test/suite/galera/galera_2nodes_as_replica_2primary.cnf b/mysql-test/suite/galera/galera_2nodes_as_replica_2primary.cnf new file mode 100644 index 00000000000..714caf6ee67 --- /dev/null +++ b/mysql-test/suite/galera/galera_2nodes_as_replica_2primary.cnf @@ -0,0 +1,70 @@ +# +# This .cnf file creates a setup with 2 standard MariaDB servers, followed by a 2-node Galera cluster +# + +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld] +loose-innodb +log-bin=mysqld-bin +log-slave-updates +binlog-format=row +innodb-autoinc-lock-mode=2 +default-storage-engine=innodb +# enforce read-committed characteristics across the cluster +# wsrep-causal-reads=ON +wsrep-sync-wait=15 + +[mysqld.1] +wsrep-on=1 +server-id=1 +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +wsrep_provider=@ENV.WSREP_PROVIDER +wsrep_cluster_address=gcomm:// +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' +wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port' +wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port +wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' + +[mysqld.2] +wsrep-on=1 +server-id=2 +#galera_port=@OPT.port +#ist_port=@OPT.port +#sst_port=@OPT.port +wsrep_provider=@ENV.WSREP_PROVIDER +wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M' +wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' +wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port +wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' + +[mysqld.3] +wsrep-on=OFF +server-id=3 +gtid_domain_id=3 + +[mysqld.4] +wsrep-on=OFF +server-id=4 +gtid_domain_id=4 + + +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + +[ENV] +NODE_MYPORT_1= @mysqld.1.port +NODE_MYSOCK_1= @mysqld.1.socket + +NODE_MYPORT_2= @mysqld.2.port +NODE_MYSOCK_2= @mysqld.2.socket + +NODE_MYPORT_3= @mysqld.3.port +NODE_MYSOCK_3= @mysqld.3.socket + +NODE_MYPORT_4= @mysqld.4.port +NODE_MYSOCK_4= @mysqld.4.socket diff --git a/mysql-test/suite/galera/r/galera_2primary_replica.result b/mysql-test/suite/galera/r/galera_2primary_replica.result new file mode 100644 index 00000000000..8bdbf5be962 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_2primary_replica.result @@ -0,0 +1,95 @@ +connection node_2; +connection node_1; +connect primary1, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connect primary2, 127.0.0.1, root, , test, $NODE_MYPORT_4; +connection primary1; +# Primary1 creating user for replication +create user repl@'%' identified by 'repl'; +grant all on *.* to repl@'%'; +connection primary2; +# Primary2 creating user for replication +create user repl2@'%' identified by 'repl2'; +grant all on *.* to repl2@'%'; +connect replica, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection replica; +connection node_2; +connection replica; +# Galera replica changing master to primary1 +SET @@default_master_connection='stream2'; +# Primary node changing master to primary2 +START ALL SLAVES; +Warnings: +Note 1937 SLAVE 'stream1' started +Note 1937 SLAVE 'stream2' started +connection primary1; +# Primary 1: Creating table and populating it with data +CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +connection primary2; +# Primary 2: Creating table and populating it with data +CREATE TABLE t2 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +EXPECT_1000 +1000 +connection replica; +# Waiting for data to replicate to node_1 +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +EXPECT_1000 +1000 +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +3-3-1003,4-4-1003 3-3-1003,4-4-1003 3-3-1003,4-4-1003 +connection node_2; +# Waiting for data to replicate to node_2 +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +EXPECT_1000 +1000 +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +3-3-1003,4-4-1003 3-3-1003,4-4-1003 3-3-1003,4-4-1003 +connection primary1; +drop table t1; +connection primary2; +drop table t2; +# Wait until drop table is replicated on Galera +connection replica; +connection node_2; +connection replica; +STOP ALL SLAVES; +Warnings: +Note 1938 SLAVE 'stream1' stopped +Note 1938 SLAVE 'stream2' stopped +RESET SLAVE ALL; +connection primary1; +RESET MASTER; +connection primary2; +RESET MASTER; +connection node_1; +disconnect primary1; +disconnect primary2; +disconnect replica; +disconnect node_2; +disconnect node_1; +# End of test diff --git a/mysql-test/suite/galera/r/galera_circular_replication.result b/mysql-test/suite/galera/r/galera_circular_replication.result new file mode 100644 index 00000000000..72340977005 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_circular_replication.result @@ -0,0 +1,138 @@ +connection node_2; +connection node_1; +connect replica1, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect primary2, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connect primary1, 127.0.0.1, root, , test, $NODE_MYPORT_4; +connect replica2, 127.0.0.1, root, , test, $NODE_MYPORT_4; +connection primary1; +# Primary1 node creating user for replication +create user repl@'%' identified by 'repl'; +grant all on *.* to repl@'%'; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +connection replica1; +connection node_2; +connection primary2; +connection replica1; +# Galera replica changing master to primary1 +START SLAVE; +connection primary2; +# Primary2 creating user for replication +create user repl2@'%' identified by 'repl2'; +grant all on *.* to repl2@'%'; +connection replica2; +# replica2 changing master to primary2 +START SLAVE; +connection primary1; +# Primary1: Creating table and populating it with data +CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +connection replica1; +# Waiting for data to replicate to replica +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +# Writing more data to table +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_2000 FROM t1; +EXPECT_2000 +2000 +connection node_2; +# Waiting for data to replicate to Galera node_2 +SELECT COUNT(*) AS EXPECT_2000 FROM t1; +EXPECT_2000 +2000 +# Writing more data to table +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_3000 FROM t1; +EXPECT_3000 +3000 +connection primary2; +# Waiting for data to replicate to primary2 +SELECT COUNT(*) AS EXPECT_3000 FROM t1; +EXPECT_3000 +3000 +# Writing more data to table +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +EXPECT_4000 +4000 +connection primary1; +# Waiting for data to replicate to primary1 +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +EXPECT_4000 +4000 +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-4-1004,16-15-3002 0-4-1004,16-15-3002 0-4-1004,16-15-3002 +connection replica1; +# Waiting for data to replicate to replica +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +EXPECT_4000 +4000 +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-4-1004,16-15-3002 0-4-1004,16-15-3002 0-4-1004,16-15-3002 +connection node_2; +# Waiting for data to replicate to node_2 +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +EXPECT_4000 +4000 +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-4-1004 0-4-1004,16-15-3002 0-4-1004,16-15-3002 +connection primary2; +# Waiting for data to replicate to node_3 +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +EXPECT_4000 +4000 +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-4-1004 0-4-1004,16-15-3002 0-4-1004,16-15-3002 +connection primary1; +drop table t1; +# Wait until drop table is replicated on Galera +connection replica1; +connection node_2; +connection primary2; +connection replica1; +STOP SLAVE; +RESET SLAVE ALL; +connection replica2; +STOP SLAVE; +RESET SLAVE ALL; +RESET MASTER; +connection node_1; +disconnect primary1; +disconnect replica1; +disconnect primary2; +disconnect replica2; +disconnect node_2; +disconnect node_1; +# End of test diff --git a/mysql-test/suite/galera/r/galera_restart_replica.result b/mysql-test/suite/galera/r/galera_restart_replica.result index 9b7e9fd259f..efc9a83a168 100644 --- a/mysql-test/suite/galera/r/galera_restart_replica.result +++ b/mysql-test/suite/galera/r/galera_restart_replica.result @@ -1,122 +1,169 @@ connection node_2; connection node_1; -connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connect replica, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect primary, 127.0.0.1, root, , test, $NODE_MYPORT_3; create user repl@'%' identified by 'repl'; grant all on *.* to repl@'%'; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; connection node_1; -connection node_2; -connection node_2; +connection replica; +connection replica; START SLAVE; -connection node_3; -CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 -connection node_2; +connection primary; +CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +connection replica; SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; EXPECT_1 1 -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-3-1004 0-3-1004 0-3-1004 +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 connection node_1; SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; EXPECT_1 1 -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 -connection node_2; -# Verify that graceful shutdown succeeds. +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-3-1004 0-3-1004 0-3-1004 +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +connection replica; +# Verify that graceful shutdown succeeds in replica. # Force SST connection node_1; -# Waiting until node_2 is not part of cluster anymore -connection node_2; -# Start node_2 again -ยค Wait until node_2 is back on cluster -connection node_2; +# Waiting until replica is not part of cluster anymore +connection replica; +# Start replica again +# Wait until replica is back on cluster SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; EXPECT_1 1 -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-3-1004 0-3-1004 0-3-1004 +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 connection node_1; SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; EXPECT_1 1 -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 -connection node_3; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 -connection node_3; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-3-1004 0-3-1004 0-3-1004 +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +connection primary; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 drop table t1; -connection node_2; +connection replica; connection node_1; -connection node_3; -CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 -connection node_2; +connection primary; +CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 +connection replica; SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; EXPECT_1 1 -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-3-2006 0-3-2006 0-3-2006 +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +EXPECT_1000 +1000 connection node_1; SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; EXPECT_1 1 -SELECT COUNT(*) AS EXPECT_10000 FROM t1; -EXPECT_10000 -10000 -connection node_2; -# Verify that graceful shutdown succeeds. +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-3-2006 0-3-2006 0-3-2006 +connection replica; +# Verify that graceful shutdown succeeds in replica. # Force SST connection node_1; -# Waiting until node_2 is not part of cluster anymore -connection node_3; -SELECT COUNT(*) AS EXPECT_20000 FROM t1; -EXPECT_20000 -20000 -connection node_2; -# Start node_2 again -ยค Wait until node_2 is back on cluster -connection node_2; +# Waiting until replica is not part of cluster anymore +# Add writes to primary +connection primary; +# Intentionally generate 1k GTID-events +SELECT COUNT(*) AS EXPECT_2000 FROM t1; +EXPECT_2000 +2000 +connection replica; +# Start replica again +# Wait until replica is back on cluster SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; EXPECT_1 1 -SELECT COUNT(*) AS EXPECT_20000 FROM t1; -EXPECT_20000 -20000 +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-3-3006 0-3-3006 0-3-3006 +SELECT COUNT(*) AS EXPECT_2000 FROM t1; +EXPECT_2000 +2000 connection node_1; SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; EXPECT_1 1 -SELECT COUNT(*) AS EXPECT_20000 FROM t1; -EXPECT_20000 -20000 -connection node_3; -SELECT COUNT(*) AS EXPECT_20000 FROM t1; -EXPECT_20000 -20000 -connection node_3; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos +0-3-3006 0-3-3006 0-3-3006 +SELECT COUNT(*) AS EXPECT_2000 FROM t1; +EXPECT_2000 +2000 +connection primary; +SELECT COUNT(*) AS EXPECT_2000 FROM t1; +EXPECT_2000 +2000 drop table t1; -connection node_2; +connection replica; connection node_1; -connection node_2; +connection replica; STOP SLAVE; RESET SLAVE ALL; -connection node_3; +connection primary; RESET MASTER; connection node_1; -disconnect node_3; +disconnect primary; +disconnect replica; disconnect node_2; disconnect node_1; # End of test diff --git a/mysql-test/suite/galera/t/galera_2primary_replica.cnf b/mysql-test/suite/galera/t/galera_2primary_replica.cnf new file mode 100644 index 00000000000..e066866de87 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_2primary_replica.cnf @@ -0,0 +1,22 @@ +!include ../galera_2nodes_as_replica_2primary.cnf + +[mysqld] +wsrep-debug=1 + +[mysqld.1] +server_id=15 +wsrep_gtid_mode=1 +wsrep_gtid_domain_id=16 +gtid_domain_id=11 +gtid_strict_mode=1 +wsrep-slave-threads=4 +slave-parallel-threads=2 + +[mysqld.2] +skip-slave-start=OFF +server_id=15 +wsrep_gtid_mode=1 +wsrep_gtid_domain_id=16 +gtid_domain_id=11 +gtid_strict_mode=1 +wsrep-slave-threads=4 diff --git a/mysql-test/suite/galera/t/galera_2primary_replica.test b/mysql-test/suite/galera/t/galera_2primary_replica.test new file mode 100644 index 00000000000..fb57c6637d0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_2primary_replica.test @@ -0,0 +1,170 @@ +# +# Test two primary nodes async replication to Galera cluster +# +# primary1 primary2 +# #3 #4 +# | | +# | async replication v +# +-------------------+ +----------------+ +# | | +# v v +# galera replica <------galera replication-------->galera node_2 +# #1 #2 +# +# Test outline +# +# - Create user for async replication and table with rows in both primaries +# - Verify that tables and rows are replicated to all Galera nodes +# - Verify that gtid position is same in all Galera nodes +# +# The galera/galera_2nodes_as_replica_2primary.cnf describes the setup of the nodes +# +--source include/force_restart.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# As node #3 and #4 are not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the connections here +--connect primary1, 127.0.0.1, root, , test, $NODE_MYPORT_3 +--connect primary2, 127.0.0.1, root, , test, $NODE_MYPORT_4 +--connection primary1 +--echo # Primary1 creating user for replication +create user repl@'%' identified by 'repl'; +grant all on *.* to repl@'%'; + +--connection primary2 +--echo # Primary2 creating user for replication +create user repl2@'%' identified by 'repl2'; +grant all on *.* to repl2@'%'; + +--connect replica, 127.0.0.1, root, , test, $NODE_MYPORT_1 + +--let $node_1 = replica +--let $node_2 = node_2 +--source include/auto_increment_offset_save.inc + +--connection replica +--echo # Galera replica changing master to primary1 +--disable_query_log +SET @@default_master_connection='stream1'; +--eval CHANGE MASTER 'stream1' TO master_host='127.0.0.1', master_user='repl', master_password='repl', master_port=$NODE_MYPORT_3, master_use_gtid=slave_pos; +--enable_query_log + +SET @@default_master_connection='stream2'; +--echo # Primary node changing master to primary2 +--disable_query_log +--eval CHANGE MASTER 'stream2' TO master_host='127.0.0.1', master_user='repl2', master_password='repl2', master_port=$NODE_MYPORT_4, master_use_gtid=slave_pos; +--enable_query_log + +START ALL SLAVES; + +--connection primary1 +--echo # Primary 1: Creating table and populating it with data +CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +--disable_query_log +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 +--disable_query_log +while($count < $inserts) +{ + --eval insert into t1 values (NULL,'test1') + --inc $count +} +--enable_query_log + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; + +--connection primary2 +--echo # Primary 2: Creating table and populating it with data +CREATE TABLE t2 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 +--disable_query_log +while($count < $inserts) +{ + --eval insert into t2 values (NULL,'test1') + --inc $count +} +--enable_query_log + +SELECT COUNT(*) AS EXPECT_1000 FROM t2; + +--connection replica +--echo # Waiting for data to replicate to node_1 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--let $wait_condition_on_error_output = SHOW ALL SLAVES STATUS; +--source include/wait_condition_with_debug.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +--let $wait_condition_on_error_output = SHOW ALL SLAVES STATUS; +--source include/wait_condition_with_debug.inc + +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t2; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +SELECT COUNT(*) AS EXPECT_1000 FROM t2; + +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; + +--connection node_2 +--echo # Waiting for data to replicate to node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t2; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; +SELECT COUNT(*) AS EXPECT_1000 FROM t2; +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +# +# Cleanup +# +--connection primary1 +drop table t1; +--connection primary2 +drop table t2; + +--echo # Wait until drop table is replicated on Galera +--connection replica +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +--source include/wait_condition.inc + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2'; +--source include/wait_condition.inc + +--connection replica +STOP ALL SLAVES; +RESET SLAVE ALL; + +--connection primary1 +RESET MASTER; +--connection primary2 +RESET MASTER; + +--source include/auto_increment_offset_restore.inc + +--connection node_1 +--disconnect primary1 +--disconnect primary2 +--disconnect replica + +--source include/galera_end.inc +--echo # End of test diff --git a/mysql-test/suite/galera/t/galera_circular_replication.cnf b/mysql-test/suite/galera/t/galera_circular_replication.cnf new file mode 100644 index 00000000000..b1c6320d4df --- /dev/null +++ b/mysql-test/suite/galera/t/galera_circular_replication.cnf @@ -0,0 +1,25 @@ +!include ../galera_3nodes_as_slave.cnf + +[mysqld] +wsrep-debug=1 + +[mysqld.1] +server_id=15 +wsrep_gtid_mode=1 +wsrep_gtid_domain_id=16 +gtid_domain_id=11 +gtid_strict_mode=1 + +[mysqld.2] +server_id=15 +wsrep_gtid_mode=1 +wsrep_gtid_domain_id=16 +gtid_domain_id=11 +gtid_strict_mode=1 + +[mysqld.3] +server_id=15 +wsrep_gtid_mode=1 +wsrep_gtid_domain_id=16 +gtid_domain_id=11 +gtid_strict_mode=1 diff --git a/mysql-test/suite/galera/t/galera_circular_replication.test b/mysql-test/suite/galera/t/galera_circular_replication.test new file mode 100644 index 00000000000..dbe85da4b23 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_circular_replication.test @@ -0,0 +1,234 @@ +# +# Test circular replication where galera cluster is async replica and master +# +# mariadb #4 galera galera +# primary1 +# replica2 +# ---async replication-->replica1 #1 <--galera replication--> node_2 #2 +# ^ ^ +# | | galera replication +# | v +# +<------------------async replication----------------------primary2 (galera) #3 +# +# Test outline: +# +# - Create user for async replication in primary1 +# - Create user for async replication in primary2 +# - Create table and some data in primary1 +# - Verify that table and data is replicated to galera nodes +# - Verify that mysql.gtid_slave_pos has some rows in all Galera nodes +# - Verify that gtid_slave_pos, gtid_binlog_pos and gtid_current_pos are +# same in all Galera nodes and primary1 +# - Verify that writes on Galera nodes are replicated to all nodes +# and to primary1 +# +# The galera/galera_3nodes_as_slave.cnf describes the setup of the nodes +# +--source include/force_restart.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connect replica1, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connect primary2, 127.0.0.1, root, , test, $NODE_MYPORT_3 + +# As node #4 is not a Galera node, and galera_cluster.inc does not open connetion to it +# because it is both primary and replica we open both connections here +--connect primary1, 127.0.0.1, root, , test, $NODE_MYPORT_4 +--connect replica2, 127.0.0.1, root, , test, $NODE_MYPORT_4 + +--connection primary1 +--echo # Primary1 node creating user for replication +create user repl@'%' identified by 'repl'; +grant all on *.* to repl@'%'; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; + +--let $node_1 = replica1 +--let $node_2 = node_2 +--let $node_3 = primary2 +--source include/auto_increment_offset_save.inc + +--connection replica1 +--echo # Galera replica changing master to primary1 +--disable_query_log +--eval CHANGE MASTER TO master_host='127.0.0.1', master_user='repl', master_password='repl', master_port=$NODE_MYPORT_4, master_use_gtid=slave_pos; +--enable_query_log +START SLAVE; + +--connection primary2 +--echo # Primary2 creating user for replication +create user repl2@'%' identified by 'repl2'; +grant all on *.* to repl2@'%'; + +--connection replica2 +--echo # replica2 changing master to primary2 +--disable_query_log +--eval CHANGE MASTER TO master_host='127.0.0.1', master_user='repl2', master_password='repl2', master_port=$NODE_MYPORT_3, master_use_gtid=slave_pos; +--enable_query_log +START SLAVE; + +--connection primary1 +--echo # Primary1: Creating table and populating it with data +CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 +--disable_query_log +while($count < $inserts) +{ + --eval insert into t1 values (NULL,'test1') + --inc $count +} +--enable_query_log + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; + +--connection replica1 +--echo # Waiting for data to replicate to replica +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_1000 FROM t1; + +--echo # Writing more data to table +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 +--disable_query_log +while($count < $inserts) +{ + --eval insert into t1 values (NULL,'test1') + --inc $count +} +--enable_query_log + +SELECT COUNT(*) AS EXPECT_2000 FROM t1; + +--connection node_2 +--echo # Waiting for data to replicate to Galera node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 2000 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_2000 FROM t1; + +--echo # Writing more data to table +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 +--disable_query_log +while($count < $inserts) +{ + --eval insert into t1 values (NULL,'test1') + --inc $count +} +--enable_query_log + +SELECT COUNT(*) AS EXPECT_3000 FROM t1; + +--connection primary2 +--echo # Waiting for data to replicate to primary2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 3000 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_3000 FROM t1; + +--echo # Writing more data to table +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 +--disable_query_log +while($count < $inserts) +{ + --eval insert into t1 values (NULL,'test1') + --inc $count +} +--enable_query_log + +SELECT COUNT(*) AS EXPECT_4000 FROM t1; + +--connection primary1 +--echo # Waiting for data to replicate to primary1 +--let $wait_condition = SELECT COUNT(*) = 4000 FROM t1; +--let $wait_condition_on_error_output = SHOW SLAVE STATUS; +--source include/wait_condition_with_debug.inc + +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; + +--connection replica1 +--echo # Waiting for data to replicate to replica +--let $wait_condition = SELECT COUNT(*) = 4000 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; + +--connection node_2 +--echo # Waiting for data to replicate to node_2 +--let $wait_condition = SELECT COUNT(*) = 4000 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; + +--connection primary2 +--echo # Waiting for data to replicate to node_3 +--let $wait_condition = SELECT COUNT(*) = 4000 FROM t1; +--source include/wait_condition.inc + +SELECT COUNT(*) AS EXPECT_4000 FROM t1; +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +# +# Cleanup +# +--connection primary1 +drop table t1; + +--echo # Wait until drop table is replicated on Galera +--connection replica1 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection primary2 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection replica1 +STOP SLAVE; +RESET SLAVE ALL; + +--connection replica2 +STOP SLAVE; +RESET SLAVE ALL; +RESET MASTER; + +--source include/auto_increment_offset_restore.inc + +--connection node_1 +--disconnect primary1 +--disconnect replica1 +--disconnect primary2 +--disconnect replica2 + +--source include/galera_end.inc +--echo # End of test diff --git a/mysql-test/suite/galera/t/galera_restart_replica.test b/mysql-test/suite/galera/t/galera_restart_replica.test index 37cfd9bc0f9..05ab77f2519 100644 --- a/mysql-test/suite/galera/t/galera_restart_replica.test +++ b/mysql-test/suite/galera/t/galera_restart_replica.test @@ -1,77 +1,115 @@ # -# Test Galera as a replica to a MySQL async replication +# Test Galera as a replica to a MariaDB async replication +# +# MariaDB +# primary ---async replication--->galera node_2 (replica)<----galera replication---> galera node1 +# +# Test outline: +# +# - Create user for async replication +# - Create table and some data in primary +# - Verify that table and data is replicated to galera nodes +# - Verify that mysql.gtid_slave_pos has some rows in all Galera nodes +# - Verify that gtid_slave_pos, gtid_binlog_pos and gtid_current_pos are +# same in all Galera nodes +# - Verify that we can shutdown and restart Galera replica (node #2) +# - Verify that gtid_slave_pos, gtid_binlog_pos and gtid_current_pos are +# same in all Galera nodes +# - Verify that mysql.gtid_slave_pos table has limited amount of rows +# - Veruft that ddl works (drop table) +# +# Similar test is done so that new rows are added to table in +# primary while async replica (node #2) is down. # # The galera/galera_2node_slave.cnf describes the setup of the nodes # --source include/force_restart.inc --source include/galera_cluster.inc --source include/have_innodb.inc ---source include/have_sequence.inc + +# In this test we mark node #2 as replica +--connect replica, 127.0.0.1, root, , test, $NODE_MYPORT_2 # As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it -# we open the node_3 connection here ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 +# we open the primary connection her +--connect primary, 127.0.0.1, root, , test, $NODE_MYPORT_3 create user repl@'%' identified by 'repl'; grant all on *.* to repl@'%'; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; --let $node_1 = node_1 ---let $node_2 = node_2 +--let $node_2 = replica --source include/auto_increment_offset_save.inc ---connection node_2 +--connection replica --disable_query_log --eval CHANGE MASTER TO master_host='127.0.0.1', master_user='repl', master_password='repl', master_port=$NODE_MYPORT_3, master_use_gtid=slave_pos; --enable_query_log START SLAVE; ---connection node_3 +--connection primary +CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; -CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb; +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 --disable_query_log -INSERT INTO t1 SELECT seq, 'test' from seq_1_to_10000; +while($count < $inserts) +{ + --eval insert into t1 values (NULL,'test1') + --inc $count +} --enable_query_log -SELECT COUNT(*) AS EXPECT_10000 FROM t1; ---connection node_2 +SELECT COUNT(*) AS EXPECT_1000 FROM t1; + +--connection replica --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 10000 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1; --source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; --connection node_1 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 10000 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1; --source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; ---connection node_2 ---echo # Verify that graceful shutdown succeeds. +--connection replica +--echo # Verify that graceful shutdown succeeds in replica. --source include/shutdown_mysqld.inc --echo # Force SST --remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat --connection node_1 ---echo # Waiting until node_2 is not part of cluster anymore +--echo # Waiting until replica is not part of cluster anymore --let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc --let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; --source include/wait_condition.inc ---connection node_2 ---echo # Start node_2 again +--connection replica +--echo # Start replica again --source include/start_mysqld.inc ---echo ยค Wait until node_2 is back on cluster +--echo # Wait until replica is back on cluster --let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; --source include/wait_condition.inc --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; @@ -79,24 +117,30 @@ SELECT COUNT(*) AS EXPECT_10000 FROM t1; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; --source include/wait_condition.inc ---connection node_2 +--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; --connection node_1 +--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; ---connection node_3 -SELECT COUNT(*) AS EXPECT_10000 FROM t1; +--connection primary +SELECT COUNT(*) AS EXPECT_1000 FROM t1; # # Cleanup # ---connection node_3 drop table t1; ---connection node_2 +--connection replica --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc @@ -108,59 +152,80 @@ drop table t1; # Case 2 : While slave is down add writes to master # ---connection node_3 - -CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb; +--connection primary +CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb; +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 --disable_query_log -INSERT INTO t1 SELECT seq, 'test' from seq_1_to_10000; +while($count < $inserts) +{ + --eval insert into t1 values (NULL,'test1') + --inc $count +} --enable_query_log -SELECT COUNT(*) AS EXPECT_10000 FROM t1; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; ---connection node_2 +--connection replica --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 10000 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1; --source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +SELECT COUNT(*) AS EXPECT_1000 FROM t1; --connection node_1 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 10000 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1; --source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos; +--source include/wait_condition.inc SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; -SELECT COUNT(*) AS EXPECT_10000 FROM t1; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; ---connection node_2 ---echo # Verify that graceful shutdown succeeds. +--connection replica +--echo # Verify that graceful shutdown succeeds in replica. --source include/shutdown_mysqld.inc --echo # Force SST --remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat --connection node_1 ---echo # Waiting until node_2 is not part of cluster anymore +--echo # Waiting until replica is not part of cluster anymore --let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc --let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; --source include/wait_condition.inc -# Add writes to master ---connection node_3 +--echo # Add writes to primary +--connection primary +--echo # Intentionally generate 1k GTID-events +--let $inserts=1000 +--let $count=0 --disable_query_log -INSERT INTO t1 SELECT seq, 'test' from seq_20001_to_30000; +while($count < $inserts) +{ + --eval insert into t1 values (NULL,'test1') + --inc $count +} --enable_query_log -SELECT COUNT(*) AS EXPECT_20000 FROM t1; ---connection node_2 ---echo # Start node_2 again +SELECT COUNT(*) AS EXPECT_2000 FROM t1; + +--connection replica +--echo # Start replica again --source include/start_mysqld.inc ---echo ยค Wait until node_2 is back on cluster +--echo # Wait until replica is back on cluster --let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; --source include/wait_condition.inc --let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; @@ -168,28 +233,34 @@ SELECT COUNT(*) AS EXPECT_20000 FROM t1; --let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; --source include/wait_condition.inc ---connection node_2 ---let $wait_condition = SELECT COUNT(*) = 20000 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 2000 FROM t1; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos; --source include/wait_condition.inc SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; -SELECT COUNT(*) AS EXPECT_20000 FROM t1; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +SELECT COUNT(*) AS EXPECT_2000 FROM t1; --connection node_1 ---let $wait_condition = SELECT COUNT(*) = 20000 FROM t1; +--let $wait_condition = SELECT COUNT(*) = 2000 FROM t1; +--source include/wait_condition.inc +--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos; --source include/wait_condition.inc SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; -SELECT COUNT(*) AS EXPECT_20000 FROM t1; +SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos; +SELECT COUNT(*) AS EXPECT_2000 FROM t1; ---connection node_3 -SELECT COUNT(*) AS EXPECT_20000 FROM t1; +--connection primary +SELECT COUNT(*) AS EXPECT_2000 FROM t1; # # Cleanup # ---connection node_3 drop table t1; ---connection node_2 +--connection replica --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc @@ -197,16 +268,18 @@ drop table t1; --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc ---connection node_2 +--connection replica STOP SLAVE; RESET SLAVE ALL; ---connection node_3 +--connection primary RESET MASTER; ---connection node_1 ---disconnect node_3 - --source include/auto_increment_offset_restore.inc + +--connection node_1 +--disconnect primary +--disconnect replica + --source include/galera_end.inc --echo # End of test diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 93a83426d37..8112a5b911d 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -28,10 +28,6 @@ #include "rpl_rli.h" #include "slave.h" #include "log_event.h" -#ifdef WITH_WSREP -#include "wsrep_mysqld.h" // wsrep_thd_is_local -#include "wsrep_trans_observer.h" // wsrep_start_trx_if_not_started -#endif const LEX_CSTRING rpl_gtid_slave_state_table_name= { STRING_WITH_LEN("gtid_slave_pos") }; @@ -696,23 +692,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, goto end; #ifdef WITH_WSREP - /* - We should replicate local gtid_slave_pos updates to other nodes if - wsrep gtid mode is set. - In applier we should not append them to galera writeset. - */ - if (WSREP_ON_ && wsrep_gtid_mode && wsrep_thd_is_local(thd)) - { - thd->wsrep_ignore_table= false; - table->file->row_logging= 1; // replication requires binary logging - if (thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) - thd->set_query_id(next_query_id()); - wsrep_start_trx_if_not_started(thd); - } - else - { - thd->wsrep_ignore_table= true; - } + thd->wsrep_ignore_table= true; // Do not replicate mysql.gtid_slave_pos table #endif if (!in_transaction) @@ -749,10 +729,6 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, } end: -#ifdef WITH_WSREP - thd->wsrep_ignore_table= false; -#endif - if (table_opened) { if (err || (err= ha_commit_trans(thd, FALSE))) @@ -764,6 +740,10 @@ end: else thd->release_transactional_locks(); } + +#ifdef WITH_WSREP + thd->wsrep_ignore_table= false; +#endif thd->lex->restore_backup_query_tables_list(&lex_backup); thd->variables.option_bits= thd_saved_option; thd->resume_subsequent_commits(suspended_wfc); @@ -877,25 +857,7 @@ rpl_slave_state::gtid_delete_pending(THD *thd, return; #ifdef WITH_WSREP - /* - We should replicate local gtid_slave_pos updates to other nodes if - wsrep gtid mode is set. - In applier we should not append them to galera writeset. - */ - if (WSREP_ON_ && wsrep_gtid_mode && - wsrep_thd_is_local(thd) && - thd->wsrep_cs().state() != wsrep::client_state::s_none) - { - if (thd->wsrep_trx().active() == false) - { - if (thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) - thd->set_query_id(next_query_id()); - wsrep_start_transaction(thd, thd->wsrep_next_trx_id()); - } - thd->wsrep_ignore_table= false; - } - else - thd->wsrep_ignore_table= true; + thd->wsrep_ignore_table= true; // No Galera replication for mysql.gtid_pos_table #endif thd_saved_option= thd->variables.option_bits; diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index feb78507bf9..39df306a0e2 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -22,6 +22,7 @@ #include "wsrep_xid.h" #include "wsrep_thd.h" #include "wsrep_trans_observer.h" +#include "wsrep_schema.h" // wsrep_schema #include "slave.h" // opt_log_slave_updates #include "debug_sync.h" @@ -180,6 +181,10 @@ int wsrep_apply_events(THD* thd, { thd->variables.gtid_seq_no= gtid_ev->seq_no; } + + if (wsrep_gtid_mode) + wsrep_schema->store_gtid_event(thd, gtid_ev); + delete ev; } continue; diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc index 08e516b2a7a..f29442abac1 100644 --- a/sql/wsrep_schema.cc +++ b/sql/wsrep_schema.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2023 Codership Oy +/* Copyright (C) 2015-2025 Codership Oy 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 @@ -31,6 +31,8 @@ #include "wsrep_storage_service.h" #include "wsrep_thd.h" #include "wsrep_server_state.h" +#include "log_event.h" +#include "sql_class.h" #include #include @@ -165,6 +167,24 @@ private: my_bool m_wsrep_on; }; +class wsrep_ignore_table +{ +public: + wsrep_ignore_table(THD* thd) + : m_thd(thd) + , m_wsrep_ignore_table(thd->wsrep_ignore_table) + { + thd->wsrep_ignore_table= true; + } + ~wsrep_ignore_table() + { + m_thd->wsrep_ignore_table= m_wsrep_ignore_table; + } +private: + THD* m_thd; + my_bool m_wsrep_ignore_table; +}; + class thd_server_status { public: @@ -1535,3 +1555,61 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) out: DBUG_RETURN(ret); } + +int Wsrep_schema::store_gtid_event(THD* thd, + const Gtid_log_event *gtid) +{ + DBUG_ENTER("Wsrep_schema::store_gtid_event"); + int error=0; + void *hton= NULL; + const bool in_transaction= (gtid->flags2 & Gtid_log_event::FL_TRANSACTIONAL); + const bool in_ddl= (gtid->flags2 & Gtid_log_event::FL_DDL); + + DBUG_PRINT("info", ("thd: %p, in_transaction: %d, in_ddl: %d " + "in_active_multi_stmt_transaction: %d", + thd, in_transaction, in_ddl, + thd->in_active_multi_stmt_transaction())); + + Wsrep_schema_impl::wsrep_ignore_table ignore_table(thd); + Wsrep_schema_impl::binlog_off binlog_off(thd); + Wsrep_schema_impl::sql_safe_updates sql_safe_updates(thd); + + rpl_group_info *rgi= thd->wsrep_rgi; + const uint64 sub_id= rpl_global_gtid_slave_state->next_sub_id(gtid->domain_id); + rpl_gtid current_gtid; + current_gtid.domain_id= gtid->domain_id; + current_gtid.server_id= gtid->server_id; + current_gtid.seq_no= gtid->seq_no; + rgi->gtid_pending= false; + + DBUG_ASSERT(!in_transaction || thd->in_active_multi_stmt_transaction()); + + if ((error= rpl_global_gtid_slave_state->record_gtid(thd, ¤t_gtid, + sub_id, + in_transaction, false, &hton))) + goto out; + + rpl_global_gtid_slave_state->update_state_hash(sub_id, ¤t_gtid, hton, rgi); + + if (in_ddl) + { + // Commit transaction if this GTID is part of DDL-clause because + // DDL causes implicit commit assuming there is no multi statement + // transaction ongoing. + if((error= trans_commit_stmt(thd))) + goto out; + + (void)trans_commit(thd); + } + +out: + if (error) + { + WSREP_DEBUG("Wsrep_schema::store_gtid_event %llu-%llu-%llu failed error=%s (%d).", + gtid->domain_id, gtid->server_id, gtid->seq_no, strerror(error), error); + (void)trans_rollback_stmt(thd); + (void)trans_rollback(thd); + } + + DBUG_RETURN(error); +} diff --git a/sql/wsrep_schema.h b/sql/wsrep_schema.h index f0f79046768..46acba2961b 100644 --- a/sql/wsrep_schema.h +++ b/sql/wsrep_schema.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2023 Codership Oy +/* Copyright (C) 2015-2024 Codership Oy 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 @@ -22,7 +22,6 @@ #include "mysqld.h" #include "wsrep_mysqld.h" - /* Forward decls */ @@ -32,6 +31,7 @@ struct TABLE; struct TABLE_LIST; struct st_mysql_lex_string; typedef struct st_mysql_lex_string LEX_STRING; +class Gtid_log_event; /** Name of the table in `wsrep_schema_str` used for storing streaming replication data. In an InnoDB full format, e.g. "database/tablename". */ @@ -133,6 +133,16 @@ class Wsrep_schema */ int recover_sr_transactions(THD* orig_thd); + /** + Store GTID-event to mysql.gtid_slave_pos table. + + @param thd The THD object of the calling thread. + @param gtid GTID event from binlog. + + @return Zero on success, non-zero on failure. + */ + int store_gtid_event(THD* thd, const Gtid_log_event *gtid); + private: /* Non-copyable */ Wsrep_schema(const Wsrep_schema&); From d8c841d0d4fcd7a37e1e135052838d8fba565c92 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Mon, 13 Jan 2025 07:04:53 -0700 Subject: [PATCH 016/118] MDEV-35096: History is stored in different partitions on different nodes when using SYSTEM VERSION MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Row-injection updates donโ€™t correctly set the historical partition for tables with system versioning and system_time partitions. This results in inconsistencies between the master and slave when replicating transactions that target such tables (i.e. the primary server would correctly distribute archived rows amongst its partitions, whereas the replica would have all archived rows in a single partition). The function partition_info::vers_set_hist_part(THD*) is used to set the partition; however, its initial check for vers_require_hist_part(THD*) returns false, bypassing the rest of the function (which sets up the partition to use). This is because the actual check uses the LEX sql_command (via LEX::vers_history_generating()) to determine if the command is valid to generate history. Row injections donโ€™t have sql_commands though. This patch provides a fix which extends the check in vers_history_generating() to additionally allow row injections to be history generating (via the function LEX::is_stmt_row_injection()). Special thanks to Jan Lindstrom for his work in reproducing the bug, and providing an initial test case. Reviewed By ============ Kristian Nielsen Aleksey Midenkov --- .../r/rpl_system_versioning_partitions.result | 71 +++++ .../t/rpl_system_versioning_partitions.cnf | 4 + .../t/rpl_system_versioning_partitions.test | 248 ++++++++++++++++++ sql/sql_lex.h | 6 +- 4 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/rpl/r/rpl_system_versioning_partitions.result create mode 100644 mysql-test/suite/rpl/t/rpl_system_versioning_partitions.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_system_versioning_partitions.test diff --git a/mysql-test/suite/rpl/r/rpl_system_versioning_partitions.result b/mysql-test/suite/rpl/r/rpl_system_versioning_partitions.result new file mode 100644 index 00000000000..8edc6996a05 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_system_versioning_partitions.result @@ -0,0 +1,71 @@ +include/master-slave.inc +[connection master] +# +# Initialize system-versioned and partitioned table and its data +connection master; +SET timestamp=UNIX_TIMESTAMP('2025-01-01 01:00:00.000000'); +RESET MASTER; +create table t1 (x int) engine=InnoDB with system versioning partition by system_time limit 3 partitions 5; +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); +insert into t1 values(5); +# Verifying master partitions are correct after data insertion.. +# .. done +connection slave; +connection slave; +# Verifying partitions of master and slave match on data setup.. +# .. done +# +# "Delete" each row -- these are the BINLOG commands generated by +# mysqlbinlog from `delete from t1 where x=` statments. Because the +# table uses system versioning and system_time partition, the actual +# events are updates, with added fields for the `row_start` and `row_end` +# columns. +connection master; +# BINLOG for Format Description event +BINLOG ' +APZ0Zw8BAAAA/AAAAAABAAAAAAQAMTAuNi4yMS1NYXJpYURCLWRlYnVnLWxvZwAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAA9nRnEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA +CgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAEEwQADQgICAoKCgHgiCNP +'; +# BINLOG for delete from t1 where x=1; +BINLOG ' +APZ0ZxMBAAAAMQAAAAQHAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBvaHPfA== +APZ0ZxgBAAAASAAAAEwHAAAAACEAAAAAAAEAAwcH+AEAAABndPYAAAAAf////w9CP/gBAAAAZ3T2 +AAAAAGd09gAAAADnhA23 +'; +# BINLOG for delete from t1 where x=2; +BINLOG ' +APZ0ZxMBAAAAMQAAAPUHAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBwNtQNQ== +APZ0ZxgBAAAASAAAAD0IAAAAACEAAAAAAAEAAwcH+AIAAABndPYAAAAAf////w9CP/gCAAAAZ3T2 +AAAAAGd09gAAAABPYZUX +'; +# BINLOG for delete from t1 where x=3; +BINLOG ' +APZ0ZxMBAAAAMQAAAOYIAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBKWGevg== +APZ0ZxgBAAAASAAAAC4JAAAAACEAAAAAAAEAAwcH+AMAAABndPYAAAAAf////w9CP/gDAAAAZ3T2 +AAAAAGd09gAAAAD0hz5S +'; +# BINLOG for delete from t1 where x=4; +BINLOG ' +APZ0ZxMBAAAAMQAAANcJAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBaT9IZg== +APZ0ZxgBAAAASAAAAB8KAAAAACEAAAAAAAEAAwcH+AQAAABndPYAAAAAf////w9CP/gEAAAAZ3T2 +AAAAAGd09gAAAADA4Tdx +'; +# BINLOG for delete from t1 where x=5; +BINLOG ' +APZ0ZxMBAAAAMQAAAMgKAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBMk64Mw== +APZ0ZxgBAAAASAAAABALAAAAACEAAAAAAAEAAwcH+AUAAABndPYAAAAAf////w9CP/gFAAAAZ3T2 +AAAAAGd09gAAAAA5blY6 +'; +# Verifying master partitions are correct after deletion BINLOG stmts.. +# .. done +connection slave; +connection slave; +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_system_versioning_partitions.cnf b/mysql-test/suite/rpl/t/rpl_system_versioning_partitions.cnf new file mode 100644 index 00000000000..53153614f0a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_system_versioning_partitions.cnf @@ -0,0 +1,4 @@ +!include ../my.cnf + +[mysqld] +default_time_zone="-7:00" diff --git a/mysql-test/suite/rpl/t/rpl_system_versioning_partitions.test b/mysql-test/suite/rpl/t/rpl_system_versioning_partitions.test new file mode 100644 index 00000000000..70103acf862 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_system_versioning_partitions.test @@ -0,0 +1,248 @@ +# +# Ensure that executing row-injected events (i.e. via BINLOG statments and +# row-based binlog events) uses historical partitions. That is, for tables +# which use system versioning and system_time partitions, MDEV-35096 reported +# that row-injected events would not be stored into the correct historical +# partition. This test considers both use cases of row-injected events. +# +# The test setup creates a system-versioned table with system_time-based +# partitioning and fills the table up with enough records that bypass the size +# limit of each historical partition. +# +# To test BINLOG statements, a series of BINLOG statements are used to delete +# all the records in the test tables, and the resulting partitions are analyzed +# to ensure that they match the partition specification. The BINLOG events +# were collected by running an original set of delete statements on the table +# data, and taking their binlog data from mysqlbinlog. Note these binary log +# events are actually Update events, because system versioning just archives +# the rows, rather than deleting them. +# +# To test row-based event replication, a slave replicates the master's +# events, and the partitions are compared between the slave and master for +# consistency. +# +# Note that the TIMESTAMP of this test is fixed so the BINLOG statements can +# identify the correct rows to delete (system versioning adds implicit fields +# `row_start` and `row_end`, which are automatically populated using the current +# timestamp). +# +# +# References: +# MDEV-35096: History is stored in different partitions on different nodes +# when using SYSTEM VERSION +# +--source include/have_binlog_format_row.inc +--source include/master-slave.inc +--source include/have_innodb.inc +--source include/have_partition.inc + +--echo # +--echo # Initialize system-versioned and partitioned table and its data +--connection master + +# Fix the timestamp for the system versioned row_start and row_end fields, so +# the later hard-coded BINLOG base64 data can find the rows. +SET timestamp=UNIX_TIMESTAMP('2025-01-01 01:00:00.000000'); +RESET MASTER; + +create table t1 (x int) engine=InnoDB with system versioning partition by system_time limit 3 partitions 5; +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); +insert into t1 values(5); +--let $master_total_size= `select count(*) from t1` +--let $master_p0_size= `select count(*) from t1 partition (p0)` +--let $master_p1_size= `select count(*) from t1 partition (p1)` +--let $master_p2_size= `select count(*) from t1 partition (p2)` + +--echo # Verifying master partitions are correct after data insertion.. +if ($master_total_size != 5) +{ + --echo # Master t1 count: $master_total_size + --die Master table t1 should have 5 entries +} +if ($master_p0_size) +{ + --echo # Master t1,p0 count: $master_p0_size + --die Master t1 partition p0 should be empty +} +if ($master_p1_size) +{ + --echo # Master t1,p1 count: $master_p1_size + --die Master t1 partition p1 should be empty +} +if ($master_p2_size) +{ + --echo # Master t1,p2 count: $master_p2_size + --die Master t1 partition p2 should be empty +} +--echo # .. done + +--sync_slave_with_master + +--connection slave +--let $slave_total_size= `select count(*) from t1` +--let $slave_p0_size= `select count(*) from t1 partition (p0)` +--let $slave_p1_size= `select count(*) from t1 partition (p1)` +--let $slave_p2_size= `select count(*) from t1 partition (p2)` + +--echo # Verifying partitions of master and slave match on data setup.. +if ($slave_total_size != $master_total_size) +{ + --connection master + select count(*) from t0; + --connection slave + select count(*) from t1; + --die Size of t1 differs between master and slave +} +if ($slave_p0_size != $master_p0_size) +{ + --connection master + select count(*) from t1 partition (p0); + --connection slave + select count(*) from t1 partition (p0); + --die Size of t1 partition p0 differs between master and slave +} +if ($slave_p1_size != $master_p1_size) +{ + --connection master + select count(*) from t1 partition (p1); + --connection slave + select count(*) from t1 partition (p1); + --die Size of t1 partition p1 differs between master and slave +} +if ($slave_p2_size != $master_p2_size) +{ + --connection master + select count(*) from t1 partition (p2); + --connection slave + select count(*) from t1 partition (p2); + --die Size of t1 partition p2 differs between master and slave +} +--echo # .. done + +--echo # +--echo # "Delete" each row -- these are the BINLOG commands generated by +--echo # mysqlbinlog from `delete from t1 where x=` statments. Because the +--echo # table uses system versioning and system_time partition, the actual +--echo # events are updates, with added fields for the `row_start` and `row_end` +--echo # columns. +--connection master + +--echo # BINLOG for Format Description event +BINLOG ' +APZ0Zw8BAAAA/AAAAAABAAAAAAQAMTAuNi4yMS1NYXJpYURCLWRlYnVnLWxvZwAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAA9nRnEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA +CgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAEEwQADQgICAoKCgHgiCNP +'; + +--echo # BINLOG for delete from t1 where x=1; +BINLOG ' +APZ0ZxMBAAAAMQAAAAQHAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBvaHPfA== +APZ0ZxgBAAAASAAAAEwHAAAAACEAAAAAAAEAAwcH+AEAAABndPYAAAAAf////w9CP/gBAAAAZ3T2 +AAAAAGd09gAAAADnhA23 +'; + +--echo # BINLOG for delete from t1 where x=2; +BINLOG ' +APZ0ZxMBAAAAMQAAAPUHAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBwNtQNQ== +APZ0ZxgBAAAASAAAAD0IAAAAACEAAAAAAAEAAwcH+AIAAABndPYAAAAAf////w9CP/gCAAAAZ3T2 +AAAAAGd09gAAAABPYZUX +'; + + +--echo # BINLOG for delete from t1 where x=3; +BINLOG ' +APZ0ZxMBAAAAMQAAAOYIAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBKWGevg== +APZ0ZxgBAAAASAAAAC4JAAAAACEAAAAAAAEAAwcH+AMAAABndPYAAAAAf////w9CP/gDAAAAZ3T2 +AAAAAGd09gAAAAD0hz5S +'; + +--echo # BINLOG for delete from t1 where x=4; +BINLOG ' +APZ0ZxMBAAAAMQAAANcJAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBaT9IZg== +APZ0ZxgBAAAASAAAAB8KAAAAACEAAAAAAAEAAwcH+AQAAABndPYAAAAAf////w9CP/gEAAAAZ3T2 +AAAAAGd09gAAAADA4Tdx +'; + +--echo # BINLOG for delete from t1 where x=5; +BINLOG ' +APZ0ZxMBAAAAMQAAAMgKAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBMk64Mw== +APZ0ZxgBAAAASAAAABALAAAAACEAAAAAAAEAAwcH+AUAAABndPYAAAAAf////w9CP/gFAAAAZ3T2 +AAAAAGd09gAAAAA5blY6 +'; + +--let $master_total_size= `select count(*) from t1` +--let $master_p0_size= `select count(*) from t1 partition (p0)` +--let $master_p1_size= `select count(*) from t1 partition (p1)` +--let $master_p2_size= `select count(*) from t1 partition (p2)` +--echo # Verifying master partitions are correct after deletion BINLOG stmts.. +if ($master_total_size > 0) +{ + --echo # Master t1 count: $master_total_size + --die Master table t1 should have 0 count +} +if ($master_p0_size != 3) +{ + --echo # Master t1,p0 count: $master_p0_size + --die Master t1 partition p0 should have 3 entries +} +if ($master_p1_size != 2) +{ + --echo # Master t1,p1 count: $master_p1_size + --die Master t1 partition p1 should have 2 entries +} +if ($master_p2_size) +{ + --echo # Master t1,p2 count: $master_p2_size + --die Master t1 partition p2 should be empty +} +--echo # .. done +--sync_slave_with_master + +--connection slave +--let $slave_total_size= `select count(*) from t1` +--let $slave_p0_size= `select count(*) from t1 partition (p0)` +--let $slave_p1_size= `select count(*) from t1 partition (p1)` +--let $slave_p2_size= `select count(*) from t1 partition (p2)` + +if ($slave_total_size != $master_total_size) +{ + --connection master + select count(*) from t1; + --connection slave + select count(*) from t1; + --die Size of t1 differs between master and slave +} +if ($slave_p0_size != $master_p0_size) +{ + --connection master + select count(*) from t1 partition (p0); + --connection slave + select count(*) from t1 partition (p0); + --die Size of t1 partition p0 differs between master and slave +} +if ($slave_p1_size != $master_p1_size) +{ + --connection master + select count(*) from t1 partition (p1); + --connection slave + select count(*) from t1 partition (p1); + --die Size of t1 partition p1 differs between master and slave +} +if ($slave_p2_size != $master_p2_size) +{ + --connection master + select count(*) from t1 partition (p2); + --connection slave + select count(*) from t1 partition (p2); + --die Size of t1 partition p2 differs between master and slave +} + +--connection master +drop table t1; + +--source include/rpl_end.inc diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 1dbd839ac53..f1c3e041c7a 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -4617,7 +4617,11 @@ public: case SQLCOM_LOAD: return duplicates == DUP_REPLACE; default: - return false; + /* + Row injections (i.e. row binlog events and BINLOG statements) should + generate history. + */ + return is_stmt_row_injection(); } } From 4b0ac5a12b95afbb47a7c41b33b3e8785c9f21a4 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 14 Jan 2025 10:48:59 +1100 Subject: [PATCH 017/118] MDEV-35838 libressl support differences in CRYPTO_set_mem_functions Based on FreeBSD patch. The FreeBSD inclusion of check_openssl_compatibility prevented any use of the crypto callbacks and as such the later differences where ignored. The later differences in coc_malloc didn't propegate to the other callback functions of CRYPTO_set_mem_functions where a reduced argument list also applied. Looking where[2] libressl added the functions it was of the same prototype 10 years ago so omitting any version check. [1] https://github.com/freebsd/freebsd-ports/blob/a34cf9c2dbf503c8248371ba3bab24f34d2d045d/databases/mariadb106-server/files/patch-mysys__ssl_openssl.c [2] https://github.com/libressl/openbsd/commit/5ebad8aceae77c6da6a1e47c3f7e70e8ffae3dae#diff-7f393e5489e6c5780773408f11ca27d9b3bb8f55b174631a1e9467a1dd3010b9R22 --- mysys_ssl/openssl.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/mysys_ssl/openssl.c b/mysys_ssl/openssl.c index e0271817309..3890e3524be 100644 --- a/mysys_ssl/openssl.c +++ b/mysys_ssl/openssl.c @@ -36,8 +36,12 @@ int check_openssl_compatibility() static uint testing; static size_t alloc_size, alloc_count; -static void *coc_malloc(size_t size, const char *f __attribute__((unused)), - int l __attribute__((unused))) +static void *coc_malloc(size_t size +#ifndef LIBRESSL_VERSION_NUMBER + , const char *f __attribute__((unused)), + int l __attribute__((unused)) +#endif +) { if (unlikely(testing)) { @@ -47,15 +51,22 @@ static void *coc_malloc(size_t size, const char *f __attribute__((unused)), return malloc(size); } -static void *coc_realloc(void *addr, size_t num, - const char *file __attribute__((unused)), - int line __attribute__((unused))) +static void *coc_realloc(void *addr, size_t num +#ifndef LIBRESSL_VERSION_NUMBER + , const char *file __attribute__((unused)), + int line __attribute__((unused)) +#endif +) { return realloc(addr, num); } -static void coc_free(void *addr, const char *file __attribute__((unused)), - int line __attribute__((unused))) +static void coc_free(void *addr +#ifndef LIBRESSL_VERSION_NUMBER + , const char *file __attribute__((unused)), + int line __attribute__((unused)) +#endif +) { free(addr); } From 901c6c7ab63f9c9473b90d3f62be656321bcf871 Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Mon, 25 Dec 2023 13:59:07 +0300 Subject: [PATCH 018/118] MDEV-33064: Sync trx->wsrep state from THD on trx start InnoDB transactions may be reused after committed: - when taken from the transaction pool - during a DDL operation execution In this case wsrep flag on trx object is cleared, which may cause wrong execution logic afterwards (wsrep-related hooks are not run). Make trx->wsrep flag initialize from THD object only once on InnoDB transaction start and don't change it throughout the transaction's lifetime. The flag is reset at commit time as before. Unconditionally set wsrep=OFF for THD objects that represent InnoDB background threads. Make Wsrep_schema::store_view() operate in its own transaction. Fix streaming replication transactions' fragments rollback to not switch THD->wsrep value during transaction's execution (use THD->wsrep_ignore_table as a workaround). Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-33064.result | 26 ++++++++++ mysql-test/suite/galera/t/MDEV-33064.test | 57 +++++++++++++++++++++ sql/handler.cc | 4 +- sql/sql_class.cc | 6 ++- sql/wsrep_schema.cc | 23 ++++++++- sql/wsrep_server_service.cc | 24 +-------- storage/innobase/handler/ha_innodb.cc | 11 ++-- storage/innobase/trx/trx0trx.cc | 3 ++ 8 files changed, 122 insertions(+), 32 deletions(-) create mode 100644 mysql-test/suite/galera/r/MDEV-33064.result create mode 100644 mysql-test/suite/galera/t/MDEV-33064.test diff --git a/mysql-test/suite/galera/r/MDEV-33064.result b/mysql-test/suite/galera/r/MDEV-33064.result new file mode 100644 index 00000000000..22e1ce7a77a --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-33064.result @@ -0,0 +1,26 @@ +connection node_2; +connection node_1; +connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1; +CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t1_fk(c1 INT PRIMARY KEY, c2 INT, INDEX (c2), FOREIGN KEY (c2) REFERENCES t1(c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +connection con1; +SET SESSION wsrep_retry_autocommit = 0; +SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL may_alter WAIT_FOR bf_abort'; +INSERT INTO t1_fk VALUES (1, 1); +connection node_1; +SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; +SET DEBUG_SYNC = 'lock_wait_end WAIT_FOR alter_continue'; +ALTER TABLE t1 ADD COLUMN c2 INT, ALGORITHM=INPLACE; +connection con1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET DEBUG_SYNC = 'now SIGNAL alter_continue'; +connection node_1; +connection node_2; +INSERT INTO t1 (c1, c2) VALUES (2, 2); +connection node_1; +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1_fk, t1; +disconnect con1; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/t/MDEV-33064.test b/mysql-test/suite/galera/t/MDEV-33064.test new file mode 100644 index 00000000000..704ed70ab56 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-33064.test @@ -0,0 +1,57 @@ +# +# MDEV-33064: ALTER INPLACE running TOI should abort a conflicting DML operation +# +# DDL operations may commit InnoDB transactions more than once during the execution. +# In this case wsrep flag on trx object is cleared, which may cause wrong logic of +# such operations afterwards (wsrep-related hooks are not run). +# One of the consequences was that DDL operation couldn't abort a DML operation +# holding conflicting locks. +# +# The fix: re-enable wsrep flag on trx restart if it's a part of a DDL operation. +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connect con1,127.0.0.1,root,,test,$NODE_MYPORT_1 + +CREATE TABLE t1(c1 INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t1_fk(c1 INT PRIMARY KEY, c2 INT, INDEX (c2), FOREIGN KEY (c2) REFERENCES t1(c1)) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1); + +--connection con1 +SET SESSION wsrep_retry_autocommit = 0; +SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL may_alter WAIT_FOR bf_abort'; +# INSERT also grabs FK-referenced table lock. +--send + INSERT INTO t1_fk VALUES (1, 1); + +--connection node_1 +SET DEBUG_SYNC = 'now WAIT_FOR may_alter'; +SET DEBUG_SYNC = 'lock_wait_end WAIT_FOR alter_continue'; +# ALTER BF-aborts INSERT. +--send + ALTER TABLE t1 ADD COLUMN c2 INT, ALGORITHM=INPLACE; + +--connection con1 +# INSERT gets BF-aborted. +--error ER_LOCK_DEADLOCK +--reap +SET DEBUG_SYNC = 'now SIGNAL alter_continue'; + +--connection node_1 +# ALTER succeeds. +--reap + +--connection node_2 +# Sanity check that ALTER has been replicated. +INSERT INTO t1 (c1, c2) VALUES (2, 2); + +# Cleanup. +--connection node_1 +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1_fk, t1; +--disconnect con1 +--source include/galera_end.inc diff --git a/sql/handler.cc b/sql/handler.cc index 4ecd1ea2048..38453b5e2a7 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7500,7 +7500,9 @@ int handler::ha_delete_row(const uchar *buf) } #ifdef WITH_WSREP THD *thd= ha_thd(); - if (WSREP_NNULL(thd)) + /* For streaming replication, when removing fragments, don't call + wsrep_after_row() as that would initiate new streaming transaction */ + if (WSREP_NNULL(thd) && !thd->wsrep_ignore_table) { /* for streaming replication, the following wsrep_after_row() may replicate a fragment, so we have to declare potential PA diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8cb5b4954aa..66f689c5312 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5083,6 +5083,9 @@ MYSQL_THD create_background_thd() thd->real_id= 0; thd->thread_id= 0; thd->query_id= 0; +#ifdef WITH_WSREP + thd->variables.wsrep_on= FALSE; +#endif /* WITH_WSREP */ return thd; } @@ -6347,7 +6350,8 @@ int THD::decide_logging_format(TABLE_LIST *tables) wsrep_is_active(this) && variables.wsrep_trx_fragment_size > 0) { - if (!is_current_stmt_binlog_format_row()) + if (!is_current_stmt_binlog_disabled() && + !is_current_stmt_binlog_format_row()) { my_message(ER_NOT_SUPPORTED_YET, "Streaming replication not supported with " diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc index f29442abac1..8e271565b13 100644 --- a/sql/wsrep_schema.cc +++ b/sql/wsrep_schema.cc @@ -768,6 +768,12 @@ int Wsrep_schema::store_view(THD* thd, const Wsrep_view& view) Wsrep_schema_impl::binlog_off binlog_off(thd); Wsrep_schema_impl::sql_safe_updates sql_safe_updates(thd); + if (trans_begin(thd, MYSQL_START_TRANS_OPT_READ_WRITE)) + { + WSREP_ERROR("Failed to start transaction for store view"); + goto out_not_started; + } + /* Clean up cluster table and members table. */ @@ -861,7 +867,22 @@ int Wsrep_schema::store_view(THD* thd, const Wsrep_view& view) #endif /* WSREP_SCHEMA_MEMBERS_HISTORY */ ret= 0; out: + if (ret) + { + trans_rollback_stmt(thd); + if (!trans_rollback(thd)) + { + close_thread_tables(thd); + } + } + else if (trans_commit(thd)) + { + ret= 1; + WSREP_ERROR("Failed to commit transaction for store view"); + } + thd->release_transactional_locks(); +out_not_started: DBUG_RETURN(ret); } @@ -1213,7 +1234,7 @@ int Wsrep_schema::remove_fragments(THD* thd, int ret= 0; WSREP_DEBUG("Removing %zu fragments", fragments.size()); - Wsrep_schema_impl::wsrep_off wsrep_off(thd); + Wsrep_schema_impl::wsrep_ignore_table wsrep_ignore_table(thd); Wsrep_schema_impl::binlog_off binlog_off(thd); Wsrep_schema_impl::sql_safe_updates sql_safe_updates(thd); diff --git a/sql/wsrep_server_service.cc b/sql/wsrep_server_service.cc index a2879b59789..b50a3081660 100644 --- a/sql/wsrep_server_service.cc +++ b/sql/wsrep_server_service.cc @@ -241,29 +241,9 @@ void Wsrep_server_service::log_view( view.state_id().seqno().get() >= prev_view.state_id().seqno().get()); } - if (trans_begin(applier->m_thd, MYSQL_START_TRANS_OPT_READ_WRITE)) + if (wsrep_schema->store_view(applier->m_thd, view)) { - WSREP_WARN("Failed to start transaction for store view"); - } - else - { - if (wsrep_schema->store_view(applier->m_thd, view)) - { - WSREP_WARN("Failed to store view"); - trans_rollback_stmt(applier->m_thd); - if (!trans_rollback(applier->m_thd)) - { - close_thread_tables(applier->m_thd); - } - } - else - { - if (trans_commit(applier->m_thd)) - { - WSREP_WARN("Failed to commit transaction for store view"); - } - } - applier->m_thd->release_transactional_locks(); + WSREP_WARN("Failed to store view"); } /* diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c2341aa667a..68e3f6c7b56 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2381,9 +2381,6 @@ innobase_trx_init( trx->check_unique_secondary = !thd_test_options( thd, OPTION_RELAXED_UNIQUE_CHECKS); -#ifdef WITH_WSREP - trx->wsrep = wsrep_on(thd); -#endif DBUG_VOID_RETURN; } @@ -4173,9 +4170,6 @@ innobase_commit_low( trx_commit_for_mysql(trx); } else { trx->will_lock = false; -#ifdef WITH_WSREP - trx->wsrep = false; -#endif /* WITH_WSREP */ } #ifdef WITH_WSREP @@ -8571,7 +8565,10 @@ func_exit: } #ifdef WITH_WSREP - if (error == DB_SUCCESS && trx->is_wsrep() + if (error == DB_SUCCESS && + /* For sequences, InnoDB transaction may not have been started yet. + Check THD-level wsrep state in that case. */ + (trx->is_wsrep() || (!trx_is_started(trx) && wsrep_on(m_user_thd))) && wsrep_thd_is_local(m_user_thd) && !wsrep_thd_ignore_table(m_user_thd) && (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE) diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 284437497b5..38393444932 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -953,6 +953,7 @@ trx_start_low( #ifdef WITH_WSREP trx->xid->null(); + trx->wsrep = wsrep_on(trx->mysql_thd); #endif /* WITH_WSREP */ ut_a(ib_vector_is_empty(trx->autoinc_locks)); @@ -1402,6 +1403,8 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr) trx_finalize_for_fts(this, undo_no != 0); #ifdef WITH_WSREP + ut_ad(is_wsrep() == wsrep_on(mysql_thd)); + /* Serialization history has been written and the transaction is committed in memory, which makes this commit ordered. Release commit order critical section. */ From d1f2ceee1bb1d33e181b5f35b12ed8536a8a0d24 Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Thu, 20 Jun 2024 12:34:55 +0300 Subject: [PATCH 019/118] MDEV-33064: Sync trx->wsrep state from THD on trx start Replace trx->wsrep= 0 with an assert in trx_rollback_for_mysql() Signed-off-by: Julius Goryavsky --- storage/innobase/trx/trx0roll.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index fbe5a7e9b0a..626dd7378f6 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -211,7 +211,7 @@ dberr_t trx_rollback_for_mysql(trx_t* trx) trx->will_lock = false; ut_ad(trx->mysql_thd); #ifdef WITH_WSREP - trx->wsrep= false; + ut_ad(!trx->is_wsrep()); trx->lock.was_chosen_as_wsrep_victim= false; #endif return(DB_SUCCESS); From 6868d965db1e14f2441c3bff05f0156079524c35 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 14 Jan 2025 08:54:14 +1100 Subject: [PATCH 020/118] MDEV-34825 FreeBSD fails to build under clang natively (postfix) The fix in MDEV-34825/#3484/dff354e7df2f originally just took the FreeBSD carried patch of inline ASM as it didn't have the __ppc_get_timebase function. What clang does have is the __builtin_ppc_get_timebase, which was replaced in the same commit, which was the fix taken from Alpine. To reduce complexity - we only need one working function rather than an equivalent asm implementation. Noted by Marko, thanks! --- include/my_cpu.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/my_cpu.h b/include/my_cpu.h index 1f562dc700c..f9b0c5f0c6d 100644 --- a/include/my_cpu.h +++ b/include/my_cpu.h @@ -94,13 +94,8 @@ static inline void MY_RELAX_CPU(void) __asm__ __volatile__ ("pause"); #endif #elif defined(_ARCH_PWR8) -#ifdef __FreeBSD__ - uint64_t __tb; - __asm__ volatile ("mfspr %0, 268" : "=r" (__tb)); -#else - /* Changed from __ppc_get_timebase for musl compatibility */ + /* Changed from __ppc_get_timebase for musl and clang compatibility */ __builtin_ppc_get_timebase(); -#endif #elif defined __GNUC__ && (defined __arm__ || defined __aarch64__) /* Mainly, prevent the compiler from optimizing away delay loops */ #ifdef _aarch64_ From 200c235244bd06d12fc4d01c79830f2e8b2512cf Mon Sep 17 00:00:00 2001 From: ParadoxV5 Date: Thu, 9 Jan 2025 17:54:57 -0700 Subject: [PATCH 021/118] MDEV-35429 my_snprintf fixes for 10.5+ * Innobase `os0file.cc`: use `PRIu64` over `llu` * These came after I prepared #3485. * MyISAM `mi_check.c`: in impossible block length warning * I missed this one in #3485 (and #3360 too?). --- storage/innobase/os/os0file.cc | 6 +++--- storage/myisam/mi_check.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 012f23b3b8d..c6106d47557 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -1641,8 +1641,8 @@ bool os_file_set_size(const char *name, os_file_t file, os_offset_t size, if (is_sparse) { bool success = !ftruncate(file, size); if (!success) { - sql_print_error("InnoDB: ftruncate of file %s" - " to %llu bytes failed with error %d", + sql_print_error("InnoDB: ftruncate of file %s to %" + PRIu64 " bytes failed with error %d", name, size, errno); } return success; @@ -1680,7 +1680,7 @@ bool os_file_set_size(const char *name, os_file_t file, os_offset_t size, case 0: return true; default: - sql_print_error("InnoDB: preallocating %llu" + sql_print_error("InnoDB: preallocating %" PRIu64 " bytes for file %s failed with error %d", size, name, err); /* fall through */ diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index e46dc35f861..dff5fcdbcb6 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -3429,9 +3429,9 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param) { if (!searching) mi_check_print_info(param, - "Found block with impossible length %u at %s; Skipped", - block_info.block_len+ (uint) (block_info.filepos-pos), - llstr(pos,llbuff)); + "Found block with impossible length %lu at %s; Skipped", + block_info.block_len + (unsigned long) (block_info.filepos-pos), + llstr(pos, llbuff)); if (found_record) goto try_next; searching=1; From b337e14440ba4fa79a5b4fd34341e6bce4eecbc7 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:58 +0300 Subject: [PATCH 022/118] WITHOUT_ABI_CHECK ABI check takes several seconds on compilation. It is not needed in repetitive build during the development process. --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 642f7b39b99..2c1e2719e43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -501,7 +501,9 @@ IF(UNIX) ADD_SUBDIRECTORY(man) ENDIF() -INCLUDE(cmake/abi_check.cmake) +IF (NOT WITHOUT_ABI_CHECK) + INCLUDE(cmake/abi_check.cmake) +ENDIF() INCLUDE(cmake/tags.cmake) INCLUDE(for_clients) ADD_SUBDIRECTORY(scripts) From 52dd4895157da932d152d8d762df0989613ffb9d Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Mon, 13 Jan 2025 15:40:58 +0300 Subject: [PATCH 023/118] MDEV-22441 implement a generic way to change a value of a variable in a scope Example: { auto _= make_scope_value(var, tmp_value); } make_scope_value(): a function which returns RAII object which temporary changes a value of a variable detail::Scope_value: actual implementation of such RAII class. It shouldn't be used directly! That's why it's inside a namespace detail. --- include/scope.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ sql/sql_acl.cc | 6 ++++-- sql/sql_show.cc | 4 ++-- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/include/scope.h b/include/scope.h index e0e9fc62969..836c4f77b35 100644 --- a/include/scope.h +++ b/include/scope.h @@ -72,3 +72,48 @@ make_scope_exit(Callable &&f) #define ANONYMOUS_VARIABLE CONCAT(_anonymous_variable, __LINE__) #define SCOPE_EXIT auto ANONYMOUS_VARIABLE= make_scope_exit + +namespace detail +{ + +template class Scope_value +{ +public: + Scope_value(T &variable, const T &scope_value) + : variable_(variable), saved_value_(variable) + { + variable= scope_value; + } + + Scope_value(Scope_value &&rhs) + : variable_(rhs.variable_), saved_value_(rhs.saved_value_), + engaged_(rhs.engaged_) + { + rhs.engaged_= false; + } + + Scope_value(const Scope_value &)= delete; + Scope_value &operator=(const Scope_value &)= delete; + Scope_value &operator=(Scope_value &&)= delete; + + ~Scope_value() + { + if (engaged_) + variable_= saved_value_; + } + +private: + T &variable_; + T saved_value_; + bool engaged_= true; +}; + +} // namespace detail + +// Use like this: +// auto _= make_scope_value(var, tmp_value); +template +detail::Scope_value make_scope_value(T &variable, const T &scope_value) +{ + return detail::Scope_value(variable, scope_value); +} diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 59980264741..98e79babcc3 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -54,6 +54,7 @@ #include "sql_array.h" #include "sql_hset.h" #include "password.h" +#include "scope.h" #include "sql_plugin_compat.h" #include "wsrep_mysqld.h" @@ -2552,10 +2553,11 @@ static bool acl_load(THD *thd, const Grant_tables& tables) { READ_RECORD read_record_info; char tmp_name[SAFE_NAME_LEN+1]; - Sql_mode_save old_mode_save(thd); DBUG_ENTER("acl_load"); - thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH; + auto _= make_scope_value(thd->variables.sql_mode, + thd->variables.sql_mode & + ~MODE_PAD_CHAR_TO_FULL_LENGTH); grant_version++; /* Privileges updated */ diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2965cdf0199..ee3d85e6ba2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -65,6 +65,7 @@ #include "transaction.h" #include "opt_trace.h" #include "my_cpu.h" +#include "scope.h" #include "lex_symbol.h" @@ -6437,8 +6438,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, { Field *field; LEX_CSTRING tmp_string; - Sql_mode_save sql_mode_backup(thd); - thd->variables.sql_mode= sql_mode; + auto _= make_scope_value(thd->variables.sql_mode, sql_mode); if (sph->type() == SP_TYPE_FUNCTION) { From d8adc5286373f366c74c56a53cbb4258e9b315d3 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:58 +0300 Subject: [PATCH 024/118] MDEV-22441 SCOPE_VALUE macro for temporary values - Needless engaged_ removed; - SCOPE_VALUE, SCOPE_SET, SCOPE_CLEAR macros for neater declaration; - IF_CLASS / IF_NOT_CLASS SFINAE checkers to pass arg by value or reference; - inline keyword; - couple of refactorings of temporary free_list. --- include/scope.h | 83 ++++++++++++++++++++++++++++++++++++---------- sql/sql_acl.cc | 4 +-- sql/sql_prepare.cc | 21 +++++------- sql/sql_show.cc | 2 +- 4 files changed, 76 insertions(+), 34 deletions(-) diff --git a/include/scope.h b/include/scope.h index 836c4f77b35..932ab410d78 100644 --- a/include/scope.h +++ b/include/scope.h @@ -32,6 +32,11 @@ public: { } + template + scope_exit(F &&f, bool engaged) : function_(std::forward(f)), engaged_(engaged) + { + } + scope_exit(scope_exit &&rhs) : function_(std::move(rhs.function_)), engaged_(rhs.engaged_) { @@ -43,6 +48,7 @@ public: scope_exit &operator=(const scope_exit &)= delete; void release() { engaged_= false; } + void engage() { DBUG_ASSERT(!engaged_); engaged_= true; } ~scope_exit() { @@ -58,38 +64,51 @@ private: } // end namespace detail template -detail::scope_exit::type> -make_scope_exit(Callable &&f) +inline +::detail::scope_exit::type> +make_scope_exit(Callable &&f, bool engaged= true) { - return detail::scope_exit::type>( - std::forward(f)); + return ::detail::scope_exit::type>( + std::forward(f), engaged); } #define CONCAT_IMPL(x, y) x##y - #define CONCAT(x, y) CONCAT_IMPL(x, y) - #define ANONYMOUS_VARIABLE CONCAT(_anonymous_variable, __LINE__) #define SCOPE_EXIT auto ANONYMOUS_VARIABLE= make_scope_exit +#define IF_CLASS(C) typename std::enable_if::value>::type +#define IF_NOT_CLASS(C) typename std::enable_if::value>::type + namespace detail { -template class Scope_value +template +class Scope_value { public: + // Use SFINAE for passing structs by reference and plain types by value. + // This ctor is defined only if T is a class or struct: + template Scope_value(T &variable, const T &scope_value) - : variable_(variable), saved_value_(variable) + : variable_(&variable), saved_value_(variable) + { + variable= scope_value; + } + + // This ctor is defined only if T is NOT a class or struct: + template + Scope_value(T &variable, const T scope_value) + : variable_(&variable), saved_value_(variable) { variable= scope_value; } Scope_value(Scope_value &&rhs) - : variable_(rhs.variable_), saved_value_(rhs.saved_value_), - engaged_(rhs.engaged_) + : variable_(rhs.variable_), saved_value_(rhs.saved_value_) { - rhs.engaged_= false; + rhs.variable_= NULL; } Scope_value(const Scope_value &)= delete; @@ -98,22 +117,50 @@ public: ~Scope_value() { - if (engaged_) - variable_= saved_value_; + if (variable_) + *variable_= saved_value_; } private: - T &variable_; + T *variable_; T saved_value_; - bool engaged_= true; }; } // namespace detail // Use like this: // auto _= make_scope_value(var, tmp_value); -template -detail::Scope_value make_scope_value(T &variable, const T &scope_value) + +template +inline +::detail::Scope_value make_scope_value(T &variable, const T &scope_value) { - return detail::Scope_value(variable, scope_value); + return ::detail::Scope_value(variable, scope_value); } + +template +inline +::detail::Scope_value make_scope_value(T &variable, T scope_value) +{ + return ::detail::Scope_value(variable, scope_value); +} + +/* + Note: perfect forwarding version can not pass const: + + template + inline + detail::Scope_value make_scope_value(T &variable, U &&scope_value) + { + return detail::Scope_value(variable, std::forward(scope_value)); + } + + as `const U &&` fails with error `expects an rvalue for 2nd argument`. That + happens because const U && is treated as rvalue only (this is the exact syntax + for declaring rvalues). +*/ + + +#define SCOPE_VALUE auto ANONYMOUS_VARIABLE= make_scope_value +#define SCOPE_SET(VAR, MASK) auto ANONYMOUS_VARIABLE= make_scope_value(VAR, VAR | MASK) +#define SCOPE_CLEAR(VAR, MASK) auto ANONYMOUS_VARIABLE= make_scope_value(VAR, VAR & ~MASK) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 98e79babcc3..c7f2a8d3d46 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2555,9 +2555,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) char tmp_name[SAFE_NAME_LEN+1]; DBUG_ENTER("acl_load"); - auto _= make_scope_value(thd->variables.sql_mode, - thd->variables.sql_mode & - ~MODE_PAD_CHAR_TO_FULL_LENGTH); + SCOPE_CLEAR(thd->variables.sql_mode, MODE_PAD_CHAR_TO_FULL_LENGTH); grant_version++; /* Privileges updated */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9d53d7cf543..c102e2f734e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2993,8 +2993,8 @@ void mysql_sql_stmt_execute_immediate(THD *thd) DBUG_VOID_RETURN; // out of memory // See comments on thd->free_list in mysql_sql_stmt_execute() - Item *free_list_backup= thd->free_list; - thd->free_list= NULL; + SCOPE_VALUE(thd->free_list, (Item *) NULL); + SCOPE_EXIT([thd]() mutable { thd->free_items(); }); /* Make sure we call Prepared_statement::execute_immediate() with an empty THD::change_list. It can be non empty as the above @@ -3017,8 +3017,6 @@ void mysql_sql_stmt_execute_immediate(THD *thd) Item_change_list_savepoint change_list_savepoint(thd); (void) stmt->execute_immediate(query.str, (uint) query.length); change_list_savepoint.rollback(thd); - thd->free_items(); - thd->free_list= free_list_backup; /* stmt->execute_immediately() sets thd->query_string with the executed @@ -3578,8 +3576,13 @@ void mysql_sql_stmt_execute(THD *thd) so they don't get freed in case of re-prepare. See MDEV-10702 Crash in SET STATEMENT FOR EXECUTE */ - Item *free_list_backup= thd->free_list; - thd->free_list= NULL; // Hide the external (e.g. "SET STATEMENT") Items + /* + Hide and restore at scope exit the "external" (e.g. "SET STATEMENT") Item list. + It will be freed normaly in THD::cleanup_after_query(). + */ + SCOPE_VALUE(thd->free_list, (Item *) NULL); + // Free items created by execute_loop() at scope exit + SCOPE_EXIT([thd]() mutable { thd->free_items(); }); /* Make sure we call Prepared_statement::execute_loop() with an empty THD::change_list. It can be non-empty because the above @@ -3603,12 +3606,6 @@ void mysql_sql_stmt_execute(THD *thd) (void) stmt->execute_loop(&expanded_query, FALSE, NULL, NULL); change_list_savepoint.rollback(thd); - thd->free_items(); // Free items created by execute_loop() - /* - Now restore the "external" (e.g. "SET STATEMENT") Item list. - It will be freed normaly in THD::cleanup_after_query(). - */ - thd->free_list= free_list_backup; stmt->lex->restore_set_statement_var(); DBUG_VOID_RETURN; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ee3d85e6ba2..dff2a9c73da 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -6438,7 +6438,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, { Field *field; LEX_CSTRING tmp_string; - auto _= make_scope_value(thd->variables.sql_mode, sql_mode); + SCOPE_VALUE(thd->variables.sql_mode, sql_mode); if (sph->type() == SP_TYPE_FUNCTION) { From 92383f8db17b0a3eb95b63c6aee4220017fe63da Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:58 +0300 Subject: [PATCH 025/118] MDEV-26891 Segfault in Field::register_field_in_read_map upon INSERT DELAYED with virtual columns Segfault was cause by two different copies of same Field instance in prepared delayed insert. One was made by Delayed_insert::get_local_table() (see make_new_field()). That copy went through parse_vcol_defs() and received new vcol_info->expr. Another one was made by copy_keys_from_share() by this code: /* We are using only a prefix of the column as a key: Create a new field for the key part that matches the index */ field= key_part->field=field->make_new_field(root, outparam, 0); field->field_length= key_part->length; So, key_part and table got different objects of same field and the crash was because key_part->field->vcol_info->expr is NULL. The fix does update_keypart_vcol_info() to update vcol_info->expr in key_part->field. Cleanup: memdup_vcol() is static inline instead of macro + check OOM. --- mysql-test/suite/vcol/r/vcol_misc.result | 14 ++++++++++ mysql-test/suite/vcol/t/vcol_misc.test | 19 ++++++++++++++ sql/sql_insert.cc | 30 +++++++++++++++------ sql/table.cc | 33 ++++++++++++++---------- sql/table.h | 1 + 5 files changed, 75 insertions(+), 22 deletions(-) diff --git a/mysql-test/suite/vcol/r/vcol_misc.result b/mysql-test/suite/vcol/r/vcol_misc.result index 64c56e81815..2900cd4b4f4 100644 --- a/mysql-test/suite/vcol/r/vcol_misc.result +++ b/mysql-test/suite/vcol/r/vcol_misc.result @@ -577,3 +577,17 @@ drop table t; # # End of 10.4 tests # +# +# MDEV-26891 Segfault in Field::register_field_in_read_map upon INSERT DELAYED with virtual columns +# +CREATE TABLE t ( +id INT AUTO_INCREMENT, +a varchar(16) NOT NULL DEFAULT '', +b varchar(16) GENERATED ALWAYS AS (a) VIRTUAL, +KEY `col_year` (b(8),id) +) ENGINE=MyISAM; +INSERT DELAYED INTO t (a) VALUES ('foo'),('bar'); +DROP TABLE t; +# +# End of 10.5 tests +# diff --git a/mysql-test/suite/vcol/t/vcol_misc.test b/mysql-test/suite/vcol/t/vcol_misc.test index 83a06e83f6f..2709ff5b465 100644 --- a/mysql-test/suite/vcol/t/vcol_misc.test +++ b/mysql-test/suite/vcol/t/vcol_misc.test @@ -541,3 +541,22 @@ drop table t; --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # MDEV-26891 Segfault in Field::register_field_in_read_map upon INSERT DELAYED with virtual columns +--echo # +CREATE TABLE t ( + id INT AUTO_INCREMENT, + a varchar(16) NOT NULL DEFAULT '', + b varchar(16) GENERATED ALWAYS AS (a) VIRTUAL, + KEY `col_year` (b(8),id) +) ENGINE=MyISAM; + +INSERT DELAYED INTO t (a) VALUES ('foo'),('bar'); + +# Cleanup +DROP TABLE t; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 000695c5399..50a1a37e3ea 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2674,12 +2674,21 @@ end_create: DBUG_RETURN(thd->is_error()); } -#define memdup_vcol(thd, vcol) \ - if (vcol) \ - { \ - (vcol)= (Virtual_column_info*)(thd)->memdup((vcol), sizeof(*(vcol))); \ - (vcol)->expr= NULL; \ +static inline +bool memdup_vcol(THD *thd, Virtual_column_info *&vcol) +{ + if (vcol) + { + vcol= (Virtual_column_info*)(thd->memdup(vcol, sizeof(*vcol))); + if (!vcol) + { + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + return true; + } + vcol->expr= NULL; } + return false; +} /** As we can't let many client threads modify the same TABLE @@ -2820,9 +2829,12 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) (*field)->move_field_offset(adjust_ptrs); // Point at copy->record[0] (*field)->flags|= ((*org_field)->flags & LONG_UNIQUE_HASH_FIELD); (*field)->invisible= (*org_field)->invisible; - memdup_vcol(client_thd, (*field)->vcol_info); - memdup_vcol(client_thd, (*field)->default_value); - memdup_vcol(client_thd, (*field)->check_constraint); + if (memdup_vcol(client_thd, (*field)->vcol_info)) + goto error; + if (memdup_vcol(client_thd, (*field)->default_value)) + goto error; + if (memdup_vcol(client_thd, (*field)->check_constraint)) + goto error; if (*org_field == found_next_number_field) (*field)->table->found_next_number_field= *field; } @@ -2839,6 +2851,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) &error_reported, VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING))) goto error; + + copy->update_keypart_vcol_info(); } switch_defaults_to_nullable_trigger_fields(copy); diff --git a/sql/table.cc b/sql/table.cc index aaec593df76..11564e85af0 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3952,6 +3952,24 @@ bool copy_keys_from_share(TABLE *outparam, MEM_ROOT *root) return 0; } +void TABLE::update_keypart_vcol_info() +{ + for (uint k= 0; k < s->keys; k++) + { + KEY &info_k= key_info[k]; + uint parts = (s->use_ext_keys ? info_k.ext_key_parts : + info_k.user_defined_key_parts); + for (uint p= 0; p < parts; p++) + { + KEY_PART_INFO &kp= info_k.key_part[p]; + if (kp.field != field[kp.fieldnr - 1]) + { + kp.field->vcol_info = field[kp.fieldnr - 1]->vcol_info; + } + } + } +} + /* Open a table based on a TABLE_SHARE @@ -4184,20 +4202,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, /* Update to use trigger fields */ switch_defaults_to_nullable_trigger_fields(outparam); - for (uint k= 0; k < share->keys; k++) - { - KEY &key_info= outparam->key_info[k]; - uint parts = (share->use_ext_keys ? key_info.ext_key_parts : - key_info.user_defined_key_parts); - for (uint p= 0; p < parts; p++) - { - KEY_PART_INFO &kp= key_info.key_part[p]; - if (kp.field != outparam->field[kp.fieldnr - 1]) - { - kp.field->vcol_info = outparam->field[kp.fieldnr - 1]->vcol_info; - } - } - } + outparam->update_keypart_vcol_info(); } #ifdef WITH_PARTITION_STORAGE_ENGINE diff --git a/sql/table.h b/sql/table.h index b3e23ab02e8..d46f91ee2dd 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1695,6 +1695,7 @@ public: bool is_filled_at_execution(); bool update_const_key_parts(COND *conds); + void update_keypart_vcol_info(); inline void initialize_opt_range_structures(); From 0cf2176b7975abeacc7c1e7c5f673440c26953c6 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:58 +0300 Subject: [PATCH 026/118] MDEV-34033 Exchange partition with virtual columns fails MDEV-28127 did is_equal() which compared vcol expressions literally. But another table vcol expression is not equal because of different table name. We implement another comparison method is_identical() which respects different table name in vcol comparison. If any field item points to table_A and compared field item points to table_B, such items are treated as equal in (table_A, table_B) comparison. This is done by cloning table_B expression and renaming any table_B entries to table_A in it. --- mysql-test/main/partition_exchange.result | 22 ++++++++++++++++ mysql-test/main/partition_exchange.test | 32 +++++++++++++++++++++++ sql/field.h | 3 +++ sql/item.cc | 24 +++++++++++++++++ sql/item.h | 9 +++++++ sql/sql_class.h | 1 + sql/sql_partition_admin.cc | 2 ++ sql/sql_table.cc | 6 ++++- sql/table.cc | 21 +++++++++++++++ 9 files changed, 119 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/partition_exchange.result b/mysql-test/main/partition_exchange.result index c82d8d2071b..999517f4028 100644 --- a/mysql-test/main/partition_exchange.result +++ b/mysql-test/main/partition_exchange.result @@ -1321,3 +1321,25 @@ CREATE TABLE t2 (a INT, PRIMARY KEY(a)) CHECKSUM=1, ENGINE=InnoDB; ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; ERROR HY000: Tables have different definitions DROP TABLE t1, t2; +# +# MDEV-34033 Exchange partition with virtual columns fails +# +create or replace table t1( +id int primary key, +col1 int, +col2 boolean as (col1 is null)) +partition by list (id) ( partition p1 values in (1) +); +create or replace table t1_working like t1; +alter table t1_working remove partitioning; +alter table t1 exchange partition p1 with table t1_working; +create or replace table t2( +id int primary key, +col1 int, +col2 boolean as (true)) +partition by list (id) ( partition p1 values in (1) +); +create or replace table t2_working like t2; +alter table t2_working remove partitioning; +alter table t2 exchange partition p1 with table t2_working; +drop tables t1, t1_working, t2, t2_working; diff --git a/mysql-test/main/partition_exchange.test b/mysql-test/main/partition_exchange.test index 4125e998623..e92b8dfff5c 100644 --- a/mysql-test/main/partition_exchange.test +++ b/mysql-test/main/partition_exchange.test @@ -554,3 +554,35 @@ ALTER TABLE t1 EXCHANGE PARTITION p0 WITH TABLE t2; # Cleanup DROP TABLE t1, t2; + +--echo # +--echo # MDEV-34033 Exchange partition with virtual columns fails +--echo # +# this fails when the virtual persistent column +# references another column +create or replace table t1( + id int primary key, + col1 int, + col2 boolean as (col1 is null)) + partition by list (id) ( partition p1 values in (1) +); + +create or replace table t1_working like t1; +alter table t1_working remove partitioning; +alter table t1 exchange partition p1 with table t1_working; + +# this works when the virtual persistent column +# does not reference another column +create or replace table t2( + id int primary key, + col1 int, + col2 boolean as (true)) + partition by list (id) ( partition p1 values in (1) +); + +create or replace table t2_working like t2; +alter table t2_working remove partitioning; +alter table t2 exchange partition p1 with table t2_working; + +# Cleanup +drop tables t1, t1_working, t2, t2_working; diff --git a/sql/field.h b/sql/field.h index 7ea431e8acb..3894c22e6da 100644 --- a/sql/field.h +++ b/sql/field.h @@ -659,6 +659,9 @@ public: bool cleanup_session_expr(); bool fix_and_check_expr(THD *thd, TABLE *table); inline bool is_equal(const Virtual_column_info* vcol) const; + /* Same as is_equal() but for comparing with different table */ + bool is_equivalent(THD *thd, TABLE_SHARE *share, TABLE_SHARE *vcol_share, + const Virtual_column_info* vcol, bool &error) const; inline void print(String*); }; diff --git a/sql/item.cc b/sql/item.cc index 44bd4bbfbba..e6e69629fe5 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -833,6 +833,30 @@ bool Item_field::rename_fields_processor(void *arg) return 0; } +/** + Rename table and clean field for EXCHANGE comparison +*/ + +bool Item_field::rename_table_processor(void *arg) +{ + Item::func_processor_rename_table *p= (Item::func_processor_rename_table*) arg; + + /* If (db_name, table_name) matches (p->old_db, p->old_table) + rename to (p->new_db, p->new_table) */ + if (((!db_name.str && !p->old_db.str) || + db_name.streq(p->old_db)) && + ((!table_name.str && !p->old_table.str) || + table_name.streq(p->old_table))) + { + db_name= p->new_db; + table_name= p->new_table; + } + + /* Item_field equality is done by field pointer if it is set, we need to avoid that */ + field= NULL; + return 0; +} + /** Check if an Item_field references some field from a list of fields. diff --git a/sql/item.h b/sql/item.h index 147b12dfa8b..a146107508f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2148,6 +2148,7 @@ public: virtual bool check_partition_func_processor(void *arg) { return 1;} virtual bool post_fix_fields_part_expr_processor(void *arg) { return 0; } virtual bool rename_fields_processor(void *arg) { return 0; } + virtual bool rename_table_processor(void *arg) { return 0; } /* TRUE if the function is knowingly TRUE or FALSE. Not to be used for AND/OR formulas. @@ -2176,6 +2177,13 @@ public: LEX_CSTRING table_name; List fields; }; + struct func_processor_rename_table + { + Lex_ident_db old_db; + Lex_ident_table old_table; + Lex_ident_db new_db; + Lex_ident_table new_table; + }; virtual bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(full_name(), arg, VCOL_IMPOSSIBLE); @@ -3659,6 +3667,7 @@ public: bool switch_to_nullable_fields_processor(void *arg) override; bool update_vcol_processor(void *arg) override; bool rename_fields_processor(void *arg) override; + bool rename_table_processor(void *arg) override; bool check_vcol_func_processor(void *arg) override; bool set_fields_as_dependent_processor(void *arg) override { diff --git a/sql/sql_class.h b/sql/sql_class.h index 032d0bc2606..03860e5ff4e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -50,6 +50,7 @@ #include "session_tracker.h" #include "backup.h" #include "xa.h" +#include "scope.h" extern "C" void set_thd_stage_info(void *thd, diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 68dd3379d64..0ee775687f9 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -241,6 +241,8 @@ static bool compare_table_with_partition(THD *thd, TABLE *table, part_create_info.row_type= table->s->row_type; } + part_create_info.table= part_table; + /* NOTE: ha_blackhole does not support check_if_compatible_data, so this always fail for blackhole tables. diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2119b98a0a2..64c142e6df3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7874,8 +7874,12 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, { if (!tmp_new_field->field->vcol_info) DBUG_RETURN(false); - if (!field->vcol_info->is_equal(tmp_new_field->field->vcol_info)) + bool err; + if (!field->vcol_info->is_equivalent(thd, table->s, create_info->table->s, + tmp_new_field->field->vcol_info, err)) DBUG_RETURN(false); + if (err) + DBUG_RETURN(true); } /* diff --git a/sql/table.cc b/sql/table.cc index 11564e85af0..b18ee64f480 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3542,6 +3542,27 @@ bool Virtual_column_info::cleanup_session_expr() } +bool +Virtual_column_info::is_equivalent(THD *thd, TABLE_SHARE *share, TABLE_SHARE *vcol_share, + const Virtual_column_info* vcol, bool &error) const +{ + error= true; + Item *cmp_expr= vcol->expr->build_clone(thd); + if (!cmp_expr) + return false; + Item::func_processor_rename_table param; + param.old_db= Lex_ident_db(vcol_share->db); + param.old_table= Lex_ident_table(vcol_share->table_name); + param.new_db= Lex_ident_db(share->db); + param.new_table= Lex_ident_table(share->table_name); + cmp_expr->walk(&Item::rename_table_processor, 1, ¶m); + + error= false; + return type_handler() == vcol->type_handler() + && is_stored() == vcol->is_stored() + && expr->eq(cmp_expr, true); +} + class Vcol_expr_context { From 0dcd30197ade55b7afb248e99b29b80ead99b3e2 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:58 +0300 Subject: [PATCH 027/118] MDEV-25654 Unexpected ER_CRASHED_ON_USAGE and Assertion `limit >= trx_id' failed in purge_node_t::skip For fast alter partition ALTER lost hash fields in frm field count. mysql_prepare_create_table() did not call add_hash_field() because the logic of ALTER-ing field types implies automatic promotion/demotion to/from hash index. So we don't pass hash algorithm to mysql_prepare_create_table() and let it decide itself, but it cannot decide it correctly for fast alter partition. So now mysql_prepare_alter_table() is a bit more sophisticated on what to pass in the algorithm. If not changed any fields it will force mysql_prepare_create_table() to re-add hash fields by setting HA_KEY_ALG_HASH. The problem with the original logic is mysql_prepare_alter_table() does not care 100% about hash property so the decision is blurred between mysql_prepare_alter_table() and mysql_prepare_create_table(). --- mysql-test/main/long_unique_bugs.result | 12 ++++++++++++ mysql-test/main/long_unique_bugs.test | 15 +++++++++++++++ sql/sql_table.cc | 15 ++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index c85f5d5b21e..1caec209d9f 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -729,4 +729,16 @@ alter table t1 enable keys; insert into t1 values (2); ERROR 23000: Duplicate entry '2' for key 'i' drop table t1; +# +# MDEV-25654 Unexpected ER_CRASHED_ON_USAGE and Assertion `limit >= trx_id' failed in purge_node_t::skip +# +create table t1 (a int, unique using hash (a)) engine=innodb +partition by range(a) ( +partition p1 values less than (2), +partition p2 values less than (101) +); +insert into t1 select seq from seq_1_to_100; +alter table t1 add partition (partition p3 values less than (maxvalue)); +alter table t1 force; +drop table t1; # End of 10.5 tests diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 2f85328bda3..6ad59fe6495 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -706,4 +706,19 @@ alter table t1 enable keys; insert into t1 values (2); drop table t1; +--echo # +--echo # MDEV-25654 Unexpected ER_CRASHED_ON_USAGE and Assertion `limit >= trx_id' failed in purge_node_t::skip +--echo # +create table t1 (a int, unique using hash (a)) engine=innodb +partition by range(a) ( + partition p1 values less than (2), + partition p2 values less than (101) +); +insert into t1 select seq from seq_1_to_100; + +alter table t1 add partition (partition p3 values less than (maxvalue)); +alter table t1 force; + +drop table t1; + --echo # End of 10.5 tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 64c142e6df3..e744ab78a2f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9264,7 +9264,20 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, LEX_CSTRING tmp_name; bzero((char*) &key_create_info, sizeof(key_create_info)); if (key_info->algorithm == HA_KEY_ALG_LONG_HASH) - key_info->algorithm= HA_KEY_ALG_UNDEF; + key_info->algorithm= (alter_info->flags & ALTER_CHANGE_COLUMN) ? + HA_KEY_ALG_UNDEF : HA_KEY_ALG_HASH; + /* + This one goes to mysql_prepare_create_table(): + + key_info->algorithm= key->key_create_info.algorithm; + + For HA_KEY_ALG_LONG_HASH if we didn't change ANY column, we pass + HA_KEY_ALG_HASH to ensure mysql_prepare_create_table() does add_hash_field(). + This protects fast alter partition from losing hash properties. + In case of any column changes we drop algorithm to HA_KEY_ALG_UNDEF and + let decide mysql_prepare_create_table() if the hash field is needed + depending on new types. + */ key_create_info.algorithm= key_info->algorithm; /* We copy block size directly as some engines, like Area, sets this From e760a6dc1ceab5b0f2809d194af0f321fa12b933 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Mon, 13 Jan 2025 15:40:59 +0300 Subject: [PATCH 028/118] MDEV-35343 ha_heap: recover the cursor after failed ha_update_row --- storage/heap/hp_update.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/storage/heap/hp_update.c b/storage/heap/hp_update.c index da83a9c76a8..ad56ca979de 100644 --- a/storage/heap/hp_update.c +++ b/storage/heap/hp_update.c @@ -21,7 +21,8 @@ int heap_update(HP_INFO *info, const uchar *old, const uchar *heap_new) { HP_KEYDEF *keydef, *end, *p_lastinx; - uchar *pos; + uchar *pos, *recovery_ptr; + struct st_hp_hash_info *recovery_hash_ptr; my_bool auto_key_changed= 0, key_changed= 0; HP_SHARE *share= info->s; DBUG_ENTER("heap_update"); @@ -34,6 +35,10 @@ int heap_update(HP_INFO *info, const uchar *old, const uchar *heap_new) if (--(share->records) < share->blength >> 1) share->blength>>= 1; share->changed=1; + // Save the cursor position to recover if insert fails. + recovery_ptr= info->current_ptr; + recovery_hash_ptr= info->current_hash_ptr; + p_lastinx= share->keydef + info->lastinx; for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++) { @@ -84,6 +89,8 @@ int heap_update(HP_INFO *info, const uchar *old, const uchar *heap_new) } keydef--; } + info->current_ptr= recovery_ptr; + info->current_hash_ptr= recovery_hash_ptr; } if (++(share->records) == share->blength) share->blength+= share->blength; From e1e1e50bbaf3fd96ac0b5ca4fcd28a458132e9bd Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:59 +0300 Subject: [PATCH 029/118] MDEV-35343 DML debug logging Usage: mtr --mysqld=--debug=d,dml,query:i:o,/tmp/dml.log Example output: T@6 : dispatch_command: query: insert into t1 values ('a') T@6 : handler::ha_write_row: exit: INSERT: t1(a) = 0 T@6 : dispatch_command: query: alter ignore table t1 add unique index (data) T@6 : handler::ha_write_row: exit: INSERT: t1(a) = 0 T@6 : dispatch_command: query: alter ignore table t1 add unique index (data) T@6 : handler::ha_write_row: exit: INSERT: t1(a) = 0 T@6 : dispatch_command: query: replace into t1 values ('b'), ('c'), ('a'), ('b') T@6 : handler::ha_write_row: exit: INSERT: t1(b) = 0 T@6 : handler::ha_write_row: exit: INSERT: t1(c) = 0 T@6 : handler::ha_write_row: exit: INSERT: t1(a) = 121 T@6 : write_record: exit: DELETE: t1(a) = 0 T@6 : handler::ha_write_row: exit: INSERT: t1(a) = 0 T@6 : handler::ha_write_row: exit: INSERT: t1(b) = 121 T@6 : write_record: exit: DELETE: t1(b) = 0 T@6 : handler::ha_write_row: exit: INSERT: t1(b) = 0 --- sql/filesort.cc | 70 +++++++++++++++++++++++++++---------------------- sql/handler.cc | 4 +++ sql/handler.h | 4 +++ 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/sql/filesort.cc b/sql/filesort.cc index 822c52700a6..af03067257c 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -634,13 +634,6 @@ static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count, } #ifndef DBUG_OFF - -/* Buffer where record is returned */ -char dbug_print_row_buff[512]; - -/* Temporary buffer for printing a column */ -char dbug_print_row_buff_tmp[512]; - /* Print table's current row into a buffer and return a pointer to it. @@ -653,37 +646,53 @@ char dbug_print_row_buff_tmp[512]; Only columns in table->read_set are printed */ -const char* dbug_print_table_row(TABLE *table) +const char* dbug_print_row(TABLE *table, const uchar *rec, bool print_names) { Field **pfield; - String tmp(dbug_print_row_buff_tmp, - sizeof(dbug_print_row_buff_tmp),&my_charset_bin); + const size_t alloc_size= 512; + char *row_buff= (char *) alloc_root(&table->mem_root, alloc_size); + char *row_buff_tmp= (char *) alloc_root(&table->mem_root, alloc_size); + String tmp(row_buff_tmp, alloc_size, &my_charset_bin); + String output(row_buff, alloc_size, &my_charset_bin); - String output(dbug_print_row_buff, sizeof(dbug_print_row_buff), - &my_charset_bin); + auto move_back_lambda= [table, rec]() mutable { + table->move_fields(table->field, table->record[0], rec); + }; + auto move_back_guard= make_scope_exit(move_back_lambda, false); + + if (rec != table->record[0]) + { + table->move_fields(table->field, rec, table->record[0]); + move_back_guard.engage(); + } + + SCOPE_VALUE(table->read_set, (table->read_set && table->write_set) ? + table->write_set : table->read_set); output.length(0); output.append(table->alias); output.append("("); bool first= true; - - for (pfield= table->field; *pfield ; pfield++) + if (print_names) { - if (table->read_set && !bitmap_is_set(table->read_set, (*pfield)->field_index)) - continue; - - if (first) - first= false; - else - output.append(","); + for (pfield= table->field; *pfield ; pfield++) + { + if (table->read_set && !bitmap_is_set(table->read_set, (*pfield)->field_index)) + continue; - output.append((*pfield)->field_name.str ? - (*pfield)->field_name.str: "NULL"); + if (first) + first= false; + else + output.append(", "); + + output.append((*pfield)->field_name.str ? + (*pfield)->field_name.str: "NULL"); + } + + output.append(")=("); + first= true; } - output.append(")=("); - - first= true; for (pfield= table->field; *pfield ; pfield++) { Field *field= *pfield; @@ -694,7 +703,7 @@ const char* dbug_print_table_row(TABLE *table) if (first) first= false; else - output.append(","); + output.append(", "); if (field->is_null()) output.append("NULL"); @@ -713,12 +722,9 @@ const char* dbug_print_table_row(TABLE *table) } -const char* dbug_print_row(TABLE *table, uchar *rec) +const char* dbug_print_table_row(TABLE *table) { - table->move_fields(table->field, rec, table->record[0]); - const char* ret= dbug_print_table_row(table); - table->move_fields(table->field, table->record[0], rec); - return ret; + return dbug_print_row(table, table->record[0]); } diff --git a/sql/handler.cc b/sql/handler.cc index 38453b5e2a7..50bcf86f25c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7350,6 +7350,7 @@ int handler::ha_write_row(const uchar *buf) TABLE_IO_WAIT(tracker, PSI_TABLE_WRITE_ROW, MAX_KEY, error, { error= write_row(buf); }) + DBUG_PRINT("dml", ("INSERT: %s = %d", dbug_print_row(table, buf, false), error)); MYSQL_INSERT_ROW_DONE(error); if (likely(!error)) @@ -7410,6 +7411,8 @@ int handler::ha_update_row(const uchar *old_data, const uchar *new_data) TABLE_IO_WAIT(tracker, PSI_TABLE_UPDATE_ROW, active_index, 0, { error= update_row(old_data, new_data);}) + DBUG_PRINT("dml", ("UPDATE: %s => %s = %d", dbug_print_row(table, old_data, false), + dbug_print_row(table, new_data, false), error)); MYSQL_UPDATE_ROW_DONE(error); if (likely(!error)) @@ -7489,6 +7492,7 @@ int handler::ha_delete_row(const uchar *buf) TABLE_IO_WAIT(tracker, PSI_TABLE_DELETE_ROW, active_index, error, { error= delete_row(buf);}) + DBUG_PRINT("dml", ("DELETE: %s = %d", dbug_print_row(table, buf, false), error)); MYSQL_DELETE_ROW_DONE(error); if (likely(!error)) { diff --git a/sql/handler.h b/sql/handler.h index ad1cbaff5b7..c06c27b08c9 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -5322,4 +5322,8 @@ bool non_existing_table_error(int error); int get_select_field_pos(Alter_info *alter_info, int select_field_count, bool versioned); + +#ifndef DBUG_OFF +const char* dbug_print_row(TABLE *table, const uchar *rec, bool print_names= true); +#endif /* DBUG_OFF */ #endif /* HANDLER_INCLUDED */ From 78c192644c093ec2968e5748cd1d66b66dfbc1a9 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:59 +0300 Subject: [PATCH 030/118] MDEV-35343 unexpected replace behaviour when long unique index on system versioned table For versioned table REPLACE first tries to insert a row, if it gets duplicate key error and optimization is possible it does UPDATE + INSERT history. If optimization is not possible it goes normal branch for UPDATE to history and repeats the cycle of INSERT. The failure was in normal branch when we tried UPDATE to history but such history already exists from previous cycles. There is no such failures in optimized branch because vers_insert_history_row() already ignores duplicates. The fix ignores duplicate errors for UPDATE to history and does DELETE instead. --- mysql-test/suite/versioning/r/replace.result | 16 +++++++++++++++ mysql-test/suite/versioning/t/replace.test | 15 ++++++++++++++ sql/sql_insert.cc | 21 ++++++++++++++++++-- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/versioning/r/replace.result b/mysql-test/suite/versioning/r/replace.result index 8ac4047c5ff..c64f42ee7cf 100644 --- a/mysql-test/suite/versioning/r/replace.result +++ b/mysql-test/suite/versioning/r/replace.result @@ -27,7 +27,9 @@ id x current 1 2 0 1 3 1 drop table t; +# # MDEV-15645 Assertion `table->insert_values' failed in write_record upon REPLACE into a view with underlying versioned table +# create or replace table t1 (a int, b int, primary key (a), unique(b)) with system versioning; insert into t1 values (1,1); create or replace table t2 (c int); @@ -48,7 +50,9 @@ INSERT INTO t1 () VALUES (),(),(),(),(),(); UPDATE IGNORE t1 SET f = 1; REPLACE t1 SELECT * FROM t1; DROP TABLE t1; +# # MDEV-22540 ER_DUP_ENTRY upon REPLACE or Assertion failed +# set timestamp=1589245268.41934; create table t1 (a int primary key) with system versioning; insert into t1 values (1),(2); @@ -72,3 +76,15 @@ Warnings: Warning 1062 Duplicate entry '1' for key 'a' load data infile '15330.data' replace into table t1 (a,b,c); drop table t1; +# +# MDEV-35343 unexpected replace behaviour when long unique index on system versioned table +# +create table t1 (data char(10)); +insert into t1 values ('o'); +alter ignore table t1 add unique index (data); +alter ignore table t1 add unique index (data); +Warnings: +Note 1831 Duplicate index `data_2`. This is deprecated and will be disallowed in a future release +alter table t1 add system versioning; +replace into t1 values ('o'), ('o'); +drop table t1; diff --git a/mysql-test/suite/versioning/t/replace.test b/mysql-test/suite/versioning/t/replace.test index d69eebd1b9c..c10b6aa443d 100644 --- a/mysql-test/suite/versioning/t/replace.test +++ b/mysql-test/suite/versioning/t/replace.test @@ -35,7 +35,9 @@ replace t values (1, 3); select *, current_row(row_end) as current from t for system_time all order by x; drop table t; +--echo # --echo # MDEV-15645 Assertion `table->insert_values' failed in write_record upon REPLACE into a view with underlying versioned table +--echo # create or replace table t1 (a int, b int, primary key (a), unique(b)) with system versioning; insert into t1 values (1,1); create or replace table t2 (c int); @@ -59,7 +61,9 @@ UPDATE IGNORE t1 SET f = 1; REPLACE t1 SELECT * FROM t1; DROP TABLE t1; +--echo # --echo # MDEV-22540 ER_DUP_ENTRY upon REPLACE or Assertion failed +--echo # set timestamp=1589245268.41934; create table t1 (a int primary key) with system versioning; insert into t1 values (1),(2); @@ -105,4 +109,15 @@ drop table t1; eval set default_storage_engine= $default_engine; --enable_query_log +--echo # +--echo # MDEV-35343 unexpected replace behaviour when long unique index on system versioned table +--echo # +create table t1 (data char(10)); +insert into t1 values ('o'); +alter ignore table t1 add unique index (data); +alter ignore table t1 add unique index (data); +alter table t1 add system versioning; +replace into t1 values ('o'), ('o'); +drop table t1; + --source suite/versioning/common_finish.inc diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 50a1a37e3ea..acc841e27f0 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2126,6 +2126,9 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) !table->file->referenced_by_foreign_key() && (!table->triggers || !table->triggers->has_delete_triggers())) { + /* + Optimized dup handling via UPDATE (and insert history for versioned). + */ if (table->versioned(VERS_TRX_ID)) { bitmap_set_bit(table->write_set, table->vers_start_field()->field_index); @@ -2160,25 +2163,39 @@ int write_record(THD *thd, TABLE *table, COPY_INFO *info, select_result *sink) } else { + /* + Normal dup handling via DELETE (or UPDATE to history for versioned) + and repeating the cycle of INSERT. + */ if (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_DELETE, TRG_ACTION_BEFORE, TRUE)) goto before_trg_err; - if (!table->versioned(VERS_TIMESTAMP)) + bool do_delete= !table->versioned(VERS_TIMESTAMP); + if (do_delete) error= table->file->ha_delete_row(table->record[1]); else { + /* Update existing row to history */ store_record(table, record[2]); restore_record(table, record[1]); table->vers_update_end(); error= table->file->ha_update_row(table->record[1], table->record[0]); restore_record(table, record[2]); + if (error == HA_ERR_FOUND_DUPP_KEY || /* Unique index, any SE */ + error == HA_ERR_FOREIGN_DUPLICATE_KEY || /* Unique index, InnoDB */ + error == HA_ERR_RECORD_IS_THE_SAME) /* No index */ + { + /* Such history row was already generated from previous cycles */ + error= table->file->ha_delete_row(table->record[1]); + do_delete= true; + } } if (unlikely(error)) goto err; - if (!table->versioned(VERS_TIMESTAMP)) + if (do_delete) info->deleted++; else info->updated++; From 4a58d1085dfc7e2dea7affdd7e389493fc0fd430 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:59 +0300 Subject: [PATCH 031/118] MDEV-35612 EXCHANGE PARTITION does not work for tables with unique blobs mysql_compare_tables() failed because of no long hash index generated fields in prepared tmp_create_info. In comparison we should skip these fields in the original table by: 1. skipping INVISIBLE_SYSTEM fields; 2. getting key_info from table->s instead of table as TABLE_SHARE contains unwrapped key_info. --- mysql-test/main/partition_exchange.result | 10 ++++++++++ mysql-test/main/partition_exchange.test | 14 ++++++++++++++ sql/sql_table.cc | 22 +++++++++++++++++----- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/partition_exchange.result b/mysql-test/main/partition_exchange.result index 999517f4028..c9169c5c818 100644 --- a/mysql-test/main/partition_exchange.result +++ b/mysql-test/main/partition_exchange.result @@ -1343,3 +1343,13 @@ create or replace table t2_working like t2; alter table t2_working remove partitioning; alter table t2 exchange partition p1 with table t2_working; drop tables t1, t1_working, t2, t2_working; +# +# MDEV-35612 EXCHANGE PARTITION does not work for tables with unique blobs +# +create table t (a int, b text, unique (b), unique(a, b)) partition by list (a) (partition p0 values in (1,2), partition pdef default); +create table tp (a int, b text, c int invisible, unique (b), unique(a, b)); +alter table t exchange partition p0 with table tp; +ERROR HY000: Tables have different definitions +create or replace table tp (a int, b text, unique (b), unique(a, b)); +alter table t exchange partition p0 with table tp; +drop table t, tp; diff --git a/mysql-test/main/partition_exchange.test b/mysql-test/main/partition_exchange.test index e92b8dfff5c..767f682ea0d 100644 --- a/mysql-test/main/partition_exchange.test +++ b/mysql-test/main/partition_exchange.test @@ -586,3 +586,17 @@ alter table t2 exchange partition p1 with table t2_working; # Cleanup drop tables t1, t1_working, t2, t2_working; + +--echo # +--echo # MDEV-35612 EXCHANGE PARTITION does not work for tables with unique blobs +--echo # +create table t (a int, b text, unique (b), unique(a, b)) partition by list (a) (partition p0 values in (1,2), partition pdef default); +create table tp (a int, b text, c int invisible, unique (b), unique(a, b)); +--error ER_TABLES_DIFFERENT_METADATA +alter table t exchange partition p0 with table tp; + +create or replace table tp (a int, b text, unique (b), unique(a, b)); +alter table t exchange partition p0 with table tp; + +# cleanup +drop table t, tp; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e744ab78a2f..3563c0fa982 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7852,7 +7852,16 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, DBUG_RETURN(1); /* Some very basic checks. */ - if (table->s->fields != alter_info->create_list.elements || + uint fields= table->s->fields; + + /* There is no field count on system-invisible fields, count them. */ + for (Field **f_ptr= table->field; *f_ptr; f_ptr++) + { + if ((*f_ptr)->invisible >= INVISIBLE_SYSTEM) + fields--; + } + + if (fields != alter_info->create_list.elements || table->s->db_type() != create_info->db_type || table->s->tmp_table || (table->s->row_type != create_info->row_type)) @@ -7863,6 +7872,9 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, for (Field **f_ptr= table->field; *f_ptr; f_ptr++) { Field *field= *f_ptr; + /* Skip hidden generated field like long hash index. */ + if (field->invisible >= INVISIBLE_SYSTEM) + continue; Create_field *tmp_new_field= tmp_new_field_it++; /* Check that NULL behavior is the same. */ @@ -7915,13 +7927,13 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, DBUG_RETURN(false); /* Go through keys and check if they are compatible. */ - KEY *table_key; - KEY *table_key_end= table->key_info + table->s->keys; + KEY *table_key= table->s->key_info; + KEY *table_key_end= table_key + table->s->keys; KEY *new_key; KEY *new_key_end= key_info_buffer + key_count; /* Step through all keys of the first table and search matching keys. */ - for (table_key= table->key_info; table_key < table_key_end; table_key++) + for (; table_key < table_key_end; table_key++) { /* Search a key with the same name. */ for (new_key= key_info_buffer; new_key < new_key_end; new_key++) @@ -7964,7 +7976,7 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, for (new_key= key_info_buffer; new_key < new_key_end; new_key++) { /* Search a key with the same name. */ - for (table_key= table->key_info; table_key < table_key_end; table_key++) + for (table_key= table->s->key_info; table_key < table_key_end; table_key++) { if (!lex_string_cmp(system_charset_info, &table_key->name, &new_key->name)) From ab90eaad792996d10c5c67cde09cffa3d5baebbd Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:59 +0300 Subject: [PATCH 032/118] MDEV-22695 Server crashes in heap_rnext upon DELETE from a HEAP table Quick read record uses different handler (H1) for finding records. It cannot use ha_delete_row() handler (H2) as it is different search mode: inited == INDEX for H1, inited == RND for H2. So, read handler H1 uses index while write handler H2 uses random access. For going next record in H1 there is info->last_pos optimization for stepping index via tree_search_next(). This optimization can work with deleted rows only if delete is conducted in the same handler, there is: 67 int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, 68 const uchar *record, uchar *recpos, int flag) 69 { ... 74 if (flag) 75 info->last_pos= NULL; /* For heap_rnext/heap_rprev */ But this cannot work for different handler. So, last_pos in H1 after delete in H2 contains stale info->parents array and last_pos points into that parents. In the specific test case last_pos' parent is already freed node and tree_search_next() steps into it. The fix invalidates local savings of info->parents and info->last_pos based on key_version. Record deletion increments share->key_version in H2, so in H1 we know the tree might be changed. Another good measure would be to use H1 for delete. But this is bigger refactoring than just bug fixing. --- mysql-test/suite/heap/heap.result | 7 +++++++ mysql-test/suite/heap/heap.test | 9 +++++++++ storage/heap/hp_rnext.c | 4 +++- storage/heap/hp_rprev.c | 3 ++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/heap/heap.result b/mysql-test/suite/heap/heap.result index 67641d51b02..11c50d97475 100644 --- a/mysql-test/suite/heap/heap.result +++ b/mysql-test/suite/heap/heap.result @@ -877,3 +877,10 @@ DELETE FROM t1 WHERE ts = 1 AND color = 'GREEN'; SELECT * from t1 WHERE ts = 1 AND color = 'GREEN'; id color ts DROP TABLE t1; +# +# MDEV-22695 Server crashes in heap_rnext upon DELETE from a HEAP table +# +CREATE TABLE t1 (a VARCHAR(128), b VARCHAR(32), KEY(a) USING BTREE, KEY(b) USING BTREE) ENGINE=HEAP; +INSERT INTO t1 VALUES ('foo',NULL),('m','b'),(6,'j'),('bar','qux'),(NULL,NULL); +DELETE FROM t1 WHERE a <=> 'm' OR b <=> NULL; +DROP TABLE t1; diff --git a/mysql-test/suite/heap/heap.test b/mysql-test/suite/heap/heap.test index ef950da5484..02a2586f605 100644 --- a/mysql-test/suite/heap/heap.test +++ b/mysql-test/suite/heap/heap.test @@ -659,3 +659,12 @@ INSERT INTO t1 VALUES("7","GREEN", 2); DELETE FROM t1 WHERE ts = 1 AND color = 'GREEN'; SELECT * from t1 WHERE ts = 1 AND color = 'GREEN'; DROP TABLE t1; + +--echo # +--echo # MDEV-22695 Server crashes in heap_rnext upon DELETE from a HEAP table +--echo # +CREATE TABLE t1 (a VARCHAR(128), b VARCHAR(32), KEY(a) USING BTREE, KEY(b) USING BTREE) ENGINE=HEAP; +INSERT INTO t1 VALUES ('foo',NULL),('m','b'),(6,'j'),('bar','qux'),(NULL,NULL); +DELETE FROM t1 WHERE a <=> 'm' OR b <=> NULL; +# Cleanup +DROP TABLE t1; diff --git a/storage/heap/hp_rnext.c b/storage/heap/hp_rnext.c index f227ce4d274..ac21ed83da2 100644 --- a/storage/heap/hp_rnext.c +++ b/storage/heap/hp_rnext.c @@ -46,7 +46,7 @@ int heap_rnext(HP_INFO *info, uchar *record) &info->last_pos, offsetof(TREE_ELEMENT, left)); } } - else if (info->last_pos) + else if (info->last_pos && info->key_version == info->s->key_version) { /* We enter this branch for non-DELETE queries after heap_rkey() @@ -72,6 +72,7 @@ int heap_rnext(HP_INFO *info, uchar *record) */ pos= tree_search_edge(&keyinfo->rb_tree, info->parents, &info->last_pos, offsetof(TREE_ELEMENT, left)); + info->key_version= info->s->key_version; } else { @@ -87,6 +88,7 @@ int heap_rnext(HP_INFO *info, uchar *record) info->last_find_flag= HA_READ_KEY_OR_NEXT; pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents, &info->last_pos, info->last_find_flag, &custom_arg); + info->key_version= info->s->key_version; } if (pos) { diff --git a/storage/heap/hp_rprev.c b/storage/heap/hp_rprev.c index 1d9420ba8b6..cc81d179570 100644 --- a/storage/heap/hp_rprev.c +++ b/storage/heap/hp_rprev.c @@ -46,7 +46,7 @@ int heap_rprev(HP_INFO *info, uchar *record) &info->last_pos, offsetof(TREE_ELEMENT, right)); } } - else if (info->last_pos) + else if (info->last_pos && info->key_version == info->s->key_version) pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos, offsetof(TREE_ELEMENT, right), offsetof(TREE_ELEMENT, left)); @@ -58,6 +58,7 @@ int heap_rprev(HP_INFO *info, uchar *record) info->last_find_flag= HA_READ_KEY_OR_PREV; pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents, &info->last_pos, info->last_find_flag, &custom_arg); + info->key_version= info->s->key_version; } if (pos) { From 0fa1a7cc6af2d1ca90363f73d6bff97c805caf22 Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Mon, 13 Jan 2025 15:40:59 +0300 Subject: [PATCH 033/118] MDEV-28130 MariaDB SEGV issue at tree_search_next In case of error last_pos points to null_element and there is no any other children. tree_search_next() walks the children from last_pos until the leaves (null_element) ignoring the case the topmost parent in search state is the leaf itself. --- mysql-test/suite/heap/heap.result | 12 ++++++++++++ mysql-test/suite/heap/heap.test | 10 ++++++++++ mysys/tree.c | 3 +++ 3 files changed, 25 insertions(+) diff --git a/mysql-test/suite/heap/heap.result b/mysql-test/suite/heap/heap.result index 11c50d97475..d42e898a0ae 100644 --- a/mysql-test/suite/heap/heap.result +++ b/mysql-test/suite/heap/heap.result @@ -884,3 +884,15 @@ CREATE TABLE t1 (a VARCHAR(128), b VARCHAR(32), KEY(a) USING BTREE, KEY(b) USING INSERT INTO t1 VALUES ('foo',NULL),('m','b'),(6,'j'),('bar','qux'),(NULL,NULL); DELETE FROM t1 WHERE a <=> 'm' OR b <=> NULL; DROP TABLE t1; +# +# MDEV-28130 MariaDB SEGV issue at tree_search_next +# +CREATE TABLE v(t1 INT, pk INT, KEY(t1), KEY pk using btree (pk), KEY v using btree(t1, pk)) engine=memory; +HANDLER v OPEN; +HANDLER v READ t1=(2) limit 3; +t1 pk +HANDLER v READ pk PREV; +t1 pk +HANDLER v READ pk PREV; +t1 pk +drop table v; diff --git a/mysql-test/suite/heap/heap.test b/mysql-test/suite/heap/heap.test index 02a2586f605..97784aefc0f 100644 --- a/mysql-test/suite/heap/heap.test +++ b/mysql-test/suite/heap/heap.test @@ -668,3 +668,13 @@ INSERT INTO t1 VALUES ('foo',NULL),('m','b'),(6,'j'),('bar','qux'),(NULL,NULL); DELETE FROM t1 WHERE a <=> 'm' OR b <=> NULL; # Cleanup DROP TABLE t1; + +--echo # +--echo # MDEV-28130 MariaDB SEGV issue at tree_search_next +--echo # +CREATE TABLE v(t1 INT, pk INT, KEY(t1), KEY pk using btree (pk), KEY v using btree(t1, pk)) engine=memory; +HANDLER v OPEN; +HANDLER v READ t1=(2) limit 3; +HANDLER v READ pk PREV; +HANDLER v READ pk PREV; +drop table v; diff --git a/mysys/tree.c b/mysys/tree.c index cd44f779e6f..db0442fa827 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -494,6 +494,9 @@ void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs, int r_offs) { TREE_ELEMENT *x= **last_pos; + + if (x == &null_element) + return NULL; if (ELEMENT_CHILD(x, r_offs) != &null_element) { From a5174aaffb8f22b211945170588828557dbdb211 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 14 Jan 2025 22:42:18 +0200 Subject: [PATCH 034/118] MDEV-35828: Assertion fails in alloc_root() when memory causes it to call itself (Variant 2: use stack for buffers) my_malloc_size_cb_func() has a call to thd->alloc() to produce an error message. thd->alloc() calls alloc_root(), so one can end up with this stack trace: alloc_root() THD::alloc() my_malloc_size_cb_func() my_malloc() alloc_root() where alloc_root() calls itself. This is a problem, as alloc_root() is not reenterable. Fixed this by switching my_malloc_size_cb_func() to use space on the stack instead. --- mysql-test/main/errors.result | 13 +++++++++++++ mysql-test/main/errors.test | 20 ++++++++++++++++++++ sql/mysqld.cc | 18 +++++------------- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/mysql-test/main/errors.result b/mysql-test/main/errors.result index baa2e0ad3c0..5b469b640f8 100644 --- a/mysql-test/main/errors.result +++ b/mysql-test/main/errors.result @@ -231,3 +231,16 @@ Error 1327 Undeclared variable: foo Error 1305 PROCEDURE P1 does not exist drop procedure P1; # End of 10.4 tests +# +# MDEV-35828: Assertion fails in alloc_root() when memory causes it to call itself +# +CREATE TEMPORARY TABLE t1 (a INT,b INT); +INSERT INTO t1 VALUES (1,1),(2,2); +SET +@tmp=@@max_session_mem_used, +max_session_mem_used=8192; +SELECT * FROM (t1 AS t2 LEFT JOIN t1 AS t3 USING (a)),t1; +ERROR HY000: The MariaDB server is running with the --max-session-mem-used=8192 option so it cannot execute this statement +DROP TABLE t1; +SET max_session_mem_used=@tmp; +# End of 10.6 tests diff --git a/mysql-test/main/errors.test b/mysql-test/main/errors.test index cc5cad2a68e..87d6d2fdec9 100644 --- a/mysql-test/main/errors.test +++ b/mysql-test/main/errors.test @@ -284,3 +284,23 @@ show warnings; drop procedure P1; -- echo # End of 10.4 tests + + +--echo # +--echo # MDEV-35828: Assertion fails in alloc_root() when memory causes it to call itself +--echo # +CREATE TEMPORARY TABLE t1 (a INT,b INT); +INSERT INTO t1 VALUES (1,1),(2,2); + +SET + @tmp=@@max_session_mem_used, + max_session_mem_used=8192; + +--error ER_OPTION_PREVENTS_STATEMENT +SELECT * FROM (t1 AS t2 LEFT JOIN t1 AS t3 USING (a)),t1; + +DROP TABLE t1; +SET max_session_mem_used=@tmp; + + +--echo # End of 10.6 tests diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c798956910f..d6dd8a566af 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3513,22 +3513,14 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) LOCK_thd_kill here (the limit will be enforced on the next allocation). */ if (!mysql_mutex_trylock(&thd->LOCK_thd_kill)) { - char buf[50], *buf2; + char buf[50], buf2[256]; thd->set_killed_no_mutex(KILL_QUERY); my_snprintf(buf, sizeof(buf), "--max-session-mem-used=%llu", thd->variables.max_mem_used); - if ((buf2= (char*) thd->alloc(256))) - { - my_snprintf(buf2, 256, - ER_THD(thd, ER_OPTION_PREVENTS_STATEMENT), buf); - thd->set_killed_no_mutex(KILL_QUERY, - ER_OPTION_PREVENTS_STATEMENT, buf2); - } - else - { - thd->set_killed_no_mutex(KILL_QUERY, ER_OPTION_PREVENTS_STATEMENT, - "--max-session-mem-used"); - } + my_snprintf(buf2, 256, + ER_THD(thd, ER_OPTION_PREVENTS_STATEMENT), buf); + thd->set_killed_no_mutex(KILL_QUERY, + ER_OPTION_PREVENTS_STATEMENT, buf2); mysql_mutex_unlock(&thd->LOCK_thd_kill); } } From b82abc71639661c642b9d753393be0f85e09c101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 15 Jan 2025 16:55:01 +0200 Subject: [PATCH 035/118] MDEV-35701 trx_t::autoinc_locks causes unnecessary dynamic memory allocation trx_t::autoinc_locks: Use small_vector in order to avoid any dynamic memory allocation in the most common case (a statement is holding AUTO_INCREMENT locks on at most 4 tables or partitions). lock_cancel_waiting_and_release(): Instead of removing elements from the middle, simply assign nullptr, like lock_table_remove_autoinc_lock(). The added test innodb.auto_increment_lock_mode covers the dynamic memory allocation as well as nondeterministically (occasionally) covers the out-of-order lock release in lock_table_remove_autoinc_lock(). Reviewed by: Debarun Banerjee --- .../innodb/r/auto_increment_lock_mode.result | 43 +++++ .../innodb/r/innodb-autoinc-56228.result | 35 ++-- .../t/auto_increment_lock_mode.combinations | 6 + .../innodb/t/auto_increment_lock_mode.test | 61 +++++++ .../suite/innodb/t/innodb-autoinc-56228.test | 36 ++-- storage/innobase/dict/drop.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/small_vector.h | 65 +++++-- storage/innobase/include/trx0trx.h | 14 +- storage/innobase/lock/lock0lock.cc | 158 +++++++----------- storage/innobase/mtr/mtr0mtr.cc | 4 +- storage/innobase/trx/trx0trx.cc | 28 +--- 12 files changed, 272 insertions(+), 182 deletions(-) create mode 100644 mysql-test/suite/innodb/r/auto_increment_lock_mode.result create mode 100644 mysql-test/suite/innodb/t/auto_increment_lock_mode.combinations create mode 100644 mysql-test/suite/innodb/t/auto_increment_lock_mode.test diff --git a/mysql-test/suite/innodb/r/auto_increment_lock_mode.result b/mysql-test/suite/innodb/r/auto_increment_lock_mode.result new file mode 100644 index 00000000000..b19d5cf40fc --- /dev/null +++ b/mysql-test/suite/innodb/r/auto_increment_lock_mode.result @@ -0,0 +1,43 @@ +CREATE TABLE t1(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t3(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t4(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t5(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t6(a SERIAL, b INT) ENGINE=InnoDB; +CREATE FUNCTION p1() RETURNS INT +BEGIN +INSERT INTO t1() VALUES(); +INSERT INTO t2() VALUES(); +INSERT INTO t3() VALUES(); +INSERT INTO t4() VALUES(); +INSERT INTO t5() VALUES(); +RETURN 1; +END$$ +INSERT INTO t6(b) SELECT p1(); +UPDATE t1,t2,t3,t4,t5 SET t1.a=2,t2.a=2,t3.a=2,t4.a=2,t5.a=2; +SELECT * FROM t1; +a +2 +connect con1,localhost,root,,; +connect con2,localhost,root,,; +connect con3,localhost,root,,; +connection con1; +INSERT INTO t6(b) SELECT SLEEP(p1()); +connection con2; +INSERT INTO t6(b) SELECT SLEEP(p1()); +connection con3; +UPDATE t1,t2,t3,t4,t5 SET t1.a=0,t2.a=0,t3.a=0,t4.a=0,t5.a=0 +WHERE t1.a=2 AND t2.a=2 AND t3.a=2 AND t4.a=2 AND t5.a=2; +connection default; +KILL QUERY $ID1; +KILL QUERY $ID2; +KILL QUERY $ID3; +connection con1; +disconnect con1; +connection con2; +disconnect con2; +connection con3; +disconnect con3; +connection default; +DROP FUNCTION p1; +DROP TABLE t1,t2,t3,t4,t5,t6; diff --git a/mysql-test/suite/innodb/r/innodb-autoinc-56228.result b/mysql-test/suite/innodb/r/innodb-autoinc-56228.result index 6a3fd85ebd3..f8616772151 100644 --- a/mysql-test/suite/innodb/r/innodb-autoinc-56228.result +++ b/mysql-test/suite/innodb/r/innodb-autoinc-56228.result @@ -1,15 +1,6 @@ -DROP TABLE IF EXISTS t1_56228; -Warnings: -Note 1051 Unknown table 'test.t1_56228' -DROP TABLE IF EXISTS t2_56228; -Warnings: -Note 1051 Unknown table 'test.t2_56228' -DROP FUNCTION IF EXISTS bug56228; -Warnings: -Note 1305 FUNCTION test.bug56228 does not exist -CREATE TEMPORARY TABLE t1_56228( +CREATE TABLE t1_56228( c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; -CREATE TEMPORARY TABLE t2_56228( +CREATE TABLE t2_56228( c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; CREATE FUNCTION bug56228() RETURNS INT DETERMINISTIC BEGIN @@ -17,14 +8,18 @@ INSERT INTO t1_56228 VALUES(NULL); INSERT INTO t2_56228 VALUES(NULL); INSERT INTO t1_56228 VALUES(NULL); INSERT INTO t2_56228 VALUES(NULL); -DROP TEMPORARY TABLE t1_56228; +DROP TABLE t1_56228; RETURN 42; END // -SELECT bug56228(); -bug56228() -42 -DROP FUNCTION bug56228; -DROP TEMPORARY TABLE t2_56228; -DROP TEMPORARY TABLE IF EXISTS t1_56228; -Warnings: -Note 1051 Unknown table 'test.t1_56228' +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger +CREATE PROCEDURE bug56228() +BEGIN +INSERT INTO t1_56228 VALUES(NULL); +INSERT INTO t2_56228 VALUES(NULL); +INSERT INTO t1_56228 VALUES(NULL); +INSERT INTO t2_56228 VALUES(NULL); +DROP TABLE t1_56228; +END // +CALL bug56228(); +DROP PROCEDURE bug56228; +DROP TABLE t2_56228; diff --git a/mysql-test/suite/innodb/t/auto_increment_lock_mode.combinations b/mysql-test/suite/innodb/t/auto_increment_lock_mode.combinations new file mode 100644 index 00000000000..efaee252a4e --- /dev/null +++ b/mysql-test/suite/innodb/t/auto_increment_lock_mode.combinations @@ -0,0 +1,6 @@ +[old] +--innodb-autoinc-lock-mode=0 +[new] +--innodb-autoinc-lock-mode=1 +[none] +--innodb-autoinc-lock-mode=2 diff --git a/mysql-test/suite/innodb/t/auto_increment_lock_mode.test b/mysql-test/suite/innodb/t/auto_increment_lock_mode.test new file mode 100644 index 00000000000..27497960e72 --- /dev/null +++ b/mysql-test/suite/innodb/t/auto_increment_lock_mode.test @@ -0,0 +1,61 @@ +--source include/have_innodb.inc + +CREATE TABLE t1(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t3(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t4(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t5(a TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t6(a SERIAL, b INT) ENGINE=InnoDB; + +DELIMITER $$; +CREATE FUNCTION p1() RETURNS INT +BEGIN + INSERT INTO t1() VALUES(); + INSERT INTO t2() VALUES(); + INSERT INTO t3() VALUES(); + INSERT INTO t4() VALUES(); + INSERT INTO t5() VALUES(); + RETURN 1; +END$$ +DELIMITER ;$$ + +INSERT INTO t6(b) SELECT p1(); + +UPDATE t1,t2,t3,t4,t5 SET t1.a=2,t2.a=2,t3.a=2,t4.a=2,t5.a=2; +SELECT * FROM t1; +--source include/count_sessions.inc + +--connect(con1,localhost,root,,) +let $ID1= `SELECT @id := CONNECTION_ID()`; +--connect(con2,localhost,root,,) +let $ID2= `SELECT @id := CONNECTION_ID()`; +--connect(con3,localhost,root,,) +let $ID3= `SELECT @id := CONNECTION_ID()`; +--connection con1 +send INSERT INTO t6(b) SELECT SLEEP(p1()); +--connection con2 +send INSERT INTO t6(b) SELECT SLEEP(p1()); +--connection con3 +send UPDATE t1,t2,t3,t4,t5 SET t1.a=0,t2.a=0,t3.a=0,t4.a=0,t5.a=0 +WHERE t1.a=2 AND t2.a=2 AND t3.a=2 AND t4.a=2 AND t5.a=2; +--connection default +evalp KILL QUERY $ID1; +evalp KILL QUERY $ID2; +evalp KILL QUERY $ID3; +--connection con1 +--error 0,ER_QUERY_INTERRUPTED,ER_AUTOINC_READ_FAILED +--reap +--disconnect con1 +--connection con2 +--error 0,ER_QUERY_INTERRUPTED,ER_AUTOINC_READ_FAILED +--reap +--disconnect con2 +--connection con3 +--error 0,ER_QUERY_INTERRUPTED,ER_AUTOINC_READ_FAILED +--reap +--disconnect con3 +--connection default + +DROP FUNCTION p1; +DROP TABLE t1,t2,t3,t4,t5,t6; +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/innodb-autoinc-56228.test b/mysql-test/suite/innodb/t/innodb-autoinc-56228.test index a02f7b4383a..e1d8741c730 100644 --- a/mysql-test/suite/innodb/t/innodb-autoinc-56228.test +++ b/mysql-test/suite/innodb/t/innodb-autoinc-56228.test @@ -2,33 +2,45 @@ ## # Bug #56228: dropping tables from within an active statement crashes server # -DROP TABLE IF EXISTS t1_56228; -DROP TABLE IF EXISTS t2_56228; -DROP FUNCTION IF EXISTS bug56228; -CREATE TEMPORARY TABLE t1_56228( +# This test used to use TEMPORARY TABLE, which before MySQL 5.7 or +# MariaDB Server 10.2 were covered by InnoDB locks. +# In MariaDB Server 10.6, the locking and logging was corrected for Atomic DDL. +# Hence, even if we tweaked create_table_info_t::innobase_table_flags() +# so that TEMPORARY TABLE are created as persistent tables, +# the DROP TEMPORARY TABLE statement inside the function would +# fail due to HA_ERR_LOCK_WAIT_TIMEOUT, instead of breaking locks +# like it used to do before MDEV-26603 and possibly other changes. +CREATE TABLE t1_56228( c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; -CREATE TEMPORARY TABLE t2_56228( +CREATE TABLE t2_56228( c1 iNT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; DELIMITER //; +--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG CREATE FUNCTION bug56228() RETURNS INT DETERMINISTIC BEGIN INSERT INTO t1_56228 VALUES(NULL); INSERT INTO t2_56228 VALUES(NULL); INSERT INTO t1_56228 VALUES(NULL); INSERT INTO t2_56228 VALUES(NULL); - DROP TEMPORARY TABLE t1_56228; + DROP TABLE t1_56228; RETURN 42; END // +CREATE PROCEDURE bug56228() +BEGIN + INSERT INTO t1_56228 VALUES(NULL); + INSERT INTO t2_56228 VALUES(NULL); + INSERT INTO t1_56228 VALUES(NULL); + INSERT INTO t2_56228 VALUES(NULL); + DROP TABLE t1_56228; +END // + DELIMITER ;// ---disable_ps_protocol -SELECT bug56228(); ---enable_ps2_protocol +CALL bug56228(); -DROP FUNCTION bug56228; -DROP TEMPORARY TABLE t2_56228; -DROP TEMPORARY TABLE IF EXISTS t1_56228; +DROP PROCEDURE bug56228; +DROP TABLE t2_56228; diff --git a/storage/innobase/dict/drop.cc b/storage/innobase/dict/drop.cc index f46b4b04752..80bf8c97ead 100644 --- a/storage/innobase/dict/drop.cc +++ b/storage/innobase/dict/drop.cc @@ -247,7 +247,7 @@ void trx_t::commit(std::vector &deleted) mutex_lock(); lock_release_on_drop(this); ut_ad(UT_LIST_GET_LEN(lock.trx_locks) == 0); - ut_ad(ib_vector_is_empty(autoinc_locks)); + ut_ad(autoinc_locks.empty()); mem_heap_empty(lock.lock_heap); lock.table_locks.clear(); /* commit_persist() already reset this. */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 4fedd79790b..31c4f525adf 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5097,7 +5097,7 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) may be executed as part of a multi-transaction DDL operation, such as rollback_inplace_alter_table() or ha_innobase::delete_table(). */; trx->error_state= DB_INTERRUPTED; - lock_sys_t::cancel(trx, lock); + lock_sys.cancel(trx, lock); } lock_sys.deadlock_check(); } diff --git a/storage/innobase/include/small_vector.h b/storage/innobase/include/small_vector.h index d28a36184b8..2acdc49f668 100644 --- a/storage/innobase/include/small_vector.h +++ b/storage/innobase/include/small_vector.h @@ -31,14 +31,14 @@ protected: small_vector_base()= delete; small_vector_base(void *small, size_t small_size) : BeginX(small), Capacity(Size_T(small_size)) {} - ATTRIBUTE_COLD void grow_by_1(void *small, size_t element_size); + ATTRIBUTE_COLD void grow_by_1(void *small, size_t element_size) noexcept; public: - size_t size() const { return Size; } - size_t capacity() const { return Capacity; } - bool empty() const { return !Size; } - void clear() { Size= 0; } + size_t size() const noexcept { return Size; } + size_t capacity() const noexcept { return Capacity; } + bool empty() const noexcept { return !Size; } + void clear() noexcept { Size= 0; } protected: - void set_size(size_t N) { Size= Size_T(N); } + void set_size(size_t N) noexcept { Size= Size_T(N); } }; template @@ -49,7 +49,7 @@ class small_vector : public small_vector_base using small_vector_base::set_size; - void grow_if_needed() + void grow_if_needed() noexcept { if (unlikely(size() >= capacity())) grow_by_1(small, sizeof *small); @@ -60,38 +60,67 @@ public: { TRASH_ALLOC(small, sizeof small); } - ~small_vector() + ~small_vector() noexcept { if (small != begin()) my_free(begin()); MEM_MAKE_ADDRESSABLE(small, sizeof small); } + void fake_defined() const noexcept + { + ut_ad(empty()); + MEM_MAKE_DEFINED(small, sizeof small); + } + void make_undefined() const noexcept { MEM_UNDEFINED(small, sizeof small); } + + bool is_small() const noexcept { return small == BeginX; } + + void deep_clear() noexcept + { + if (!is_small()) + { + my_free(BeginX); + BeginX= small; + Capacity= N; + } + ut_ad(capacity() == N); + set_size(0); + } + using iterator= T *; using const_iterator= const T *; using reverse_iterator= std::reverse_iterator; using reference= T &; using const_reference= const T&; - iterator begin() { return static_cast(BeginX); } - const_iterator begin() const { return static_cast(BeginX); } - iterator end() { return begin() + size(); } - const_iterator end() const { return begin() + size(); } + iterator begin() noexcept { return static_cast(BeginX); } + const_iterator begin() const noexcept + { return static_cast(BeginX); } + iterator end() noexcept { return begin() + size(); } + const_iterator end() const noexcept { return begin() + size(); } - reverse_iterator rbegin() { return reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } + reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } + reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - reference operator[](size_t i) { assert(i < size()); return begin()[i]; } - const_reference operator[](size_t i) const + reference operator[](size_t i) noexcept + { assert(i < size()); return begin()[i]; } + const_reference operator[](size_t i) const noexcept { return const_cast(*this)[i]; } - void erase(const_iterator S, const_iterator E) + void erase(const_iterator S, const_iterator E) noexcept { set_size(std::move(const_cast(E), end(), const_cast(S)) - begin()); } - void emplace_back(T &&arg) + void emplace_back(T &&arg) noexcept + { + grow_if_needed(); + ::new (end()) T(arg); + set_size(size() + 1); + } + void emplace_back(T &arg) noexcept { grow_if_needed(); ::new (end()) T(arg); diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 9a1c5edd43f..d79aafb1ced 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -32,10 +32,10 @@ Created 3/26/1996 Heikki Tuuri #include "que0types.h" #include "mem0mem.h" #include "trx0xa.h" -#include "ut0vec.h" #include "fts0fts.h" #include "read0types.h" #include "ilist.h" +#include "small_vector.h" #include @@ -857,12 +857,10 @@ public: ulint n_autoinc_rows; /*!< no. of AUTO-INC rows required for an SQL statement. This is useful for multi-row INSERTs */ - ib_vector_t* autoinc_locks; /* AUTOINC locks held by this - transaction. Note that these are - also in the lock list trx_locks. This - vector needs to be freed explicitly - when the trx instance is destroyed. - Protected by lock_sys.latch. */ + typedef small_vector autoinc_lock_vector; + /** AUTO_INCREMENT locks held by this transaction; a subset of trx_locks, + protected by lock_sys.latch. */ + autoinc_lock_vector autoinc_locks; /*------------------------------*/ bool read_only; /*!< true if transaction is flagged as a READ-ONLY transaction. @@ -1059,7 +1057,7 @@ public: ut_ad(!lock.wait_lock); ut_ad(UT_LIST_GET_LEN(lock.trx_locks) == 0); ut_ad(lock.table_locks.empty()); - ut_ad(!autoinc_locks || ib_vector_is_empty(autoinc_locks)); + ut_ad(autoinc_locks.empty()); ut_ad(UT_LIST_GET_LEN(lock.evicted_tables) == 0); ut_ad(!dict_operation); ut_ad(!apply_online_log); diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 5a6857678fc..5e6ed1502af 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -2302,7 +2302,7 @@ static void lock_grant(lock_t *lock) dict_table_t *table= lock->un_member.tab_lock.table; ut_ad(!table->autoinc_trx); table->autoinc_trx= trx; - ib_vector_push(trx->autoinc_locks, &lock); + trx->autoinc_locks.emplace_back(lock); } DBUG_PRINT("ib_lock", ("wait for trx " TRX_ID_FMT " ends", trx->id)); @@ -3646,7 +3646,7 @@ lock_t *lock_table_create(dict_table_t *table, unsigned type_mode, trx_t *trx, ut_ad(!table->autoinc_trx); table->autoinc_trx = trx; - ib_vector_push(trx->autoinc_locks, &lock); + trx->autoinc_locks.emplace_back(lock); goto allocated; } @@ -3695,79 +3695,45 @@ allocated: return(lock); } -/*************************************************************//** -Pops autoinc lock requests from the transaction's autoinc_locks. We -handle the case where there are gaps in the array and they need to -be popped off the stack. */ -UNIV_INLINE -void -lock_table_pop_autoinc_locks( -/*=========================*/ - trx_t* trx) /*!< in/out: transaction that owns the AUTOINC locks */ +/** Release a granted AUTO_INCREMENT lock. +@param lock AUTO_INCREMENT lock +@param trx transaction that owns the lock */ +static void lock_table_remove_autoinc_lock(lock_t *lock, trx_t *trx) noexcept { - ut_ad(!ib_vector_is_empty(trx->autoinc_locks)); + ut_ad(lock->type_mode == (LOCK_AUTO_INC | LOCK_TABLE)); + lock_sys.assert_locked(*lock->un_member.tab_lock.table); + ut_ad(trx->mutex_is_owner()); - /* Skip any gaps, gaps are NULL lock entries in the - trx->autoinc_locks vector. */ + auto begin= trx->autoinc_locks.begin(), end= trx->autoinc_locks.end(), i=end; + ut_ad(begin != end); + if (*--i == lock) + { + /* Normally, the last acquired lock is released first, in order to + avoid unnecessary traversal of trx->autoinc_locks, which + only stores granted locks. */ - do { - ib_vector_pop(trx->autoinc_locks); + /* We remove the last lock, as well as any nullptr entries + immediately preceding it, which might have been created by the + "else" branch below, or by lock_cancel_waiting_and_release(). */ + while (begin != i && !i[-1]) i--; + trx->autoinc_locks.erase(i, end); + } + else + { + ut_a(*i); + /* Clear the lock when it is not the last one. */ + while (begin != i) + { + if (*--i == lock) + { + *i= nullptr; + return; + } + } - if (ib_vector_is_empty(trx->autoinc_locks)) { - return; - } - - } while (*(lock_t**) ib_vector_get_last(trx->autoinc_locks) == NULL); -} - -/*************************************************************//** -Removes an autoinc lock request from the transaction's autoinc_locks. */ -UNIV_INLINE -void -lock_table_remove_autoinc_lock( -/*===========================*/ - lock_t* lock, /*!< in: table lock */ - trx_t* trx) /*!< in/out: transaction that owns the lock */ -{ - ut_ad(lock->type_mode == (LOCK_AUTO_INC | LOCK_TABLE)); - lock_sys.assert_locked(*lock->un_member.tab_lock.table); - ut_ad(trx->mutex_is_owner()); - - auto s = ib_vector_size(trx->autoinc_locks); - ut_ad(s); - - /* With stored functions and procedures the user may drop - a table within the same "statement". This special case has - to be handled by deleting only those AUTOINC locks that were - held by the table being dropped. */ - - lock_t* autoinc_lock = *static_cast( - ib_vector_get(trx->autoinc_locks, --s)); - - /* This is the default fast case. */ - - if (autoinc_lock == lock) { - lock_table_pop_autoinc_locks(trx); - } else { - /* The last element should never be NULL */ - ut_a(autoinc_lock != NULL); - - /* Handle freeing the locks from within the stack. */ - - while (s) { - autoinc_lock = *static_cast( - ib_vector_get(trx->autoinc_locks, --s)); - - if (autoinc_lock == lock) { - void* null_var = NULL; - ib_vector_set(trx->autoinc_locks, s, &null_var); - return; - } - } - - /* Must find the autoinc lock. */ - ut_error; - } + /* The lock must exist. */ + ut_error; + } } /*************************************************************//** @@ -3799,14 +3765,7 @@ lock_table_remove_low( ut_ad((table->autoinc_trx == trx) == !lock->is_waiting()); if (table->autoinc_trx == trx) { - table->autoinc_trx = NULL; - /* The locks must be freed in the reverse order from - the one in which they were acquired. This is to avoid - traversing the AUTOINC lock vector unnecessarily. - - We only store locks that were granted in the - trx->autoinc_locks vector (see lock_table_create() - and lock_grant()). */ + table->autoinc_trx = nullptr; lock_table_remove_autoinc_lock(lock, trx); } @@ -6443,44 +6402,31 @@ lock_clust_rec_read_check_and_lock_alt( return(err); } -/*******************************************************************//** -Check if a transaction holds any autoinc locks. -@return TRUE if the transaction holds any AUTOINC locks. */ -static -ibool -lock_trx_holds_autoinc_locks( -/*=========================*/ - const trx_t* trx) /*!< in: transaction */ -{ - ut_a(trx->autoinc_locks != NULL); - - return(!ib_vector_is_empty(trx->autoinc_locks)); -} - /** Release all AUTO_INCREMENT locks of the transaction. */ static void lock_release_autoinc_locks(trx_t *trx) { { + auto begin= trx->autoinc_locks.begin(), end= trx->autoinc_locks.end(); + ut_ad(begin != end); LockMutexGuard g{SRW_LOCK_CALL}; mysql_mutex_lock(&lock_sys.wait_mutex); trx->mutex_lock(); - auto autoinc_locks= trx->autoinc_locks; - ut_a(autoinc_locks); /* We release the locks in the reverse order. This is to avoid searching the vector for the element to delete at the lower level. See (lock_table_remove_low()) for details. */ - while (ulint size= ib_vector_size(autoinc_locks)) + do { - lock_t *lock= *static_cast - (ib_vector_get(autoinc_locks, size - 1)); + lock_t *lock= *--end; ut_ad(lock->type_mode == (LOCK_AUTO_INC | LOCK_TABLE)); lock_table_dequeue(lock, true); lock_trx_table_locks_remove(lock); } + while (begin != end); } mysql_mutex_unlock(&lock_sys.wait_mutex); trx->mutex_unlock(); + trx->autoinc_locks.clear(); } /** Cancel a waiting lock request and release possibly waiting transactions */ @@ -6502,8 +6448,18 @@ void lock_cancel_waiting_and_release(lock_t *lock) { if (lock->type_mode == (LOCK_AUTO_INC | LOCK_TABLE)) { - ut_ad(trx->autoinc_locks); - ib_vector_remove(trx->autoinc_locks, lock); + /* This is similar to lock_table_remove_autoinc_lock() */ + auto begin= trx->autoinc_locks.begin(), end= trx->autoinc_locks.end(); + ut_ad(begin != end); + if (*--end == lock) + trx->autoinc_locks.erase(end, end + 1); + else + while (begin != end) + if (*--end == lock) + { + *end= nullptr; + break; + } } lock_table_dequeue(lock, true); /* Remove the lock from table lock vector too. */ @@ -6703,7 +6659,7 @@ lock_unlock_table_autoinc( ut_ad(trx_state == TRX_STATE_ACTIVE || trx_state == TRX_STATE_PREPARED || trx_state == TRX_STATE_NOT_STARTED); - if (lock_trx_holds_autoinc_locks(trx)) + if (!trx->autoinc_locks.empty()) lock_release_autoinc_locks(trx); } diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index bd0ef0eee1b..d8f694d80f0 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -1268,14 +1268,14 @@ void mtr_t::free(const fil_space_t &space, uint32_t offset) m_log.close(log_write(id, nullptr)); } -void small_vector_base::grow_by_1(void *small, size_t element_size) +void small_vector_base::grow_by_1(void *small, size_t element_size) noexcept { const size_t cap= Capacity*= 2, s= cap * element_size; void *new_begin; if (BeginX == small) { new_begin= my_malloc(PSI_NOT_INSTRUMENTED, s, MYF(0)); - memcpy(new_begin, BeginX, size() * element_size); + memcpy(new_begin, BeginX, s / 2); TRASH_FREE(small, size() * element_size); } else diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 7935cdb6bc6..ade8dea929a 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -170,6 +170,8 @@ struct TrxFactory { allocated object. trx_t objects are allocated by ut_zalloc_nokey() in Pool::Pool() which would not call the constructors of the trx_t members. */ + new(&trx->autoinc_locks) trx_t::autoinc_lock_vector(); + new(&trx->mod_tables) trx_mod_tables_t(); new(&trx->lock.table_locks) lock_list(); @@ -232,6 +234,8 @@ struct TrxFactory { trx->mutex_destroy(); + trx->autoinc_locks.~small_vector(); + trx->mod_tables.~trx_mod_tables_t(); ut_ad(!trx->read_view.is_open()); @@ -334,21 +338,12 @@ trx_t *trx_create() trx->assert_freed(); - mem_heap_t* heap; - ib_alloc_t* alloc; - /* We just got trx from pool, it should be non locking */ ut_ad(!trx->will_lock); ut_ad(!trx->rw_trx_hash_pins); DBUG_LOG("trx", "Create: " << trx); - heap = mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 8); - - alloc = ib_heap_allocator_create(heap); - - trx->autoinc_locks = ib_vector_create(alloc, sizeof(void**), 4); - ut_ad(trx->mod_tables.empty()); ut_ad(trx->lock.n_rec_locks == 0); ut_ad(trx->lock.set_nth_bit_calls == 0); @@ -364,6 +359,7 @@ trx_t *trx_create() /** Free the memory to trx_pools */ void trx_t::free() { + autoinc_locks.fake_defined(); #ifdef HAVE_MEM_CHECK if (xid.is_null()) MEM_MAKE_DEFINED(&xid, sizeof xid); @@ -372,6 +368,7 @@ void trx_t::free() sizeof xid.data - (xid.gtrid_length + xid.bqual_length)); #endif MEM_CHECK_DEFINED(this, sizeof *this); + autoinc_locks.make_undefined(); ut_ad(!n_mysql_tables_in_use); ut_ad(!mysql_log_file_name); @@ -390,14 +387,7 @@ void trx_t::free() trx_sys.rw_trx_hash.put_pins(this); mysql_thd= nullptr; - // FIXME: We need to avoid this heap free/alloc for each commit. - if (autoinc_locks) - { - ut_ad(ib_vector_is_empty(autoinc_locks)); - /* We allocated a dedicated heap for the vector. */ - ib_vector_free(autoinc_locks); - autoinc_locks= NULL; - } + autoinc_locks.deep_clear(); MEM_NOACCESS(&skip_lock_inheritance_and_n_ref, sizeof skip_lock_inheritance_and_n_ref); @@ -495,7 +485,7 @@ inline void trx_t::release_locks() lock_release(this); ut_ad(!lock.n_rec_locks); ut_ad(UT_LIST_GET_LEN(lock.trx_locks) == 0); - ut_ad(ib_vector_is_empty(autoinc_locks)); + ut_ad(autoinc_locks.empty()); mem_heap_empty(lock.lock_heap); } @@ -923,7 +913,7 @@ trx_start_low( trx->wsrep = wsrep_on(trx->mysql_thd); #endif /* WITH_WSREP */ - ut_a(ib_vector_is_empty(trx->autoinc_locks)); + ut_a(trx->autoinc_locks.empty()); ut_a(trx->lock.table_locks.empty()); /* No other thread can access this trx object through rw_trx_hash, From 0abef37ccdba25a4a1e8e3209abd2be64ff1f19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 15 Jan 2025 16:55:29 +0200 Subject: [PATCH 036/118] Minor lock_sys cleanup Let us make some member functions of lock_sys_t non-static to avoid some shuffling of function parameter registers. lock_cancel_waiting_and_release(): Declare static, because there are no external callers. Reviewed by: Debarun Banerjee --- storage/innobase/include/lock0lock.h | 4 +- storage/innobase/lock/lock0lock.cc | 80 ++++++++++++++-------------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index c996e5f8227..a604b5ef7b5 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -869,7 +869,7 @@ public: @retval DB_DEADLOCK if trx->lock.was_chosen_as_deadlock_victim was set @retval DB_LOCK_WAIT if the lock was canceled */ template - static dberr_t cancel(trx_t *trx, lock_t *lock); + dberr_t cancel(trx_t *trx, lock_t *lock) noexcept; /** Note that a record lock wait started */ inline void wait_start(); @@ -924,7 +924,7 @@ public: void prdt_page_free_from_discard(const page_id_t id, bool all= false); /** Cancel possible lock waiting for a transaction */ - static void cancel_lock_wait_for_trx(trx_t *trx); + inline void cancel_lock_wait_for_trx(trx_t *trx) noexcept; #ifdef WITH_WSREP /** Cancel lock waiting for a wsrep BF abort. */ static void cancel_lock_wait_for_wsrep_bf_abort(trx_t *trx); diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 5e6ed1502af..94eeef57bd7 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -2232,7 +2232,7 @@ end_loop: if (wait_lock) { abort_wait: - lock_sys_t::cancel(trx, wait_lock); + lock_sys.cancel(trx, wait_lock); lock_sys.deadlock_check(); } @@ -6431,7 +6431,7 @@ static void lock_release_autoinc_locks(trx_t *trx) /** Cancel a waiting lock request and release possibly waiting transactions */ template -void lock_cancel_waiting_and_release(lock_t *lock) +static void lock_cancel_waiting_and_release(lock_t *lock) noexcept { lock_sys.assert_locked(*lock); mysql_mutex_assert_owner(&lock_sys.wait_mutex); @@ -6475,18 +6475,18 @@ void lock_cancel_waiting_and_release(lock_t *lock) trx->mutex_unlock(); } -void lock_sys_t::cancel_lock_wait_for_trx(trx_t *trx) +inline void lock_sys_t::cancel_lock_wait_for_trx(trx_t *trx) noexcept { - lock_sys.wr_lock(SRW_LOCK_CALL); - mysql_mutex_lock(&lock_sys.wait_mutex); + wr_lock(SRW_LOCK_CALL); + mysql_mutex_lock(&wait_mutex); if (lock_t *lock= trx->lock.wait_lock) { /* check if victim is still waiting */ if (lock->is_waiting()) lock_cancel_waiting_and_release(lock); } - lock_sys.wr_unlock(); - mysql_mutex_unlock(&lock_sys.wait_mutex); + wr_unlock(); + mysql_mutex_unlock(&wait_mutex); } #ifdef WITH_WSREP @@ -6510,10 +6510,10 @@ void lock_sys_t::cancel_lock_wait_for_wsrep_bf_abort(trx_t *trx) @retval DB_DEADLOCK if trx->lock.was_chosen_as_deadlock_victim was set @retval DB_LOCK_WAIT if the lock was canceled */ template -dberr_t lock_sys_t::cancel(trx_t *trx, lock_t *lock) +dberr_t lock_sys_t::cancel(trx_t *trx, lock_t *lock) noexcept { DEBUG_SYNC_C("lock_sys_t_cancel_enter"); - mysql_mutex_assert_owner(&lock_sys.wait_mutex); + mysql_mutex_assert_owner(&wait_mutex); ut_ad(trx->state == TRX_STATE_ACTIVE); /* trx->lock.wait_lock may be changed by other threads as long as we are not holding lock_sys.latch. @@ -6521,27 +6521,27 @@ dberr_t lock_sys_t::cancel(trx_t *trx, lock_t *lock) So, trx->lock.wait_lock==lock does not necessarily hold, but both pointers should be valid, because other threads cannot assign trx->lock.wait_lock=nullptr (or invalidate *lock) while we are - holding lock_sys.wait_mutex. Also, the type of trx->lock.wait_lock + holding wait_mutex. Also, the type of trx->lock.wait_lock (record or table lock) cannot be changed by other threads. So, it is - safe to call lock->is_table() while not holding lock_sys.latch. If - we have to release and reacquire lock_sys.wait_mutex, we must reread + safe to call lock->is_table() while not holding latch. If + we have to release and reacquire wait_mutex, we must reread trx->lock.wait_lock. We must also reread trx->lock.wait_lock after - lock_sys.latch acquiring, as it can be changed to not-null in lock moving - functions even if we hold lock_sys.wait_mutex. */ + latch acquiring, as it can be changed to not-null in lock moving + functions even if we hold wait_mutex. */ dberr_t err= DB_SUCCESS; /* This would be too large for a memory transaction, except in the DB_DEADLOCK case, which was already tested in lock_trx_handle_wait(). */ if (lock->is_table()) { - if (!lock_sys.rd_lock_try()) + if (!rd_lock_try()) { - mysql_mutex_unlock(&lock_sys.wait_mutex); - lock_sys.rd_lock(SRW_LOCK_CALL); - mysql_mutex_lock(&lock_sys.wait_mutex); + mysql_mutex_unlock(&wait_mutex); + rd_lock(SRW_LOCK_CALL); + mysql_mutex_lock(&wait_mutex); lock= trx->lock.wait_lock; - /* Even if waiting lock was cancelled while lock_sys.wait_mutex was - unlocked, we need to return deadlock error if transaction was chosen - as deadlock victim to rollback it */ + /* Even if the waiting lock was cancelled while we did not hold + wait_mutex, we need to return deadlock error if the transaction + was chosen as deadlock victim to be rolled back. */ if (check_victim && trx->lock.was_chosen_as_deadlock_victim) err= DB_DEADLOCK; else if (lock) @@ -6552,10 +6552,10 @@ dberr_t lock_sys_t::cancel(trx_t *trx, lock_t *lock) /* This function is invoked from the thread which executes the transaction. Table locks are requested before record locks. Some other transaction can't change trx->lock.wait_lock from table to record for the - current transaction at this point, because the current transaction has not - requested record locks yet. There is no need to move any table locks by - other threads. And trx->lock.wait_lock can't be set to null while we are - holding lock_sys.wait_mutex. That's why there is no need to reload + current transaction at this point, because the current transaction has + not requested record locks yet. There is no need to move any table locks + by other threads. And trx->lock.wait_lock can't be set to null while we + are holding wait_mutex. That's why there is no need to reload trx->lock.wait_lock here. */ ut_ad(lock == trx->lock.wait_lock); resolve_table_lock: @@ -6563,11 +6563,11 @@ resolve_table_lock: if (!table->lock_mutex_trylock()) { /* The correct latching order is: - lock_sys.latch, table->lock_latch, lock_sys.wait_mutex. - Thus, we must release lock_sys.wait_mutex for a blocking wait. */ - mysql_mutex_unlock(&lock_sys.wait_mutex); + latch, table->lock_latch, wait_mutex. + Thus, we must release wait_mutex for a blocking wait. */ + mysql_mutex_unlock(&wait_mutex); table->lock_mutex_lock(); - mysql_mutex_lock(&lock_sys.wait_mutex); + mysql_mutex_lock(&wait_mutex); /* Cache trx->lock.wait_lock under the corresponding latches. */ lock= trx->lock.wait_lock; if (!lock) @@ -6594,20 +6594,20 @@ resolve_table_lock: retreat: table->lock_mutex_unlock(); } - lock_sys.rd_unlock(); + rd_unlock(); } else { /* To prevent the record lock from being moved between pages - during a page split or merge, we must hold exclusive lock_sys.latch. */ - if (!lock_sys.wr_lock_try()) + during a page split or merge, we must hold exclusive latch. */ + if (!wr_lock_try()) { - mysql_mutex_unlock(&lock_sys.wait_mutex); - lock_sys.wr_lock(SRW_LOCK_CALL); - mysql_mutex_lock(&lock_sys.wait_mutex); + mysql_mutex_unlock(&wait_mutex); + wr_lock(SRW_LOCK_CALL); + mysql_mutex_lock(&wait_mutex); /* Cache trx->lock.wait_lock under the corresponding latches. */ lock= trx->lock.wait_lock; - /* Even if waiting lock was cancelled while lock_sys.wait_mutex was + /* Even if waiting lock was cancelled while wait_mutex was unlocked, we need to return deadlock error if transaction was chosen as deadlock victim to rollback it */ if (check_victim && trx->lock.was_chosen_as_deadlock_victim) @@ -6631,13 +6631,13 @@ resolve_record_lock: rpl.rpl_parallel_optimistic_xa_lsu_off */ err= DB_LOCK_WAIT; } - lock_sys.wr_unlock(); + wr_unlock(); } return err; } -template dberr_t lock_sys_t::cancel(trx_t *, lock_t *); +template dberr_t lock_sys_t::cancel(trx_t *, lock_t *) noexcept; /*********************************************************************//** Unlocks AUTO_INC type locks that were possibly reserved by a trx. This @@ -6689,7 +6689,7 @@ dberr_t lock_trx_handle_wait(trx_t *trx) err= DB_DEADLOCK; /* Cache trx->lock.wait_lock to avoid unnecessary atomic variable load */ else if (lock_t *wait_lock= trx->lock.wait_lock) - err= lock_sys_t::cancel(trx, wait_lock); + err= lock_sys.cancel(trx, wait_lock); lock_sys.deadlock_check(); mysql_mutex_unlock(&lock_sys.wait_mutex); return err; @@ -7153,7 +7153,7 @@ static lock_t *Deadlock::check_and_resolve(trx_t *trx, lock_t *wait_lock) return wait_lock; if (wait_lock) - lock_sys_t::cancel(trx, wait_lock); + lock_sys.cancel(trx, wait_lock); lock_sys.deadlock_check(); return reinterpret_cast(-1); From 78157c4765f2c086fabe183d51d7734ecffdbdd8 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 14 Jan 2025 17:47:08 +1100 Subject: [PATCH 037/118] MDEV-35840 Eliminate -warray-bounds triggered by TABLE_SHARE::db_type() The warnings are triggered with -O3 --- sql/sql_base.cc | 3 ++- sql/sql_partition.cc | 27 ++++++++++++++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5c03ba3d42d..aaa86e7bfa0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8953,8 +8953,9 @@ my_bool mysql_rm_tmp_tables(void) memcpy(path_copy, path, path_len - ext_len); path_copy[path_len - ext_len]= 0; init_tmp_table_share(thd, &share, "", 0, "", path_copy); + handlerton *ht= share.db_type(); if (!open_table_def(thd, &share)) - share.db_type()->drop_table(share.db_type(), path_copy); + ht->drop_table(share.db_type(), path_copy); free_table_share(&share); } /* diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 6228991d46c..e17f6e5a00a 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -721,9 +721,11 @@ static bool handle_list_of_fields(THD *thd, List_iterator it, } else { - if (table->s->db_type()->partition_flags && - (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION) && - (table->s->db_type()->partition_flags() & HA_CAN_PARTITION)) + handlerton *ht= table->s->db_type(); + if (ht->partition_flags && + ((ht->partition_flags() & + (HA_USE_AUTO_PARTITION | HA_CAN_PARTITION)) == + (HA_USE_AUTO_PARTITION | HA_CAN_PARTITION))) { /* This engine can handle automatic partitioning and there is no @@ -1927,6 +1929,7 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) bool result= TRUE; partition_info *part_info= table->part_info; enum_column_usage saved_column_usage= thd->column_usage; + handlerton *ht; DBUG_ENTER("fix_partition_func"); if (part_info->fixed) @@ -2056,8 +2059,9 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) goto end; if (unlikely(check_primary_key(table))) goto end; - if (unlikely((!(table->s->db_type()->partition_flags && - (table->s->db_type()->partition_flags() & HA_CAN_PARTITION_UNIQUE))) && + ht= table->s->db_type(); + if (unlikely((!(ht->partition_flags && + (ht->partition_flags() & HA_CAN_PARTITION_UNIQUE))) && check_unique_keys(table))) goto end; if (unlikely(set_up_partition_bitmaps(thd, part_info))) @@ -2713,12 +2717,14 @@ bool partition_key_modified(TABLE *table, const MY_BITMAP *fields) { Field **fld; partition_info *part_info= table->part_info; + handlerton *ht; DBUG_ENTER("partition_key_modified"); if (!part_info) DBUG_RETURN(FALSE); - if (table->s->db_type()->partition_flags && - (table->s->db_type()->partition_flags() & HA_CAN_UPDATE_PARTITION_KEY)) + ht= table->s->db_type(); + if (ht->partition_flags && + (ht->partition_flags() & HA_CAN_UPDATE_PARTITION_KEY)) DBUG_RETURN(FALSE); for (fld= part_info->full_part_field_array; *fld; fld++) if (bitmap_is_set(fields, (*fld)->field_index)) @@ -4927,11 +4933,10 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, if default partitioning is used. */ + handlerton *ht= table->s->db_type(); if (tab_part_info->part_type != HASH_PARTITION || - ((table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION) && - !tab_part_info->use_default_num_partitions) || - ((!(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)) && - tab_part_info->use_default_num_partitions)) + !(ht->partition_flags() & HA_USE_AUTO_PARTITION) == + tab_part_info->use_default_num_partitions) { my_error(ER_REORG_NO_PARAM_ERROR, MYF(0)); goto err; From a6ab0e6c0be218761e4dadf8959c7f42e5fea762 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 16 Jan 2025 18:14:26 +0530 Subject: [PATCH 038/118] MDEV-34898 Doublewrite recovery of innodb_checksum_algorithm=full_crc32 encrypted pages does not work - Use file_key_management encryption plugin instead of example_key_management_plugin for the encryption.doublewrite_debug test case --- mysql-test/suite/encryption/t/doublewrite_debug.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/encryption/t/doublewrite_debug.test b/mysql-test/suite/encryption/t/doublewrite_debug.test index 4dc6032c902..761f9cd3e47 100644 --- a/mysql-test/suite/encryption/t/doublewrite_debug.test +++ b/mysql-test/suite/encryption/t/doublewrite_debug.test @@ -1,7 +1,7 @@ --source include/have_innodb.inc --source include/have_debug.inc --source include/not_embedded.inc ---source include/have_example_key_management_plugin.inc +--source include/have_file_key_management_plugin.inc call mtr.add_suppression("InnoDB: Encrypted page \\[page id: space=[1-9][0-9]*, page number=3\\] in file .*test.t[12]\\.ibd looks corrupted"); call mtr.add_suppression("InnoDB: Unable to apply log to corrupted page "); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); From 86b257f8705031730f011998a7e664cf981b39b6 Mon Sep 17 00:00:00 2001 From: Dave Gosselin Date: Thu, 16 Jan 2025 10:35:44 -0500 Subject: [PATCH 039/118] MDEV-35632 HandlerSocket uses deprecated C++98 auto_ptr Change uses of auto_ptr to unique_ptr --- plugin/handler_socket/client/hslongrun.cpp | 4 ++-- plugin/handler_socket/client/hstest.cpp | 4 ++-- plugin/handler_socket/handlersocket/database.cpp | 2 +- plugin/handler_socket/handlersocket/database.hpp | 9 ++------- plugin/handler_socket/handlersocket/handlersocket.cpp | 2 +- plugin/handler_socket/handlersocket/hstcpsvr.cpp | 2 +- plugin/handler_socket/handlersocket/hstcpsvr.hpp | 2 +- plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp | 4 ++-- plugin/handler_socket/handlersocket/hstcpsvr_worker.hpp | 2 +- plugin/handler_socket/libhsclient/hstcpcli.hpp | 7 +------ 10 files changed, 14 insertions(+), 24 deletions(-) diff --git a/plugin/handler_socket/client/hslongrun.cpp b/plugin/handler_socket/client/hslongrun.cpp index b7c02951340..a9fba1dc7c3 100644 --- a/plugin/handler_socket/client/hslongrun.cpp +++ b/plugin/handler_socket/client/hslongrun.cpp @@ -927,7 +927,7 @@ hs_longrun_main(int argc, char **argv) shared.verbose = shared.conf.get_int("verbose", 1); const int table_size = shared.conf.get_int("table_size", 10000); for (int i = 0; i < table_size; ++i) { - std::auto_ptr rec(new record_value()); + std::unique_ptr rec(new record_value()); rec->key = to_stdstring(i); shared.records.push_back_ptr(rec); } @@ -966,7 +966,7 @@ hs_longrun_main(int argc, char **argv) int id = thrs.size(); const hs_longrun_thread_hs::arg_type arg(id, e.type, e.op, e.lock, shared); - std::auto_ptr thr; + std::unique_ptr thr; if (e.hs) { thr.reset(new hs_longrun_thread_hs(arg)); } else { diff --git a/plugin/handler_socket/client/hstest.cpp b/plugin/handler_socket/client/hstest.cpp index b5551fed81c..72e8a225de9 100644 --- a/plugin/handler_socket/client/hstest.cpp +++ b/plugin/handler_socket/client/hstest.cpp @@ -561,7 +561,7 @@ hstest_thread::test_9(int test_num) flds += std::string(buf); } int connected = 0; - std::auto_ptr stmt; + std::unique_ptr stmt; string_buffer wbuf; for (int i = 0; i < num; ++i) { const double tm1 = gettimeofday_double(); @@ -1474,7 +1474,7 @@ hstest_main(int argc, char **argv) #endif const int num_thrs = shared.num_threads; typedef thread thread_type; - typedef std::auto_ptr thread_ptr; + typedef std::unique_ptr thread_ptr; typedef auto_ptrcontainer< std::vector > thrs_type; thrs_type thrs; for (int i = 0; i < num_thrs; ++i) { diff --git a/plugin/handler_socket/handlersocket/database.cpp b/plugin/handler_socket/handlersocket/database.cpp index 0a006a42f00..9441863070c 100644 --- a/plugin/handler_socket/handlersocket/database.cpp +++ b/plugin/handler_socket/handlersocket/database.cpp @@ -175,7 +175,7 @@ struct dbcontext : public dbcontext_i, private noncopyable { THD *thd; MYSQL_LOCK *lock; bool lock_failed; - std::auto_ptr user_lock; + std::unique_ptr user_lock; int user_level_lock_timeout; bool user_level_lock_locked; bool commit_error; diff --git a/plugin/handler_socket/handlersocket/database.hpp b/plugin/handler_socket/handlersocket/database.hpp index 9e2aadf7380..87761050704 100644 --- a/plugin/handler_socket/handlersocket/database.hpp +++ b/plugin/handler_socket/handlersocket/database.hpp @@ -9,11 +9,6 @@ #ifndef DENA_DATABASE_HPP #define DENA_DATABASE_HPP -#ifdef __GNUC__ -/* auto_ptr is deprecated */ -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - #include #include #include @@ -26,10 +21,10 @@ namespace dena { struct database_i; -typedef std::auto_ptr database_ptr; +typedef std::unique_ptr database_ptr; struct dbcontext_i; -typedef std::auto_ptr dbcontext_ptr; +typedef std::unique_ptr dbcontext_ptr; struct database_i { virtual ~database_i() = default; diff --git a/plugin/handler_socket/handlersocket/handlersocket.cpp b/plugin/handler_socket/handlersocket/handlersocket.cpp index 45c9e13b2ca..c513afb7dd5 100644 --- a/plugin/handler_socket/handlersocket/handlersocket.cpp +++ b/plugin/handler_socket/handlersocket/handlersocket.cpp @@ -76,7 +76,7 @@ daemon_handlersocket_init(void *p) conf["readsize"] = to_stdstring(handlersocket_readsize); conf["accept_balance"] = to_stdstring(handlersocket_accept_balance); conf["wrlock_timeout"] = to_stdstring(handlersocket_wrlock_timeout); - std::auto_ptr ap(new daemon_handlersocket_data); + std::unique_ptr ap(new daemon_handlersocket_data); if (handlersocket_port != 0 && handlersocket_port_wr != handlersocket_port) { conf["port"] = handlersocket_port; if (handlersocket_plain_secret) { diff --git a/plugin/handler_socket/handlersocket/hstcpsvr.cpp b/plugin/handler_socket/handlersocket/hstcpsvr.cpp index 336d36422b0..72435b80331 100644 --- a/plugin/handler_socket/handlersocket/hstcpsvr.cpp +++ b/plugin/handler_socket/handlersocket/hstcpsvr.cpp @@ -115,7 +115,7 @@ hstcpsvr::start_listen() arg.cshared = &cshared; arg.vshared = &vshared; arg.worker_id = i; - std::auto_ptr< thread > thr( + std::unique_ptr< thread > thr( new thread(arg, stack_size)); threads.push_back_ptr(thr); } diff --git a/plugin/handler_socket/handlersocket/hstcpsvr.hpp b/plugin/handler_socket/handlersocket/hstcpsvr.hpp index 5fbed92402b..3bb17c9ea0b 100644 --- a/plugin/handler_socket/handlersocket/hstcpsvr.hpp +++ b/plugin/handler_socket/handlersocket/hstcpsvr.hpp @@ -44,7 +44,7 @@ struct hstcpsvr_shared_v : public mutex { }; struct hstcpsvr_i; -typedef std::auto_ptr hstcpsvr_ptr; +typedef std::unique_ptr hstcpsvr_ptr; struct hstcpsvr_i { virtual ~hstcpsvr_i() = default; diff --git a/plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp b/plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp index 0796546cb5e..818d7327896 100644 --- a/plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp +++ b/plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp @@ -451,7 +451,7 @@ hstcpsvr_worker::run_one_nb() { pollfd& pfd = pfds[nfds - 1]; if ((pfd.revents & mask_in) != 0) { - std::auto_ptr c(new hstcpsvr_conn()); + std::unique_ptr c(new hstcpsvr_conn()); c->nonblocking = true; c->readsize = cshared.readsize; c->accept(cshared); @@ -498,7 +498,7 @@ hstcpsvr_worker::run_one_ep() /* listener */ ++accept_count; DBG_EP(fprintf(stderr, "IN listener\n")); - std::auto_ptr c(new hstcpsvr_conn()); + std::unique_ptr c(new hstcpsvr_conn()); c->nonblocking = true; c->readsize = cshared.readsize; c->accept(cshared); diff --git a/plugin/handler_socket/handlersocket/hstcpsvr_worker.hpp b/plugin/handler_socket/handlersocket/hstcpsvr_worker.hpp index 25612adec0f..2a2a5083e31 100644 --- a/plugin/handler_socket/handlersocket/hstcpsvr_worker.hpp +++ b/plugin/handler_socket/handlersocket/hstcpsvr_worker.hpp @@ -14,7 +14,7 @@ namespace dena { struct hstcpsvr_worker_i; -typedef std::auto_ptr hstcpsvr_worker_ptr; +typedef std::unique_ptr hstcpsvr_worker_ptr; struct hstcpsvr_worker_arg { const hstcpsvr_shared_c *cshared; diff --git a/plugin/handler_socket/libhsclient/hstcpcli.hpp b/plugin/handler_socket/libhsclient/hstcpcli.hpp index d078bdfd533..3428c2f240e 100644 --- a/plugin/handler_socket/libhsclient/hstcpcli.hpp +++ b/plugin/handler_socket/libhsclient/hstcpcli.hpp @@ -19,11 +19,6 @@ #include "string_ref.hpp" #include "string_buffer.hpp" -#ifdef __GNUC__ -/* auto_ptr is deprecated */ -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - namespace dena { struct hstcpcli_filter { @@ -35,7 +30,7 @@ struct hstcpcli_filter { }; struct hstcpcli_i; -typedef std::auto_ptr hstcpcli_ptr; +typedef std::unique_ptr hstcpcli_ptr; struct hstcpcli_i { virtual ~hstcpcli_i() = default; From df602ff7fa5ed9424a1d7ebaba67b665e2f6d1f6 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 16 Jan 2025 23:04:59 +0100 Subject: [PATCH 040/118] Fix main.stack on Windows A part of the test, that tests that a frame of recursive SP takes the same amount of stack, relies on the fact that 3 calls to that SP are executed in the same OS thread. This is not guaranteed with threadpool(not with Windows native threadpool, anyway) Fix the test to execute SP calls in the same thread, as semicolon-separated batched command. --- mysql-test/main/stack.result | 1 + mysql-test/main/stack.test | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/stack.result b/mysql-test/main/stack.result index 5444381327d..d30a55cd21a 100644 --- a/mysql-test/main/stack.result +++ b/mysql-test/main/stack.result @@ -37,6 +37,7 @@ $$ call recursion(0,2,@s1); call recursion(0,3,@s2); call recursion(0,4,@s3); +$$ select @s1 > 0 && @s2 > 0 && @s3 > 0; @s1 > 0 && @s2 > 0 && @s3 > 0 1 diff --git a/mysql-test/main/stack.test b/mysql-test/main/stack.test index 2277b0f48ff..8884ad45572 100644 --- a/mysql-test/main/stack.test +++ b/mysql-test/main/stack.test @@ -40,11 +40,13 @@ begin end; $$ -delimiter ;$$ - call recursion(0,2,@s1); call recursion(0,3,@s2); call recursion(0,4,@s3); +$$ + +delimiter ;$$ + select @s1 > 0 && @s2 > 0 && @s3 > 0; if (`select @s2-@s1 <> @s3 - @s2`) From c69fb1a6273f759ad8afb4d6466aca5524df9e2f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 17 Jan 2025 13:28:02 +0400 Subject: [PATCH 041/118] MDEV-35864 UBSAN: "applying zero offset to null pointer" when using a Field_set with empty values The val_buffer variable can come to Field_set::val_str() with the Ptr member equal to nullptr. This caused UBSAN errors "applying zero offset to null pointer" in my_strnncollsp_simple() and other strnncollsp() virtual implementations. Fixing the code to make sure its Ptr is not equal to nullptr. --- mysql-test/main/type_set.result | 12 ++++++++++++ mysql-test/main/type_set.test | 12 ++++++++++++ sql/field.cc | 3 +-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/type_set.result b/mysql-test/main/type_set.result index da1e579487d..428618c9efd 100644 --- a/mysql-test/main/type_set.result +++ b/mysql-test/main/type_set.result @@ -660,3 +660,15 @@ Note 1105 Cannot use key parts with `test`.`t1`.`indexed_col` in the rewritten c DROP TABLE t2; DROP TABLE t1; SET note_verbosity=DEFAULT; +# +# MDEV-35864 UBSAN: "applying zero offset to null pointer" when using a Field_set with empty values +# +SET sql_mode=''; +CREATE OR REPLACE TABLE t (c SET('','','') KEY,c2 DECIMAL UNSIGNED ZEROFILL,c3 CHAR(1) BINARY) ENGINE=MyISAM; +Warnings: +Note 1291 Column 'c' has duplicated value '' in SET +Note 1291 Column 'c' has duplicated value '' in SET +INSERT INTO t VALUES ('',CURRENT_TIME,''); +UPDATE t SET c2=c2+5 WHERE c BETWEEN '' AND ''; +DROP TABLE t; +SET sql_mode=DEFAULT; diff --git a/mysql-test/main/type_set.test b/mysql-test/main/type_set.test index df29364f551..60427c35c01 100644 --- a/mysql-test/main/type_set.test +++ b/mysql-test/main/type_set.test @@ -291,3 +291,15 @@ DELIMITER ;$$ --source unusable_keys_joins.inc DROP TABLE t1; SET note_verbosity=DEFAULT; + + +--echo # +--echo # MDEV-35864 UBSAN: "applying zero offset to null pointer" when using a Field_set with empty values +--echo # + +SET sql_mode=''; +CREATE OR REPLACE TABLE t (c SET('','','') KEY,c2 DECIMAL UNSIGNED ZEROFILL,c3 CHAR(1) BINARY) ENGINE=MyISAM; +INSERT INTO t VALUES ('',CURRENT_TIME,''); +UPDATE t SET c2=c2+5 WHERE c BETWEEN '' AND ''; +DROP TABLE t; +SET sql_mode=DEFAULT; diff --git a/sql/field.cc b/sql/field.cc index 2d690cfe591..a1c4fd8f4cf 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -9573,8 +9573,7 @@ String *Field_set::val_str(String *val_buffer, ulonglong tmp=(ulonglong) Field_enum::val_int(); uint bitnr=0; - val_buffer->set_charset(field_charset()); - val_buffer->length(0); + val_buffer->copy("", 0, field_charset()); while (tmp && bitnr < (uint) typelib->count) { From f521b8ac219102332eec99f854809e6331b3dbce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 17 Jan 2025 12:34:03 +0200 Subject: [PATCH 042/118] MDEV-35723: applying non-zero offset to null pointer in INSERT row_mysql_read_blob_ref(): Correctly handle what Field_blob::store() generates for length=0. --- mysql-test/suite/innodb/r/innodb.result | 6 ++++++ mysql-test/suite/innodb/t/innodb.test | 7 +++++++ storage/innobase/row/row0mysql.cc | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index e1d99c3b731..8d6aa0332e0 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -3337,3 +3337,9 @@ Table Op Msg_type Msg_text test.t1 check status OK ALTER TABLE t1 FORCE; DROP TABLE t1; +# +# MDEV-35723: applying zero offset to null pointer on INSERT +# +CREATE TABLE t1(c TEXT(1) NOT NULL, INDEX (c)) ENGINE=InnoDB; +INSERT INTO t1 SET c=''; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index ec217715aef..73baf7ed7ba 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -2605,3 +2605,10 @@ CHECK TABLE t1; ALTER TABLE t1 FORCE; # Cleanup DROP TABLE t1; + +--echo # +--echo # MDEV-35723: applying zero offset to null pointer on INSERT +--echo # +CREATE TABLE t1(c TEXT(1) NOT NULL, INDEX (c)) ENGINE=InnoDB; +INSERT INTO t1 SET c=''; +DROP TABLE t1; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 4e7cd6b0b37..09b4bff16b9 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -244,6 +244,14 @@ row_mysql_read_blob_ref( *len = mach_read_from_n_little_endian(ref, col_len - 8); + if (!*len) { + /* Field_blob::store() if (!length) would encode both + the length and the pointer in the same area. An empty + string must be a valid (nonnull) pointer in the + collation functions that cmp_data() may invoke. */ + return ref; + } + memcpy(&data, ref + col_len - 8, sizeof data); return(data); From 350cc77fee66bf0ab6e6eabbbf6ec6012c72da99 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 26 Nov 2024 13:34:28 +0400 Subject: [PATCH 043/118] MDEV-29968 Functions in default values in tables with some character sets break SHOW CREATE (and mysqldump) Item:print_for_table_def() uses QT_TO_SYSTEM_CHARSET to print the DEFAULT expression into FRM file during CREATE TABLE. Therefore, the expression is encoded in utf8 in FRM. get_field_default_value() erroneously used field->charset() to print the DEFAULT expression at SHOW CREATE TABLE time. Fixing get_field_default_value() to use &my_charset_utf8mb4_general_ci instead. This makes DEFAULT work in the way way with: - virtual column expressions: if (field->vcol_info) { StringBuffer str(&my_charset_utf8mb4_general_ci); field->vcol_info->print(&str); - check constraint expressions: if (field->check_constraint) { StringBuffer str(&my_charset_utf8mb4_general_ci); field->check_constraint->print(&str); Additional cleanup: Fixing system_charset_info to &my_charset_utf8mb4_general_ci in a few places to make non-BMP characters work in DEFAULT, virtual column, check constraint expressions. --- client/mysqldump.c | 4 +- .../include/ctype_supplementary_chars.inc | 26 ++ mysql-test/main/ctype_utf32.result | 59 ++++- mysql-test/main/ctype_utf32.test | 9 +- .../main/ctype_utf32_not_embedded.result | 106 ++++++++ mysql-test/main/ctype_utf32_not_embedded.test | 38 +++ mysql-test/main/ddl_i18n_koi8r.result | 8 +- mysql-test/main/ddl_i18n_utf8.result | 8 +- mysql-test/main/lock_view.result | 16 +- mysql-test/main/mysql.result | 4 +- mysql-test/main/mysqldump-max.result | 24 +- mysql-test/main/mysqldump-nl.result | 4 +- mysql-test/main/mysqldump-timing.result | 4 +- mysql-test/main/mysqldump-utf8mb4.result | 2 +- mysql-test/main/mysqldump.result | 226 +++++++++--------- mysql-test/main/openssl_1.result | 6 +- mysql-test/main/trigger_wl3253.result | 4 +- .../r/mysqldump_restore_func_qualified.result | 8 +- mysql-test/suite/federated/federatedx.result | 2 +- mysql-test/suite/roles/definer.result | 14 +- .../suite/sql_sequence/mysqldump.result | 8 +- sql/item.cc | 2 +- sql/sql_show.cc | 8 +- .../connect/mysql-test/connect/r/mysql.result | 2 +- 24 files changed, 413 insertions(+), 179 deletions(-) create mode 100644 mysql-test/include/ctype_supplementary_chars.inc create mode 100644 mysql-test/main/ctype_utf32_not_embedded.result create mode 100644 mysql-test/main/ctype_utf32_not_embedded.test diff --git a/client/mysqldump.c b/client/mysqldump.c index 716e1f368e4..1cb41b66e30 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3182,7 +3182,7 @@ static uint get_table_structure(const char *table, const char *db, char *table_t fprintf(sql_file, "SET @saved_cs_client = @@character_set_client;\n" - "SET character_set_client = utf8;\n" + "SET character_set_client = utf8mb4;\n" "/*!50001 CREATE VIEW %s AS SELECT\n", result_table); @@ -3250,7 +3250,7 @@ static uint get_table_structure(const char *table, const char *db, char *table_t { fprintf(sql_file, "/*!40101 SET @saved_cs_client = @@character_set_client */;\n" - "/*!40101 SET character_set_client = utf8 */;\n" + "/*!40101 SET character_set_client = utf8mb4 */;\n" "%s%s;\n" "/*!40101 SET character_set_client = @saved_cs_client */;\n", is_log_table ? "CREATE TABLE IF NOT EXISTS " : "", diff --git a/mysql-test/include/ctype_supplementary_chars.inc b/mysql-test/include/ctype_supplementary_chars.inc new file mode 100644 index 00000000000..dfc2497125b --- /dev/null +++ b/mysql-test/include/ctype_supplementary_chars.inc @@ -0,0 +1,26 @@ +--eval CREATE TABLE t1 (a CHAR(8) DEFAULT REVERSE('aha')) $table_charset +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (); +SELECT * FROM t1; + +--eval CREATE TABLE t2 (a CHAR(8) DEFAULT REVERSE('รฅรครก')) $table_charset +SHOW CREATE TABLE t2; +INSERT INTO t2 VALUES (); +SELECT * FROM t2; + +--eval CREATE TABLE t3 (a CHAR(8) DEFAULT REVERSE('๐Ÿ˜Ž๐Ÿ˜€')) $table_charset +SHOW CREATE TABLE t3; +INSERT INTO t3 VALUES (); +SELECT * FROM t3; + +--eval CREATE TABLE t4 (a CHAR(8), b CHAR(8) AS (REVERSE('๐Ÿ˜Ž๐Ÿ˜€'))) $table_charset +SHOW CREATE TABLE t4; +INSERT INTO t4 (a) VALUES (''); +SELECT * FROM t4; + +--eval CREATE TABLE t5 (a CHAR(8), b CHAR(8) CHECK (b=BINARY REVERSE('๐Ÿ˜Ž๐Ÿ˜€'))) $table_charset +SHOW CREATE TABLE t5; +--error ER_CONSTRAINT_FAILED +INSERT INTO t5 VALUES ('','๐Ÿ˜Ž๐Ÿ˜€'); +INSERT INTO t5 VALUES ('','๐Ÿ˜€๐Ÿ˜Ž'); +SELECT * FROM t5; diff --git a/mysql-test/main/ctype_utf32.result b/mysql-test/main/ctype_utf32.result index 546a7415603..193ad73c7dc 100644 --- a/mysql-test/main/ctype_utf32.result +++ b/mysql-test/main/ctype_utf32.result @@ -3031,5 +3031,62 @@ SELECT CAST(CONVERT('-9223372036854775808' USING utf32) AS SIGNED) AS c1; c1 -9223372036854775808 # -# End of 10.5 tests +# MDEV-29968 Functions in default values in tables with some character sets break SHOW CREATE (and mysqldump) # +SET NAMES utf8mb4; +CREATE TABLE t1 (a CHAR(8) DEFAULT REVERSE('aha')) CHARACTER SET utf32; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(8) DEFAULT reverse('aha') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t1 VALUES (); +SELECT * FROM t1; +a +aha +CREATE TABLE t2 (a CHAR(8) DEFAULT REVERSE('รฅรครก')) CHARACTER SET utf32; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` char(8) DEFAULT reverse('รฅรครก') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t2 VALUES (); +SELECT * FROM t2; +a +รกรครฅ +CREATE TABLE t3 (a CHAR(8) DEFAULT REVERSE('๐Ÿ˜Ž๐Ÿ˜€')) CHARACTER SET utf32; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `a` char(8) DEFAULT reverse('๐Ÿ˜Ž๐Ÿ˜€') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t3 VALUES (); +SELECT * FROM t3; +a +๐Ÿ˜€๐Ÿ˜Ž +CREATE TABLE t4 (a CHAR(8), b CHAR(8) AS (REVERSE('๐Ÿ˜Ž๐Ÿ˜€'))) CHARACTER SET utf32; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `a` char(8) DEFAULT NULL, + `b` char(8) GENERATED ALWAYS AS (reverse('๐Ÿ˜Ž๐Ÿ˜€')) VIRTUAL +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t4 (a) VALUES (''); +SELECT * FROM t4; +a b + ๐Ÿ˜€๐Ÿ˜Ž +CREATE TABLE t5 (a CHAR(8), b CHAR(8) CHECK (b=BINARY REVERSE('๐Ÿ˜Ž๐Ÿ˜€'))) CHARACTER SET utf32; +SHOW CREATE TABLE t5; +Table Create Table +t5 CREATE TABLE `t5` ( + `a` char(8) DEFAULT NULL, + `b` char(8) DEFAULT NULL CHECK (`b` = cast(reverse('๐Ÿ˜Ž๐Ÿ˜€') as char charset binary)) +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t5 VALUES ('','๐Ÿ˜Ž๐Ÿ˜€'); +ERROR 23000: CONSTRAINT `t5.b` failed for `test`.`t5` +INSERT INTO t5 VALUES ('','๐Ÿ˜€๐Ÿ˜Ž'); +SELECT * FROM t5; +a b + ๐Ÿ˜€๐Ÿ˜Ž +DROP TABLE t1, t2, t3, t4, t5; +# End of 10.5 tests diff --git a/mysql-test/main/ctype_utf32.test b/mysql-test/main/ctype_utf32.test index 4a1f27260c6..49e8b6f9bdb 100644 --- a/mysql-test/main/ctype_utf32.test +++ b/mysql-test/main/ctype_utf32.test @@ -1171,5 +1171,12 @@ SELECT HEX(DATE_FORMAT(TIME'11:22:33',@format)); SELECT CAST(CONVERT('-9223372036854775808' USING utf32) AS SIGNED) AS c1; --echo # ---echo # End of 10.5 tests +--echo # MDEV-29968 Functions in default values in tables with some character sets break SHOW CREATE (and mysqldump) --echo # + +SET NAMES utf8mb4; +--let $table_charset=CHARACTER SET utf32 +--source include/ctype_supplementary_chars.inc +DROP TABLE t1, t2, t3, t4, t5; + +--echo # End of 10.5 tests diff --git a/mysql-test/main/ctype_utf32_not_embedded.result b/mysql-test/main/ctype_utf32_not_embedded.result new file mode 100644 index 00000000000..55840fb4893 --- /dev/null +++ b/mysql-test/main/ctype_utf32_not_embedded.result @@ -0,0 +1,106 @@ +# Start of 10.5 tests +# +# MDEV-29968 Functions in default values in tables with some character sets break SHOW CREATE (and mysqldump) +# +SET NAMES utf8mb4; +CREATE TABLE t1 (a CHAR(8) DEFAULT REVERSE('aha')) CHARACTER SET utf32; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(8) DEFAULT reverse('aha') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t1 VALUES (); +SELECT * FROM t1; +a +aha +CREATE TABLE t2 (a CHAR(8) DEFAULT REVERSE('รฅรครก')) CHARACTER SET utf32; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` char(8) DEFAULT reverse('รฅรครก') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t2 VALUES (); +SELECT * FROM t2; +a +รกรครฅ +CREATE TABLE t3 (a CHAR(8) DEFAULT REVERSE('๐Ÿ˜Ž๐Ÿ˜€')) CHARACTER SET utf32; +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `a` char(8) DEFAULT reverse('๐Ÿ˜Ž๐Ÿ˜€') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t3 VALUES (); +SELECT * FROM t3; +a +๐Ÿ˜€๐Ÿ˜Ž +CREATE TABLE t4 (a CHAR(8), b CHAR(8) AS (REVERSE('๐Ÿ˜Ž๐Ÿ˜€'))) CHARACTER SET utf32; +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `a` char(8) DEFAULT NULL, + `b` char(8) GENERATED ALWAYS AS (reverse('๐Ÿ˜Ž๐Ÿ˜€')) VIRTUAL +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t4 (a) VALUES (''); +SELECT * FROM t4; +a b + ๐Ÿ˜€๐Ÿ˜Ž +CREATE TABLE t5 (a CHAR(8), b CHAR(8) CHECK (b=BINARY REVERSE('๐Ÿ˜Ž๐Ÿ˜€'))) CHARACTER SET utf32; +SHOW CREATE TABLE t5; +Table Create Table +t5 CREATE TABLE `t5` ( + `a` char(8) DEFAULT NULL, + `b` char(8) DEFAULT NULL CHECK (`b` = cast(reverse('๐Ÿ˜Ž๐Ÿ˜€') as char charset binary)) +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +INSERT INTO t5 VALUES ('','๐Ÿ˜Ž๐Ÿ˜€'); +ERROR 23000: CONSTRAINT `t5.b` failed for `test`.`t5` +INSERT INTO t5 VALUES ('','๐Ÿ˜€๐Ÿ˜Ž'); +SELECT * FROM t5; +a b + ๐Ÿ˜€๐Ÿ˜Ž +# Running dump +DROP TABLE t1, t2, t3, t4, t5; +# Running restore +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(8) DEFAULT reverse('aha') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +SELECT * FROM t1; +a +aha +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` char(8) DEFAULT reverse('รฅรครก') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +SELECT * FROM t2; +a +รกรครฅ +SHOW CREATE TABLE t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `a` char(8) DEFAULT reverse('๐Ÿ˜Ž๐Ÿ˜€') +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +SELECT * FROM t3; +a +๐Ÿ˜€๐Ÿ˜Ž +SHOW CREATE TABLE t4; +Table Create Table +t4 CREATE TABLE `t4` ( + `a` char(8) DEFAULT NULL, + `b` char(8) GENERATED ALWAYS AS (reverse('๐Ÿ˜Ž๐Ÿ˜€')) VIRTUAL +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +SELECT * FROM t4; +a b + ๐Ÿ˜€๐Ÿ˜Ž +SHOW CREATE TABLE t5; +Table Create Table +t5 CREATE TABLE `t5` ( + `a` char(8) DEFAULT NULL, + `b` char(8) DEFAULT NULL CHECK (`b` = cast(reverse('๐Ÿ˜Ž๐Ÿ˜€') as char charset binary)) +) ENGINE=MyISAM DEFAULT CHARSET=utf32 COLLATE=utf32_general_ci +SELECT * FROM t5; +a b + ๐Ÿ˜€๐Ÿ˜Ž +DROP TABLE t1, t2, t3, t4, t5; +# End of 10.5 tests diff --git a/mysql-test/main/ctype_utf32_not_embedded.test b/mysql-test/main/ctype_utf32_not_embedded.test new file mode 100644 index 00000000000..622ba074078 --- /dev/null +++ b/mysql-test/main/ctype_utf32_not_embedded.test @@ -0,0 +1,38 @@ +# Embedded server doesn't support external clients +--source include/not_embedded.inc + +--echo # Start of 10.5 tests + +--echo # +--echo # MDEV-29968 Functions in default values in tables with some character sets break SHOW CREATE (and mysqldump) +--echo # + +SET NAMES utf8mb4; +--let $table_charset=CHARACTER SET utf32 +--source include/ctype_supplementary_chars.inc + +--echo # Running dump +--let $mysqldumpfile = $MYSQLTEST_VARDIR/tmp/ctype_utf32_not_embedded_dump.sql +--exec $MYSQL_DUMP test > $mysqldumpfile + +DROP TABLE t1, t2, t3, t4, t5; + +--echo # Running restore +--exec $MYSQL test < $mysqldumpfile +SHOW CREATE TABLE t1; +SELECT * FROM t1; +SHOW CREATE TABLE t2; +SELECT * FROM t2; +SHOW CREATE TABLE t3; +SELECT * FROM t3; +SHOW CREATE TABLE t4; +SELECT * FROM t4; +SHOW CREATE TABLE t5; +SELECT * FROM t5; + +DROP TABLE t1, t2, t3, t4, t5; + +--error 0,1 +--remove_file $mysqldumpfile + +--echo # End of 10.5 tests diff --git a/mysql-test/main/ddl_i18n_koi8r.result b/mysql-test/main/ddl_i18n_koi8r.result index be375e501cd..fa489aa9c15 100644 --- a/mysql-test/main/ddl_i18n_koi8r.result +++ b/mysql-test/main/ddl_i18n_koi8r.result @@ -1731,13 +1731,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER USE `mysqltest1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `log` ( `msg` varchar(255) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; @@ -1811,13 +1811,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER USE `mysqltest2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `log` ( `msg` varchar(255) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; diff --git a/mysql-test/main/ddl_i18n_utf8.result b/mysql-test/main/ddl_i18n_utf8.result index ef1b7e62d40..3cec11850ca 100644 --- a/mysql-test/main/ddl_i18n_utf8.result +++ b/mysql-test/main/ddl_i18n_utf8.result @@ -1731,13 +1731,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER USE `mysqltest1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `log` ( `msg` varchar(255) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; @@ -1811,13 +1811,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER USE `mysqltest2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `log` ( `msg` varchar(255) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `c` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; diff --git a/mysql-test/main/lock_view.result b/mysql-test/main/lock_view.result index cd693032d87..004536d60f7 100644 --- a/mysql-test/main/lock_view.result +++ b/mysql-test/main/lock_view.result @@ -22,7 +22,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER USE `mysqltest1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -32,7 +32,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest2` /*!40100 DEFAULT CHARACTER USE `mysqltest2`; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v2` AS SELECT 1 AS `a` */; SET character_set_client = @saved_cs_client; @@ -41,27 +41,27 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest3` /*!40100 DEFAULT CHARACTER USE `mysqltest3`; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v3` AS SELECT 1 AS `a` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v3i` AS SELECT 1 AS `a` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v3is` AS SELECT 1 AS `schema_name` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v3nt` AS SELECT 1 AS `1` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v3ps` AS SELECT 1 AS `user` */; SET character_set_client = @saved_cs_client; @@ -238,7 +238,7 @@ disconnect con1; connection default; /*M!999999\- enable the sandbox mode */ SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1` AS SELECT 1 AS `id` */; SET character_set_client = @saved_cs_client; diff --git a/mysql-test/main/mysql.result b/mysql-test/main/mysql.result index 1e02cd9f595..42620265567 100644 --- a/mysql-test/main/mysql.result +++ b/mysql-test/main/mysql.result @@ -562,7 +562,7 @@ a1\`b1 CREATE TABLE `a1\``b1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `a1\``b1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -592,7 +592,7 @@ a1\"b1 CREATE TABLE "a1\""b1" ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE "a1\""b1" ( "a" int(11) DEFAULT NULL ); diff --git a/mysql-test/main/mysqldump-max.result b/mysql-test/main/mysqldump-max.result index 4a2fe09d44d..735fe6374bd 100644 --- a/mysql-test/main/mysqldump-max.result +++ b/mysql-test/main/mysqldump-max.result @@ -95,7 +95,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -107,7 +107,7 @@ INSERT DELAYED IGNORE INTO `t1` VALUES (1,'first value'),(2,'first value'),(3,'f /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -119,7 +119,7 @@ INSERT DELAYED IGNORE INTO `t2` VALUES (1,'first value'),(2,'first value'),(3,'f /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `t3`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t3` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -131,7 +131,7 @@ INSERT DELAYED IGNORE INTO `t3` VALUES (1,'first value'),(2,'first value'),(3,'f /*!40000 ALTER TABLE `t3` ENABLE KEYS */; DROP TABLE IF EXISTS `t4`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t4` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -143,7 +143,7 @@ INSERT DELAYED IGNORE INTO `t4` VALUES (1,'first value'),(2,'first value'),(3,'f /*!40000 ALTER TABLE `t4` ENABLE KEYS */; DROP TABLE IF EXISTS `t5`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t5` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -155,7 +155,7 @@ INSERT DELAYED IGNORE INTO `t5` VALUES (1,'first value'),(2,'first value'),(3,'f /*!40000 ALTER TABLE `t5` ENABLE KEYS */; DROP TABLE IF EXISTS `t6`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t6` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -193,7 +193,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -205,7 +205,7 @@ INSERT DELAYED INTO `t1` VALUES (1,'first value'),(2,'first value'),(3,'first va /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -217,7 +217,7 @@ INSERT DELAYED INTO `t2` VALUES (1,'first value'),(2,'first value'),(3,'first va /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `t3`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t3` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -229,7 +229,7 @@ INSERT DELAYED INTO `t3` VALUES (1,'first value'),(2,'first value'),(3,'first va /*!40000 ALTER TABLE `t3` ENABLE KEYS */; DROP TABLE IF EXISTS `t4`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t4` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -241,7 +241,7 @@ INSERT DELAYED INTO `t4` VALUES (1,'first value'),(2,'first value'),(3,'first va /*!40000 ALTER TABLE `t4` ENABLE KEYS */; DROP TABLE IF EXISTS `t5`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t5` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL @@ -253,7 +253,7 @@ INSERT DELAYED INTO `t5` VALUES (1,'first value'),(2,'first value'),(3,'first va /*!40000 ALTER TABLE `t5` ENABLE KEYS */; DROP TABLE IF EXISTS `t6`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t6` ( `id` int(8) DEFAULT NULL, `name` varchar(32) DEFAULT NULL diff --git a/mysql-test/main/mysqldump-nl.result b/mysql-test/main/mysqldump-nl.result index 56e9c56bae2..03dbc9ea13d 100644 --- a/mysql-test/main/mysqldump-nl.result +++ b/mysql-test/main/mysqldump-nl.result @@ -34,7 +34,7 @@ USE `mysqltest1 -- /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1 1t` ( `foobar @@ -53,7 +53,7 @@ raboof` int(11) DEFAULT NULL -- SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1 1v` AS SELECT 1 AS `foobar diff --git a/mysql-test/main/mysqldump-timing.result b/mysql-test/main/mysqldump-timing.result index 2ac132412f9..8afb8de6b8c 100644 --- a/mysql-test/main/mysqldump-timing.result +++ b/mysql-test/main/mysqldump-timing.result @@ -21,7 +21,7 @@ timeout without t1 contents expected /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `i` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -45,7 +45,7 @@ This would be a race condition otherwise, but default max_statement_time=0 makes /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `i` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; diff --git a/mysql-test/main/mysqldump-utf8mb4.result b/mysql-test/main/mysqldump-utf8mb4.result index dc2ec06554e..b1a5338c083 100644 --- a/mysql-test/main/mysqldump-utf8mb4.result +++ b/mysql-test/main/mysqldump-utf8mb4.result @@ -46,7 +46,7 @@ Testing text format output /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `point` varchar(10) NOT NULL, `data` varchar(10) DEFAULT NULL, diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index 08725299a38..93e0f9ee89c 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -33,7 +33,7 @@ INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` decimal(64,20) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -49,7 +49,7 @@ Warnings: Warning 1264 Out of range value for column 'a' at row 1 /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` double DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -71,7 +71,7 @@ ERROR 42S22: Unknown column '1.2345' in 'field list' SET SQL_MODE=@OLD_SQL_MODE; /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` decimal(10,5) DEFAULT NULL, `b` float DEFAULT NULL @@ -80,7 +80,7 @@ CREATE TABLE `t1` ( INSERT INTO `t1` VALUES (1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456); /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` decimal(10,5) DEFAULT NULL, `b` float DEFAULT NULL @@ -101,7 +101,7 @@ INSERT INTO `t1` VALUES (1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23 /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` decimal(10,5) DEFAULT NULL, `b` float DEFAULT NULL @@ -131,7 +131,7 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` decimal(10,5) DEFAULT NULL, `b` float DEFAULT NULL @@ -214,7 +214,7 @@ INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` varchar(255) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=koi8r COLLATE=koi8r_general_ci; @@ -297,7 +297,7 @@ DROP TABLE t1; create table ```a` (i int); /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE ```a` ( `i` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -321,7 +321,7 @@ create table t1(a int); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -350,7 +350,7 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE "t1" ( "a" int(11) DEFAULT NULL ); @@ -382,7 +382,7 @@ set global sql_mode='ANSI_QUOTES'; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -411,7 +411,7 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE "t1" ( "a" int(11) DEFAULT NULL ); @@ -447,7 +447,7 @@ insert into t1 values (1),(2),(3); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -544,7 +544,7 @@ INSERT INTO t1 VALUES (_latin1 ' /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` char(10) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -666,7 +666,7 @@ INSERT INTO t2 VALUES (4),(5),(6); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -708,7 +708,7 @@ INSERT INTO `t1` VALUES (0x602010000280100005E71A); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `b` blob DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -750,7 +750,7 @@ INSERT INTO t1 VALUES (4),(5),(6); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -785,7 +785,7 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -1155,7 +1155,7 @@ insert into t1 (F_8d3bba7425e7c98c50f52ca1b52d3735) values (1); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `F_c4ca4238a0b923820dcc509a6f75849b` int(11) DEFAULT NULL, `F_c81e728d9d4c2f636f067f89cc14862c` int(11) DEFAULT NULL, @@ -1531,7 +1531,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -1576,14 +1576,14 @@ INSERT INTO t2 VALUES (1), (2); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -1612,14 +1612,14 @@ CREATE TABLE `t2` ( /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -1807,7 +1807,7 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(10) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -1820,7 +1820,7 @@ INSERT INTO `t1` VALUES (NULL),(10),(20); UNLOCK TABLES; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `pk` int(11) NOT NULL AUTO_INCREMENT, `a` int(10) DEFAULT NULL, @@ -1926,21 +1926,21 @@ mariadb-dump: Couldn't find table: "non_existing" /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t3`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t3` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -1976,7 +1976,7 @@ mariadb-dump: Got error: 1064: "You have an error in your SQL syntax; check the /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -2013,7 +2013,7 @@ insert into t1 values (0815, 4711, 2006); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE "t1" ( "a b" int(11) NOT NULL, "c""d" int(11) NOT NULL, @@ -2048,7 +2048,7 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a b` int(11) NOT NULL, `c"d` int(11) NOT NULL, @@ -2103,7 +2103,7 @@ create view v2 as select * from t2 where a like 'a%' with check option; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` varchar(30) DEFAULT NULL, KEY `a` (`a`(5)) @@ -2118,7 +2118,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v2` AS SELECT 1 AS `a` */; SET character_set_client = @saved_cs_client; @@ -2198,7 +2198,7 @@ create view v1 as select * from t1; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -2211,7 +2211,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1` AS SELECT 1 AS `a` */; SET character_set_client = @saved_cs_client; @@ -2269,7 +2269,7 @@ create view v2 as select * from t2 where a like 'a%' with check option; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` varchar(30) DEFAULT NULL, KEY `a` (`a`(5)) @@ -2284,7 +2284,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v2` AS SELECT 1 AS `a` */; SET character_set_client = @saved_cs_client; @@ -2335,7 +2335,7 @@ INSERT INTO t1 VALUES ('\''); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` char(10) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -2382,7 +2382,7 @@ select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, @@ -2398,7 +2398,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1` AS SELECT 1 AS `a`, 1 AS `b`, @@ -2407,14 +2407,14 @@ SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v2` AS SELECT 1 AS `a` */; SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `v3`; /*!50001 DROP VIEW IF EXISTS `v3`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v3` AS SELECT 1 AS `a`, 1 AS `b`, @@ -2536,7 +2536,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` bigint(20) DEFAULT NULL @@ -2608,7 +2608,7 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -2666,7 +2666,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` bigint(20) DEFAULT NULL @@ -2680,7 +2680,7 @@ INSERT INTO `t1` VALUES (1,NULL),(2,NULL),(4,NULL),(11,NULL); UNLOCK TABLES; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -2814,7 +2814,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `id` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -2966,7 +2966,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `d` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), UNIQUE KEY `d` (`d`) @@ -3004,7 +3004,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `d` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), UNIQUE KEY `d` (`d`) @@ -3058,7 +3058,7 @@ a2 /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1 test"; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE "t1 test" ( "a1" int(11) DEFAULT NULL ); @@ -3087,7 +3087,7 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; DROP TABLE IF EXISTS "t2 test"; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE "t2 test" ( "a2" int(11) DEFAULT NULL ); @@ -3142,7 +3142,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` varchar(32) DEFAULT NULL, @@ -3158,7 +3158,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `v0`; /*!50001 DROP VIEW IF EXISTS `v0`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v0` AS SELECT 1 AS `a`, 1 AS `b`, @@ -3167,7 +3167,7 @@ SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1` AS SELECT 1 AS `a`, 1 AS `b`, @@ -3176,7 +3176,7 @@ SET character_set_client = @saved_cs_client; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v2` AS SELECT 1 AS `a`, 1 AS `b`, @@ -3268,7 +3268,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -3328,7 +3328,7 @@ insert into t1 values ('',''); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` binary(1) DEFAULT NULL, `b` blob DEFAULT NULL @@ -3364,7 +3364,7 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` binary(1) DEFAULT NULL, `b` blob DEFAULT NULL @@ -3549,7 +3549,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_test_db` /*!40100 DEFAULT CH USE `mysqldump_test_db`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `id` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -3563,7 +3563,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1` AS SELECT 1 AS `id` */; SET character_set_client = @saved_cs_client; @@ -3610,7 +3610,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_tables` /*!40100 DEFAULT CHA USE `mysqldump_tables`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `basetable` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `tag` varchar(64) DEFAULT NULL, @@ -3622,7 +3622,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_views` /*!40100 DEFAULT CHAR USE `mysqldump_views`; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `nasishnasifu` AS SELECT 1 AS `id` */; SET character_set_client = @saved_cs_client; @@ -3758,7 +3758,7 @@ use test; /*M!999999\- enable the sandbox mode */ DROP TABLE IF EXISTS `TABLES`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TEMPORARY TABLE `TABLES` ( `TABLE_CATALOG` varchar(512) NOT NULL, `TABLE_SCHEMA` varchar(64) NOT NULL, @@ -3834,14 +3834,14 @@ CREATE TABLE t1 (a INT) ENGINE=merge UNION=(t2, t3); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci UNION=(`t2`,`t3`); /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -3853,7 +3853,7 @@ LOCK TABLES `t2` WRITE; UNLOCK TABLES; DROP TABLE IF EXISTS `t3`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t3` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -3946,7 +3946,7 @@ CREATE TABLE t1 (c1 INT, c2 LONGBLOB); INSERT INTO t1 SET c1=11, c2=REPEAT('q',509); /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `c1` int(11) DEFAULT NULL, `c2` longblob DEFAULT NULL @@ -4034,7 +4034,7 @@ create view db42635.v2 (c) as select * from db42635.t1; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `id` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -4047,7 +4047,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v2` AS SELECT 1 AS `c` */; SET character_set_client = @saved_cs_client; @@ -4184,7 +4184,7 @@ INSERT INTO t1 VALUES (3,4), (4,5); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL @@ -4461,7 +4461,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_test_db` /*!40100 DEFAULT CH USE `mysqldump_test_db`; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `id` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -4475,7 +4475,7 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1` AS SELECT 1 AS `id` */; SET character_set_client = @saved_cs_client; @@ -4573,7 +4573,7 @@ create table test (a int); /*M!999999\- enable the sandbox mode */ DROP TABLE IF EXISTS `test`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `test` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -4795,7 +4795,7 @@ ALTER DATABASE `test-database` CHARACTER SET latin1 COLLATE latin1_swedish_ci; ALTER DATABASE `test-database` CHARACTER SET utf8 COLLATE utf8_unicode_ci ; /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `test` ( `c1` varchar(10) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; @@ -5286,7 +5286,7 @@ CREATE TABLE t1 (a INT); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ); @@ -5565,20 +5565,20 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `db1` /*!40100 DEFAULT CHARACTER SET ut USE `db1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `basetable` ( `id` smallint(6) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `basetable` VALUES (5),(6); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `nonunique_table_name` ( `i3` smallint(6) DEFAULT NULL ) ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci INSERT_METHOD=LAST UNION=(`basetable`); /*!40101 SET character_set_client = @saved_cs_client */; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `nonunique_table_view_name` AS SELECT 1 AS `1` */; SET character_set_client = @saved_cs_client; @@ -5587,7 +5587,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `db2` /*!40100 DEFAULT CHARACTER SET ut USE `db2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `nonunique_table_name` ( `i1` bigint(20) unsigned NOT NULL AUTO_INCREMENT, UNIQUE KEY `i1` (`i1`) @@ -5595,7 +5595,7 @@ CREATE TABLE `nonunique_table_name` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `nonunique_table_name` VALUES (1),(2); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `nonunique_table_view_name` ( `i2` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; @@ -5624,7 +5624,7 @@ USE `db2`; /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `nonunique_table_name` ( `i1` bigint(20) unsigned NOT NULL AUTO_INCREMENT, UNIQUE KEY `i1` (`i1`) @@ -5632,7 +5632,7 @@ CREATE TABLE `nonunique_table_name` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `nonunique_table_name` VALUES (1),(2); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `nonunique_table_view_name` ( `i2` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; @@ -5647,7 +5647,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `db2` /*!40100 DEFAULT CHARACTER SET ut USE `db2`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `nonunique_table_name` ( `i1` bigint(20) unsigned NOT NULL AUTO_INCREMENT, UNIQUE KEY `i1` (`i1`) @@ -5655,7 +5655,7 @@ CREATE TABLE `nonunique_table_name` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT DELAYED INTO `nonunique_table_name` VALUES (1),(2); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `nonunique_table_view_name` ( `i2` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; @@ -5666,21 +5666,21 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `db1` /*!40100 DEFAULT CHARACTER SET ut USE `db1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `basetable` ( `id` smallint(6) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; INSERT DELAYED INTO `basetable` VALUES (5),(6); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `nonunique_table_name` ( `i3` smallint(6) DEFAULT NULL ) ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci INSERT_METHOD=LAST UNION=(`basetable`); /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `nonunique_table_name` VALUES (5),(6); SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `nonunique_table_view_name` AS SELECT 1 AS `1` */; SET character_set_client = @saved_cs_client; @@ -5827,7 +5827,7 @@ DROP TABLE t1; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `general_log` ( `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), `user_host` mediumtext NOT NULL, @@ -5838,7 +5838,7 @@ CREATE TABLE IF NOT EXISTS `general_log` ( ) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='General log'; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `slow_log` ( `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), `user_host` mediumtext NOT NULL, @@ -5857,7 +5857,7 @@ CREATE TABLE IF NOT EXISTS `slow_log` ( /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_index_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `innodb_index_stats` ( `database_name` varchar(64) NOT NULL, `table_name` varchar(199) NOT NULL, @@ -5872,7 +5872,7 @@ CREATE TABLE `innodb_index_stats` ( /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_table_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `innodb_table_stats` ( `database_name` varchar(64) NOT NULL, `table_name` varchar(199) NOT NULL, @@ -5884,7 +5884,7 @@ CREATE TABLE `innodb_table_stats` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin STATS_PERSISTENT=0; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `transaction_registry` ( `transaction_id` bigint(20) unsigned NOT NULL, `commit_id` bigint(20) unsigned NOT NULL, @@ -5923,7 +5923,7 @@ CREATE TABLE IF NOT EXISTS `transaction_registry` ( /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `general_log` ( `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), `user_host` mediumtext NOT NULL, @@ -5934,7 +5934,7 @@ CREATE TABLE IF NOT EXISTS `general_log` ( ) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='General log'; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `slow_log` ( `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), `user_host` mediumtext NOT NULL, @@ -5953,7 +5953,7 @@ CREATE TABLE IF NOT EXISTS `slow_log` ( /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_index_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `innodb_index_stats` ( `database_name` varchar(64) NOT NULL, `table_name` varchar(199) NOT NULL, @@ -5973,7 +5973,7 @@ LOCK TABLES `innodb_index_stats` WRITE; UNLOCK TABLES; DROP TABLE IF EXISTS `innodb_table_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `innodb_table_stats` ( `database_name` varchar(64) NOT NULL, `table_name` varchar(199) NOT NULL, @@ -5990,7 +5990,7 @@ LOCK TABLES `innodb_table_stats` WRITE; /*!40000 ALTER TABLE `innodb_table_stats` ENABLE KEYS */; UNLOCK TABLES; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `transaction_registry` ( `transaction_id` bigint(20) unsigned NOT NULL, `commit_id` bigint(20) unsigned NOT NULL, @@ -6029,7 +6029,7 @@ CREATE TABLE IF NOT EXISTS `transaction_registry` ( /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `general_log` ( `event_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), `user_host` mediumtext NOT NULL, @@ -6040,7 +6040,7 @@ CREATE TABLE IF NOT EXISTS `general_log` ( ) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='General log'; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `slow_log` ( `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), `user_host` mediumtext NOT NULL, @@ -6059,7 +6059,7 @@ CREATE TABLE IF NOT EXISTS `slow_log` ( /*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `innodb_index_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `innodb_index_stats` ( `database_name` varchar(64) NOT NULL, `table_name` varchar(199) NOT NULL, @@ -6079,7 +6079,7 @@ LOCK TABLES `innodb_index_stats` WRITE; UNLOCK TABLES; DROP TABLE IF EXISTS `innodb_table_stats`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `innodb_table_stats` ( `database_name` varchar(64) NOT NULL, `table_name` varchar(199) NOT NULL, @@ -6096,7 +6096,7 @@ LOCK TABLES `innodb_table_stats` WRITE; /*!40000 ALTER TABLE `innodb_table_stats` ENABLE KEYS */; UNLOCK TABLES; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE IF NOT EXISTS `transaction_registry` ( `transaction_id` bigint(20) unsigned NOT NULL, `commit_id` bigint(20) unsigned NOT NULL, @@ -6143,7 +6143,7 @@ CREATE TABLE t4(ร‹รรŒรรŽร‹ร1 INT); insert into t4 values(1); /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) INVISIBLE DEFAULT NULL @@ -6151,7 +6151,7 @@ CREATE TABLE `t1` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` (`a`, `b`) VALUES (1,NULL),(1,2); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL @@ -6159,7 +6159,7 @@ CREATE TABLE `t2` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t2` VALUES (1,2),(1,2); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t3` ( `invisible` int(11) DEFAULT NULL, `a b c & $!@#$%^&*( )` int(11) INVISIBLE DEFAULT 4, @@ -6168,7 +6168,7 @@ CREATE TABLE `t3` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t3` (`invisible`, `a b c & $!@#$%^&*( )`, `ds=~!@ \# $% ^ & * ( ) _ - = +`) VALUES (1,4,5),(5,4,5),(2,4,5),(1,2,3); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t4` ( `ร‹รรŒรรŽร‹ร1` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -6177,7 +6177,7 @@ INSERT INTO `t4` VALUES (1); #Check side effect on --complete insert /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) INVISIBLE DEFAULT NULL @@ -6185,7 +6185,7 @@ CREATE TABLE `t1` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` (`a`, `b`) VALUES (1,NULL),(1,2); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL @@ -6193,7 +6193,7 @@ CREATE TABLE `t2` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t2` (`a`, `b`) VALUES (1,2),(1,2); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t3` ( `invisible` int(11) DEFAULT NULL, `a b c & $!@#$%^&*( )` int(11) INVISIBLE DEFAULT 4, @@ -6202,7 +6202,7 @@ CREATE TABLE `t3` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t3` (`invisible`, `a b c & $!@#$%^&*( )`, `ds=~!@ \# $% ^ & * ( ) _ - = +`) VALUES (1,4,5),(5,4,5),(2,4,5),(1,2,3); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t4` ( `ร‹รรŒรรŽร‹ร1` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -6529,7 +6529,7 @@ update mysql.event set body ='select not_a_value' where db='test' and name='e1'; create table t1 (i int); /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `i` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -6583,7 +6583,7 @@ create table t1 (a int); /*M!999999\- enable the sandbox mode */ DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; diff --git a/mysql-test/main/openssl_1.result b/mysql-test/main/openssl_1.result index bfe79a9df85..b90dc76f401 100644 --- a/mysql-test/main/openssl_1.result +++ b/mysql-test/main/openssl_1.result @@ -91,7 +91,7 @@ INSERT INTO t1 VALUES (1), (2); /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ); @@ -126,7 +126,7 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ); @@ -161,7 +161,7 @@ UNLOCK TABLES; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ); diff --git a/mysql-test/main/trigger_wl3253.result b/mysql-test/main/trigger_wl3253.result index 8d4de24d4e0..54cc51a0e58 100644 --- a/mysql-test/main/trigger_wl3253.result +++ b/mysql-test/main/trigger_wl3253.result @@ -312,7 +312,7 @@ CREATE TRIGGER tr2_bi BEFORE INSERT ON t1 FOR EACH ROW SET @a:=2; CREATE TRIGGER tr1_bu BEFORE UPDATE ON t1 FOR EACH ROW SET @a:=3; /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; @@ -375,7 +375,7 @@ CREATE TRIGGER tr1_1_bi BEFORE INSERT ON t1 FOR EACH ROW FOLLOWS tr1_bi SET @a:= # Expected order of triggers in the dump is: tr0_bi, tr1_bi, tr1_1_bi, tr2_i. /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; diff --git a/mysql-test/suite/compat/oracle/r/mysqldump_restore_func_qualified.result b/mysql-test/suite/compat/oracle/r/mysqldump_restore_func_qualified.result index 26468bd2415..c772c2e1eae 100644 --- a/mysql-test/suite/compat/oracle/r/mysqldump_restore_func_qualified.result +++ b/mysql-test/suite/compat/oracle/r/mysqldump_restore_func_qualified.result @@ -26,7 +26,7 @@ LTRIM(now()) AS a0, LPAD(now(),10) AS b0; /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a0` varchar(64) NOT NULL DEFAULT ltrim(current_timestamp()), `a1` varchar(64) GENERATED ALWAYS AS (ltrim(`a0`)) STORED, @@ -35,7 +35,7 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; /*!40101 SET character_set_client = @saved_cs_client */; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a0` varchar(64) NOT NULL DEFAULT ltrim_oracle(current_timestamp()), `a1` varchar(64) GENERATED ALWAYS AS (ltrim_oracle(`a0`)) STORED, @@ -44,13 +44,13 @@ CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci; /*!40101 SET character_set_client = @saved_cs_client */; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1` AS SELECT 1 AS `a0`, 1 AS `b0` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v2` AS SELECT 1 AS `a0`, 1 AS `b0` */; diff --git a/mysql-test/suite/federated/federatedx.result b/mysql-test/suite/federated/federatedx.result index 1d757dceb93..7f815c1a61c 100644 --- a/mysql-test/suite/federated/federatedx.result +++ b/mysql-test/suite/federated/federatedx.result @@ -2245,7 +2245,7 @@ CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; # Dump table t1 using mysqldump tool /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `id` varchar(20) NOT NULL, PRIMARY KEY (`id`) diff --git a/mysql-test/suite/roles/definer.result b/mysql-test/suite/roles/definer.result index 98cf82fc39b..5939dcf2cec 100644 --- a/mysql-test/suite/roles/definer.result +++ b/mysql-test/suite/roles/definer.result @@ -280,32 +280,32 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v1` AS SELECT 1 AS `a+b`, 1 AS `c` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v2` AS SELECT 1 AS `a+b`, 1 AS `c`, 1 AS `current_role()` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v3` AS SELECT 1 AS `a+b`, 1 AS `c` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v4` AS SELECT 1 AS `a+b`, 1 AS `c` */; SET character_set_client = @saved_cs_client; SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +SET character_set_client = utf8mb4; /*!50001 CREATE VIEW `v5` AS SELECT 1 AS `a+b`, 1 AS `c` */; @@ -315,7 +315,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER USE `mysqltest1`; /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, @@ -324,7 +324,7 @@ CREATE TABLE `t1` ( /*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` VALUES (1,10,100),(2,20,200); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, diff --git a/mysql-test/suite/sql_sequence/mysqldump.result b/mysql-test/suite/sql_sequence/mysqldump.result index e56162a434c..69817b42ec9 100644 --- a/mysql-test/suite/sql_sequence/mysqldump.result +++ b/mysql-test/suite/sql_sequence/mysqldump.result @@ -9,7 +9,7 @@ DO SETVAL(`a1`, 1, 0); CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; DO SETVAL(`x1`, 1, 0); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, KEY `a` (`a`) @@ -23,7 +23,7 @@ DO SETVAL(`a1`, 1, 0); CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; DO SETVAL(`x1`, 1, 0); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, KEY `a` (`a`) @@ -37,7 +37,7 @@ DO SETVAL(`a1`, 1, 0); CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; DO SETVAL(`x1`, 1, 0); /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, KEY `a` (`a`) @@ -47,7 +47,7 @@ INSERT INTO `t1` VALUES (1),(2); # dump by tables only tables /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `a` int(11) DEFAULT NULL, KEY `a` (`a`) diff --git a/sql/item.cc b/sql/item.cc index e6e69629fe5..7143bced98b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3936,7 +3936,7 @@ void Item_string::print(String *str, enum_query_type query_type) } else { - str_value.print(str, system_charset_info); + str_value.print(str, &my_charset_utf8mb4_general_ci); } } else diff --git a/sql/sql_show.cc b/sql/sql_show.cc index dff2a9c73da..7f03debcffb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1289,7 +1289,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) { Protocol *protocol= thd->protocol; char buff[2048]; - String buffer(buff, sizeof(buff), system_charset_info); + String buffer(buff, sizeof(buff), &my_charset_utf8mb4_general_ci); List field_list; bool error= TRUE; DBUG_ENTER("mysqld_show_create"); @@ -1709,7 +1709,7 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value, def_value->length(0); if (has_default) { - StringBuffer str(field->charset()); + StringBuffer str(&my_charset_utf8mb4_general_ci); if (field->default_value) { field->default_value->print(&str); @@ -2236,11 +2236,11 @@ int show_create_table_ex(THD *thd, TABLE_LIST *table_list, { packet->append(STRING_WITH_LEN(" INVISIBLE")); } - def_value.set(def_value_buf, sizeof(def_value_buf), system_charset_info); + def_value.set(def_value_buf, sizeof(def_value_buf), &my_charset_utf8mb4_general_ci); if (get_field_default_value(thd, field, &def_value, 1)) { packet->append(STRING_WITH_LEN(" DEFAULT ")); - packet->append(def_value.ptr(), def_value.length(), system_charset_info); + packet->append(def_value.ptr(), def_value.length(), &my_charset_utf8mb4_general_ci); } if (field->vers_update_unversioned()) diff --git a/storage/connect/mysql-test/connect/r/mysql.result b/storage/connect/mysql-test/connect/r/mysql.result index 6e61fe3f4d7..93f68f5aad9 100644 --- a/storage/connect/mysql-test/connect/r/mysql.result +++ b/storage/connect/mysql-test/connect/r/mysql.result @@ -231,7 +231,7 @@ a # Start of mysqldump ------ /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t2` ( `a` int(11) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci CONNECTION='mysql://root@localhost:PORT/test/t1' `TABLE_TYPE`='MYSQL'; From a69da0c31e97109bba099022acdd393f92fa127f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 23 Dec 2024 21:27:00 +0100 Subject: [PATCH 044/118] MDEV-19761 Before Trigger not processed for Not Null Columns if no explicit value and no DEFAULT it's incorrect to zero out table->triggers->extra_null_bitmap before a statement, because if insert uses an explicit field list and omits a field that has no default value, the field should get NULL implicitly. So extra_null_bitmap should have 1s for all fields that have no defaults * create extra_null_bitmap_init and initialize it as above * copy extra_null_bitmap_init to extra_null_bitmap for inserts * still zero out extra_null_bitmap for updates/deletes where all fields definitely have a value * make not_null_fields_have_null_values() to send ER_NO_DEFAULT_FOR_FIELD for fields with no default and no value, otherwise creation of a trigger with an empty body would change the error message --- .../main/trigger_no_defaults-11698.result | 2 +- .../main/trigger_no_defaults-11698.test | 2 +- mysql-test/main/trigger_null-8605.result | 25 +++++++++ mysql-test/main/trigger_null-8605.test | 25 +++++++++ sql/field.h | 2 +- sql/field_conv.cc | 8 +-- sql/sql_base.cc | 9 +++- sql/sql_delete.cc | 4 +- sql/sql_insert.cc | 26 ++-------- sql/sql_insert.h | 7 +++ sql/sql_load.cc | 9 ++-- sql/sql_trigger.cc | 9 +++- sql/sql_trigger.h | 18 ++++--- sql/sql_update.cc | 4 +- sql/table.cc | 51 ++++++++++--------- 15 files changed, 127 insertions(+), 74 deletions(-) diff --git a/mysql-test/main/trigger_no_defaults-11698.result b/mysql-test/main/trigger_no_defaults-11698.result index 8ce495eaf3a..443bf15bb63 100644 --- a/mysql-test/main/trigger_no_defaults-11698.result +++ b/mysql-test/main/trigger_no_defaults-11698.result @@ -15,10 +15,10 @@ insert t1 (b) values (10); insert t1 (b) values (20); ERROR HY000: Field 'a' doesn't have a default value insert t1 (b) values (30); +ERROR 23000: Column 'a' cannot be null select * from t1; a b 10 10 -0 30 drop table t1; set sql_mode=default; set sql_mode=''; diff --git a/mysql-test/main/trigger_no_defaults-11698.test b/mysql-test/main/trigger_no_defaults-11698.test index c10bec68314..86a7a436ad0 100644 --- a/mysql-test/main/trigger_no_defaults-11698.test +++ b/mysql-test/main/trigger_no_defaults-11698.test @@ -19,7 +19,7 @@ delimiter ;| insert t1 (b) values (10); --error ER_NO_DEFAULT_FOR_FIELD insert t1 (b) values (20); -# arguably the statement below should fail too +--error ER_BAD_NULL_ERROR insert t1 (b) values (30); select * from t1; drop table t1; diff --git a/mysql-test/main/trigger_null-8605.result b/mysql-test/main/trigger_null-8605.result index 10315988708..6480fbf9a7e 100644 --- a/mysql-test/main/trigger_null-8605.result +++ b/mysql-test/main/trigger_null-8605.result @@ -364,3 +364,28 @@ create trigger tr before update on t1 for each row set @a = 1; insert into t1 (pk, i) values (null, null); ERROR 23000: Column 'pk' cannot be null drop table t1; +# +# MDEV-19761 Before Trigger not processed for Not Null Columns if no explicit value and no DEFAULT +# +create table t1( id int, rate int not null); +create trigger test_trigger before insert on t1 for each row +set new.rate=if(new.rate is null,10,new.rate); +insert into t1 (id) values (1); +insert into t1 values (2,3); +select * from t1; +id rate +1 10 +2 3 +create or replace trigger test_trigger before insert on t1 for each row +if new.rate is null then set new.rate = 15; end if; +$$ +insert into t1 (id) values (3); +insert into t1 values (4,5); +select * from t1; +id rate +1 10 +2 3 +3 15 +4 5 +drop table t1; +# End of 10.5 tests diff --git a/mysql-test/main/trigger_null-8605.test b/mysql-test/main/trigger_null-8605.test index 7645b61f5ad..e33f17151bf 100644 --- a/mysql-test/main/trigger_null-8605.test +++ b/mysql-test/main/trigger_null-8605.test @@ -391,3 +391,28 @@ create trigger tr before update on t1 for each row set @a = 1; --error ER_BAD_NULL_ERROR insert into t1 (pk, i) values (null, null); drop table t1; + +--echo # +--echo # MDEV-19761 Before Trigger not processed for Not Null Columns if no explicit value and no DEFAULT +--echo # +create table t1( id int, rate int not null); +create trigger test_trigger before insert on t1 for each row + set new.rate=if(new.rate is null,10,new.rate); + +insert into t1 (id) values (1); +insert into t1 values (2,3); +select * from t1; + +delimiter $$; +create or replace trigger test_trigger before insert on t1 for each row + if new.rate is null then set new.rate = 15; end if; +$$ +delimiter ;$$ + +insert into t1 (id) values (3); +insert into t1 values (4,5); +select * from t1; + +drop table t1; + +--echo # End of 10.5 tests diff --git a/sql/field.h b/sql/field.h index 3894c22e6da..09b9f895273 100644 --- a/sql/field.h +++ b/sql/field.h @@ -5846,7 +5846,7 @@ uint pack_length_to_packflag(uint type); enum_field_types get_blob_type_from_length(ulong length); int set_field_to_null(Field *field); int set_field_to_null_with_conversions(Field *field, bool no_conversions); -int convert_null_to_field_value_or_error(Field *field); +int convert_null_to_field_value_or_error(Field *field, uint err); bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name, enum_vcol_info_type type, Alter_info *alter_info= NULL); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 92e7551c00b..dcbb6b39a31 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -126,7 +126,7 @@ static int set_bad_null_error(Field *field, int err) return 0; case CHECK_FIELD_ERROR_FOR_NULL: if (!field->table->in_use->no_errors) - my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name.str); + my_error(err, MYF(0), field->field_name.str); return -1; } DBUG_ASSERT(0); // impossible @@ -164,7 +164,7 @@ int set_field_to_null(Field *field) If no_conversion was not set, an error message is printed */ -int convert_null_to_field_value_or_error(Field *field) +int convert_null_to_field_value_or_error(Field *field, uint err) { if (field->type() == MYSQL_TYPE_TIMESTAMP) { @@ -179,7 +179,7 @@ int convert_null_to_field_value_or_error(Field *field) field->table->auto_increment_field_not_null= FALSE; return 0; // field is set in fill_record() } - return set_bad_null_error(field, ER_BAD_NULL_ERROR); + return set_bad_null_error(field, err); } /** @@ -216,7 +216,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions) if (no_conversions) return -1; - return convert_null_to_field_value_or_error(field); + return convert_null_to_field_value_or_error(field, ER_BAD_NULL_ERROR); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index aaa86e7bfa0..bb73dcef975 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8622,7 +8622,6 @@ void switch_to_nullable_trigger_fields(List &items, TABLE *table) while ((item= it++)) item->walk(&Item::switch_to_nullable_fields_processor, 1, field); - table->triggers->reset_extra_null_bitmap(); } } @@ -8676,8 +8675,14 @@ static bool not_null_fields_have_null_values(TABLE *table) swap_variables(uint32, of->flags, ff->flags); if (ff->is_real_null()) { + uint err= ER_BAD_NULL_ERROR; + if (ff->flags & NO_DEFAULT_VALUE_FLAG && !ff->has_explicit_value()) + { + err= ER_NO_DEFAULT_FOR_FIELD; + table->in_use->count_cuted_fields= CHECK_FIELD_WARN; + } ff->set_notnull(); // for next row WHERE condition in UPDATE - if (convert_null_to_field_value_or_error(of) || thd->is_error()) + if (convert_null_to_field_value_or_error(of, err) || thd->is_error()) return true; } } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index fa677feb551..d85a04aa9bb 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -722,8 +722,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->mark_columns_needed_for_delete(); } - if ((table->file->ha_table_flags() & HA_CAN_FORCE_BULK_DELETE) && - !table->prepare_triggers_for_delete_stmt_or_event()) + if (!table->prepare_triggers_for_delete_stmt_or_event() && + table->file->ha_table_flags() & HA_CAN_FORCE_BULK_DELETE) will_batch= !table->file->start_bulk_delete(); /* diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index acc841e27f0..2a978640122 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1019,7 +1019,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, INSERT INTO t1 (fields) VALUES ... INSERT INTO t1 VALUES () */ - restore_record(table,s->default_values); // Get empty record + restore_default_record_for_insert(table); table->reset_default_fields(); if (unlikely(fill_record_n_invoke_before_triggers(thd, table, fields, @@ -1048,7 +1048,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, */ if (thd->lex->used_tables || // Column used in values() table->s->visible_fields != table->s->fields) - restore_record(table,s->default_values); // Get empty record + restore_default_record_for_insert(table); else { TABLE_SHARE *share= table->s; @@ -1085,24 +1085,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, } } - /* - with triggers a field can get a value *conditionally*, so we have to - repeat has_no_default_value() check for every row - */ - if (table->triggers && - table->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE)) - { - for (Field **f=table->field ; *f ; f++) - { - if (unlikely(!(*f)->has_explicit_value() && - has_no_default_value(thd, *f, table_list))) - { - error= 1; - goto values_loop_end; - } - } - } - if ((res= table_list->view_check_option(thd, (values_list.elements == 1 ? 0 : @@ -4081,7 +4063,7 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) */ table->file->ha_start_bulk_insert((ha_rows) 0); } - restore_record(table,s->default_values); // Get empty record + restore_default_record_for_insert(table); table->reset_default_fields(); table->next_number_field=table->found_next_number_field; @@ -4226,7 +4208,7 @@ int select_insert::send_data(List &values) originally touched by INSERT ... SELECT, so we have to restore their original values for the next row. */ - restore_record(table, s->default_values); + restore_default_record_for_insert(table); } if (table->next_number_field) { diff --git a/sql/sql_insert.h b/sql/sql_insert.h index 80666a81c50..9aa234b715e 100644 --- a/sql/sql_insert.h +++ b/sql/sql_insert.h @@ -46,6 +46,13 @@ void kill_delayed_threads(void); bool binlog_create_table(THD *thd, TABLE *table, bool replace); bool binlog_drop_table(THD *thd, TABLE *table); +static inline void restore_default_record_for_insert(TABLE *t) +{ + restore_record(t,s->default_values); + if (t->triggers) + t->triggers->default_extra_null_bitmap(); +} + #ifdef EMBEDDED_LIBRARY inline void kill_delayed_threads(void) {} #endif diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 3ccb6f48994..778ee498e41 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -23,7 +23,6 @@ #include "sql_priv.h" #include "unireg.h" #include "sql_load.h" -#include "sql_load.h" #include "sql_cache.h" // query_cache_* #include "sql_base.h" // fill_record_n_invoke_before_triggers #include @@ -1004,8 +1003,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, read_info.row_end[0]=0; #endif - restore_record(table, s->default_values); - + restore_default_record_for_insert(table); while ((item= it++)) { Load_data_outvar *dst= item->get_load_data_outvar(); @@ -1118,8 +1116,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, thd->progress.max_counter); } } - restore_record(table, s->default_values); + restore_default_record_for_insert(table); while ((item= it++)) { uint length; @@ -1273,8 +1271,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, } #endif - restore_record(table, s->default_values); - + restore_default_record_for_insert(table); while ((item= it++)) { /* If this line is to be skipped we don't want to fill field or var */ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index f35a07347fe..f85faff37ac 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1297,8 +1297,9 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table) { int null_bytes= (table->s->fields - table->s->null_fields + 7)/8; - if (!(extra_null_bitmap= (uchar*)alloc_root(&table->mem_root, null_bytes))) + if (!(extra_null_bitmap= (uchar*)alloc_root(&table->mem_root, 2*null_bytes))) return 1; + extra_null_bitmap_init= extra_null_bitmap + null_bytes; if (!(record0_field= (Field **)alloc_root(&table->mem_root, (table->s->fields + 1) * sizeof(Field*)))) @@ -1323,13 +1324,17 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table) null_ptr++, null_bit= 1; else null_bit*= 2; + if (f->flags & NO_DEFAULT_VALUE_FLAG) + f->set_null(); + else + f->set_notnull(); } else *trg_fld= *fld; } *trg_fld= 0; DBUG_ASSERT(null_ptr <= extra_null_bitmap + null_bytes); - bzero(extra_null_bitmap, null_bytes); + memcpy(extra_null_bitmap_init, extra_null_bitmap, null_bytes); } else { diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 101784ee776..685f4d15b3b 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -147,7 +147,7 @@ class Table_triggers_list: public Sql_alloc BEFORE INSERT/UPDATE triggers. */ Field **record0_field; - uchar *extra_null_bitmap; + uchar *extra_null_bitmap, *extra_null_bitmap_init; /** Copy of TABLE::Field array with field pointers set to TABLE::record[1] buffer instead of TABLE::record[0] (used for OLD values in on UPDATE @@ -211,8 +211,8 @@ public: /* End of character ser context. */ Table_triggers_list(TABLE *table_arg) - :record0_field(0), extra_null_bitmap(0), record1_field(0), - trigger_table(table_arg), + :record0_field(0), extra_null_bitmap(0), extra_null_bitmap_init(0), + record1_field(0), trigger_table(table_arg), m_has_unparseable_trigger(false), count(0) { bzero((char *) triggers, sizeof(triggers)); @@ -276,11 +276,15 @@ public: TABLE_LIST *table_list); Field **nullable_fields() { return record0_field; } - void reset_extra_null_bitmap() + void clear_extra_null_bitmap() { - size_t null_bytes= (trigger_table->s->fields - - trigger_table->s->null_fields + 7)/8; - bzero(extra_null_bitmap, null_bytes); + if (size_t null_bytes= extra_null_bitmap_init - extra_null_bitmap) + bzero(extra_null_bitmap, null_bytes); + } + void default_extra_null_bitmap() + { + if (size_t null_bytes= extra_null_bitmap_init - extra_null_bitmap) + memcpy(extra_null_bitmap, extra_null_bitmap_init, null_bytes); } Trigger *find_trigger(const LEX_CSTRING *name, bool remove_from_list); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 9dfb681b119..f2cea510ce7 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -996,8 +996,8 @@ update_begin: goto update_end; } - if ((table->file->ha_table_flags() & HA_CAN_FORCE_BULK_UPDATE) && - !table->prepare_triggers_for_update_stmt_or_event()) + if (!table->prepare_triggers_for_update_stmt_or_event() && + table->file->ha_table_flags() & HA_CAN_FORCE_BULK_UPDATE) will_batch= !table->file->start_bulk_update(); /* diff --git a/sql/table.cc b/sql/table.cc index b18ee64f480..0aad7ae24e1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -9140,8 +9140,8 @@ void TABLE::prepare_triggers_for_insert_stmt_or_event() { if (triggers) { - if (triggers->has_triggers(TRG_EVENT_DELETE, - TRG_ACTION_AFTER)) + triggers->clear_extra_null_bitmap(); + if (triggers->has_triggers(TRG_EVENT_DELETE, TRG_ACTION_AFTER)) { /* The table has AFTER DELETE triggers that might access to @@ -9150,8 +9150,7 @@ void TABLE::prepare_triggers_for_insert_stmt_or_event() */ (void) file->extra(HA_EXTRA_DELETE_CANNOT_BATCH); } - if (triggers->has_triggers(TRG_EVENT_UPDATE, - TRG_ACTION_AFTER)) + if (triggers->has_triggers(TRG_EVENT_UPDATE, TRG_ACTION_AFTER)) { /* The table has AFTER UPDATE triggers that might access to subject @@ -9166,17 +9165,19 @@ void TABLE::prepare_triggers_for_insert_stmt_or_event() bool TABLE::prepare_triggers_for_delete_stmt_or_event() { - if (triggers && - triggers->has_triggers(TRG_EVENT_DELETE, - TRG_ACTION_AFTER)) + if (triggers) { - /* - The table has AFTER DELETE triggers that might access to subject table - and therefore might need delete to be done immediately. So we turn-off - the batching. - */ - (void) file->extra(HA_EXTRA_DELETE_CANNOT_BATCH); - return TRUE; + triggers->clear_extra_null_bitmap(); + if (triggers->has_triggers(TRG_EVENT_DELETE, TRG_ACTION_AFTER)) + { + /* + The table has AFTER DELETE triggers that might access to subject table + and therefore might need delete to be done immediately. So we turn-off + the batching. + */ + (void) file->extra(HA_EXTRA_DELETE_CANNOT_BATCH); + return TRUE; + } } return FALSE; } @@ -9184,17 +9185,19 @@ bool TABLE::prepare_triggers_for_delete_stmt_or_event() bool TABLE::prepare_triggers_for_update_stmt_or_event() { - if (triggers && - triggers->has_triggers(TRG_EVENT_UPDATE, - TRG_ACTION_AFTER)) + if (triggers) { - /* - The table has AFTER UPDATE triggers that might access to subject - table and therefore might need update to be done immediately. - So we turn-off the batching. - */ - (void) file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH); - return TRUE; + triggers->clear_extra_null_bitmap(); + if (triggers->has_triggers(TRG_EVENT_UPDATE, TRG_ACTION_AFTER)) + { + /* + The table has AFTER UPDATE triggers that might access to subject + table and therefore might need update to be done immediately. + So we turn-off the batching. + */ + (void) file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH); + return TRUE; + } } return FALSE; } From b87c1b06dceaa8f7db7fc900931829aef4421713 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 18 Jan 2025 08:10:49 +0100 Subject: [PATCH 045/118] MDEV-29968 update test results followup for 350cc77fee66 --- mysql-test/suite/s3/mysqldump.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/s3/mysqldump.result b/mysql-test/suite/s3/mysqldump.result index 78d97874c87..47adac57e23 100644 --- a/mysql-test/suite/s3/mysqldump.result +++ b/mysql-test/suite/s3/mysqldump.result @@ -18,7 +18,7 @@ alter table t1 engine=S3; ### /*M!999999\- enable the sandbox mode */ /*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; +/*!40101 SET character_set_client = utf8mb4 */; CREATE TABLE `t1` ( `pk` int(11) NOT NULL, `a` int(11) DEFAULT NULL, From b1f57a98a8fe1d79e3d1b827501383a19301d6fa Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 18 Jan 2025 15:07:53 +0100 Subject: [PATCH 046/118] cleanup: Alter_table_ctx::Alter_table_ctx() --- sql/sql_alter.cc | 22 ++++------------------ sql/sql_alter.h | 16 ++++++++-------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index dc98f9c8d93..d8cb7e8f341 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -297,16 +297,8 @@ uint Alter_info::check_vcol_field(Item_field *item) const Alter_table_ctx::Alter_table_ctx() - : implicit_default_value_error_field(NULL), - error_if_not_empty(false), - tables_opened(0), - db(null_clex_str), table_name(null_clex_str), alias(null_clex_str), - new_db(null_clex_str), new_name(null_clex_str), new_alias(null_clex_str), - fk_error_if_delete_row(false), fk_error_id(NULL), - fk_error_table(NULL), modified_primary_key(false) -#ifdef DBUG_ASSERT_EXISTS - , tmp_table(false) -#endif + : db(null_clex_str), table_name(null_clex_str), alias(null_clex_str), + new_db(null_clex_str), new_name(null_clex_str), new_alias(null_clex_str) { } @@ -319,14 +311,8 @@ Alter_table_ctx::Alter_table_ctx(THD *thd, TABLE_LIST *table_list, uint tables_opened_arg, const LEX_CSTRING *new_db_arg, const LEX_CSTRING *new_name_arg) - : implicit_default_value_error_field(NULL), error_if_not_empty(false), - tables_opened(tables_opened_arg), - new_db(*new_db_arg), new_name(*new_name_arg), - fk_error_if_delete_row(false), fk_error_id(NULL), - fk_error_table(NULL), modified_primary_key(false) -#ifdef DBUG_ASSERT_EXISTS - , tmp_table(false) -#endif + : tables_opened(tables_opened_arg), + new_db(*new_db_arg), new_name(*new_name_arg) { /* Assign members db, table_name, new_db and new_name diff --git a/sql/sql_alter.h b/sql/sql_alter.h index 65643eac46f..c5e6cb9ba34 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -306,9 +306,9 @@ public: void report_implicit_default_value_error(THD *thd, const TABLE_SHARE *) const; public: - Create_field *implicit_default_value_error_field; - bool error_if_not_empty; - uint tables_opened; + Create_field *implicit_default_value_error_field= NULL; + bool error_if_not_empty= false; + uint tables_opened= 0; LEX_CSTRING db; LEX_CSTRING table_name; LEX_CSTRING alias; @@ -322,12 +322,12 @@ public: of table to the new version ER_FK_CANNOT_DELETE_PARENT error should be emitted. */ - bool fk_error_if_delete_row; + bool fk_error_if_delete_row= false; /** Name of foreign key for the above error. */ - const char *fk_error_id; + const char *fk_error_id= NULL; /** Name of table for the above error. */ - const char *fk_error_table; - bool modified_primary_key; + const char *fk_error_table= NULL; + bool modified_primary_key= false; private: char new_filename[FN_REFLEN + 1]; @@ -339,7 +339,7 @@ private: #ifdef DBUG_ASSERT_EXISTS /** Indicates that we are altering temporary table. Used only in asserts. */ - bool tmp_table; + bool tmp_table= false; #endif Alter_table_ctx &operator=(const Alter_table_ctx &rhs); // not implemented From 782c4b94f08ef50f5f86e70c14a601e20ca72f1a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 18 Jan 2025 15:11:12 +0100 Subject: [PATCH 047/118] MDEV-25654 only force HA_KEY_ALG_HASH for fast alter partition not for any ALTER TABLE without ALTER_CHANGE_COLUMN. This fixes galera_sr.MDEV-28971 test followup for 0dcd30197ade --- mysql-test/main/long_unique_bugs.result | 6 ++++++ mysql-test/main/long_unique_bugs.test | 5 +++++ sql/sql_alter.h | 1 + sql/sql_table.cc | 25 +++++++++---------------- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index 1caec209d9f..5ee8b65fbf6 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -741,4 +741,10 @@ insert into t1 select seq from seq_1_to_100; alter table t1 add partition (partition p3 values less than (maxvalue)); alter table t1 force; drop table t1; +# veirfy that duplicate has unique is detected +create table t1 (a blob unique); +alter table t1 add constraint constraint_1 unique (a); +Warnings: +Note 1831 Duplicate index `constraint_1`. This is deprecated and will be disallowed in a future release +drop table t1; # End of 10.5 tests diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 6ad59fe6495..3fbe2a6b777 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -721,4 +721,9 @@ alter table t1 force; drop table t1; +--echo # veirfy that duplicate has unique is detected +create table t1 (a blob unique); +alter table t1 add constraint constraint_1 unique (a); +drop table t1; + --echo # End of 10.5 tests diff --git a/sql/sql_alter.h b/sql/sql_alter.h index c5e6cb9ba34..5e7f59650b2 100644 --- a/sql/sql_alter.h +++ b/sql/sql_alter.h @@ -328,6 +328,7 @@ public: /** Name of table for the above error. */ const char *fk_error_table= NULL; bool modified_primary_key= false; + bool fast_alter_partition= false; private: char new_filename[FN_REFLEN + 1]; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3563c0fa982..aec81d8941e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9276,19 +9276,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, LEX_CSTRING tmp_name; bzero((char*) &key_create_info, sizeof(key_create_info)); if (key_info->algorithm == HA_KEY_ALG_LONG_HASH) - key_info->algorithm= (alter_info->flags & ALTER_CHANGE_COLUMN) ? - HA_KEY_ALG_UNDEF : HA_KEY_ALG_HASH; + key_info->algorithm= alter_ctx->fast_alter_partition ? + HA_KEY_ALG_HASH : HA_KEY_ALG_UNDEF; /* - This one goes to mysql_prepare_create_table(): - - key_info->algorithm= key->key_create_info.algorithm; - - For HA_KEY_ALG_LONG_HASH if we didn't change ANY column, we pass - HA_KEY_ALG_HASH to ensure mysql_prepare_create_table() does add_hash_field(). - This protects fast alter partition from losing hash properties. - In case of any column changes we drop algorithm to HA_KEY_ALG_UNDEF and - let decide mysql_prepare_create_table() if the hash field is needed - depending on new types. + For fast alter partition we set HA_KEY_ALG_HASH above to make sure it + doesn't lose the hash property. + Otherwise we let mysql_prepare_create_table() decide if the hash field + is needed depending on the (possibly changed) data types. */ key_create_info.algorithm= key_info->algorithm; /* @@ -10317,7 +10311,6 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db, TABLE *table, *new_table= nullptr; #ifdef WITH_PARTITION_STORAGE_ENGINE bool partition_changed= false; - bool fast_alter_partition= false; #endif /* Create .FRM for new version of table with a temporary name. @@ -10844,7 +10837,7 @@ do_continue:; Partitioning: part_info is prepared and returned via thd->work_part_info */ if (prep_alter_part_table(thd, table, alter_info, create_info, - &partition_changed, &fast_alter_partition)) + &partition_changed, &alter_ctx.fast_alter_partition)) { DBUG_RETURN(true); } @@ -10879,7 +10872,7 @@ do_continue:; Note, one can run a separate "ALTER TABLE t1 FORCE;" statement before or after the partition change ALTER statement to upgrade data types. */ - if (IF_PARTITIONING(!fast_alter_partition, 1)) + if (!alter_ctx.fast_alter_partition) Create_field::upgrade_data_types(alter_info->create_list); if (create_info->check_fields(thd, alter_info, @@ -10891,7 +10884,7 @@ do_continue:; promote_first_timestamp_column(&alter_info->create_list); #ifdef WITH_PARTITION_STORAGE_ENGINE - if (fast_alter_partition) + if (alter_ctx.fast_alter_partition) { /* ALGORITHM and LOCK clauses are generally not allowed by the From cbb24d9aa5978c1a2d008f9ebf208acd9ee9eaa9 Mon Sep 17 00:00:00 2001 From: ParadoxV5 Date: Thu, 16 Jan 2025 20:57:01 -0700 Subject: [PATCH 048/118] MDEV-35646: Limit `pseudo_thread_id` to `UINT32_MAX` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although the `my_thread_id` type is 64 bits, binlog format specs limits it to 32 bits in practice. (See also: MDEV-35706) The writable SQL variable `pseudo_thread_id` didnโ€™t realize this though and had a range of `ULONGLONG_MAX` (at least `UINT64_MAX` in C/C++). It consequentially accepted larger values silently, but only the lower 32 bits of whom gets binlogged; this could lead to inconsistency. Reviewed-by: Brandon Nesterenko --- include/my_pthread.h | 7 +++++++ mysql-test/suite/sys_vars/r/sysvars_server_embedded.result | 2 +- .../suite/sys_vars/r/sysvars_server_notembedded.result | 2 +- sql/mysqld.cc | 2 +- sql/sys_vars.cc | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/my_pthread.h b/include/my_pthread.h index 10cc2301ea6..519d1be1cb5 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -641,6 +641,13 @@ extern pthread_mutexattr_t my_errorcheck_mutexattr; #endif typedef uint64 my_thread_id; +/** + Long-standing formats (such as the client-server protocol and the binary log) + hard-coded `my_thread_id` to 32 bits in practice. (Though not all + `thread_id`s are typed as such, @ref my_thread_id itself among those.) + @see MDEV-35706 +*/ +#define MY_THREAD_ID_MAX UINT32_MAX extern void my_threadattr_global_init(void); extern my_bool my_thread_global_init(void); diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index a5a02bfa1bc..cdf6d210933 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2877,7 +2877,7 @@ VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT This variable is for internal server use NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 50dd4ae23a3..0af08d00c89 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -3037,7 +3037,7 @@ VARIABLE_SCOPE SESSION ONLY VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT This variable is for internal server use NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_MAX_VALUE 4294967295 NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d6dd8a566af..7a7c1f0491a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -9770,7 +9770,7 @@ void init_server_psi_keys(void) */ -static my_thread_id thread_id_max= UINT_MAX32; +static my_thread_id thread_id_max= MY_THREAD_ID_MAX; #include #include diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 93298ff7b04..a2058dee224 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1767,7 +1767,7 @@ Sys_pseudo_thread_id( "pseudo_thread_id", "This variable is for internal server use", SESSION_ONLY(pseudo_thread_id), - NO_CMD_LINE, VALID_RANGE(0, ULONGLONG_MAX), DEFAULT(0), + NO_CMD_LINE, VALID_RANGE(0, MY_THREAD_ID_MAX), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG); static bool From 8d6c9ef00112f8eddbcebb4f34902e1023f2a497 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 20 Dec 2024 14:14:28 +1100 Subject: [PATCH 049/118] MDEV-34925 Fix segv on thd in spider recovery. Create temporary thd whenever needed in spider xa commit / recovery. This prevents crash during recovery. --- .../spider/bugfix/r/mdev_27438.result | 6 +++ .../bugfix/r/mdev_27438_spider_table.result | 25 ++++++++++ .../spider/bugfix/t/mdev_27438.test | 22 ++++++++ .../bugfix/t/mdev_27438_spider_table.test | 38 ++++++++++++++ storage/spider/spd_trx.cc | 50 +++++++++++++------ 5 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_27438.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_27438_spider_table.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_27438.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_27438_spider_table.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27438.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27438.result new file mode 100644 index 00000000000..7a30b0d27db --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27438.result @@ -0,0 +1,6 @@ +install soname 'ha_spider'; +CREATE TABLE t1 (a INT) ENGINE=Innodb; +SET SESSION debug_dbug="+d,crash_commit_after_log"; +INSERT INTO t1 VALUES (1); +Got one of the listed errors +drop table t1; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27438_spider_table.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27438_spider_table.result new file mode 100644 index 00000000000..a3fc1de5767 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27438_spider_table.result @@ -0,0 +1,25 @@ +install soname 'ha_spider'; +set spider_same_server_link= 1; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t1 (a INT); +create table t2 (a int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +INSERT INTO t2 VALUES (1); +SET SESSION debug_dbug="+d,crash_commit_after_log"; +INSERT INTO t2 VALUES (2); +Got one of the listed errors +call mtr.add_suppression(".*\\[ERROR\\] mariadbd: Table './test/t1' is marked as crashed and should be repaired"); +call mtr.add_suppression(".*\\[Warning\\] Checking table: './test/t1'"); +set spider_same_server_link= 1; +select * from t2; +a +1 +2 +Warnings: +Error 1034 1 client is using or hasn't closed the table properly +Error 1034 Table is fixed +drop server srv; +drop table t1, t2; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27438.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27438.test new file mode 100644 index 00000000000..44b4e0be912 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27438.test @@ -0,0 +1,22 @@ +--source include/have_debug.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc +install soname 'ha_spider'; +CREATE TABLE t1 (a INT) ENGINE=Innodb; + +# crash the server. +--let $expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` +--let $expect_file_name= $MYSQLTEST_VARDIR/tmp/$expect_file_name.expect +--exec echo wait > $expect_file_name +SET SESSION debug_dbug="+d,crash_commit_after_log"; +--error 2006,2013 +INSERT INTO t1 VALUES (1); + +# restart the server +--exec echo restart >> $expect_file_name +--enable_reconnect +--source include/wait_until_connected_again.inc + +drop table t1; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27438_spider_table.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27438_spider_table.test new file mode 100644 index 00000000000..dff655141bb --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27438_spider_table.test @@ -0,0 +1,38 @@ +--source include/have_debug.inc +# Valgrind does not work well with test that crashes the server +--source include/not_valgrind.inc + +# Same as spider/bugfix.mdev_27438, but actually using a spider table. +install soname 'ha_spider'; +set spider_same_server_link= 1; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +CREATE TABLE t1 (a INT); +create table t2 (a int) ENGINE=Spider +COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +INSERT INTO t2 VALUES (1); + +# crash the server. +--let $expect_file_name= `select regexp_replace(@@tmpdir, '^.*/','')` +--let $expect_file_name= $MYSQLTEST_VARDIR/tmp/$expect_file_name.expect +--exec echo wait > $expect_file_name +SET SESSION debug_dbug="+d,crash_commit_after_log"; +--error 2006,2013 +INSERT INTO t2 VALUES (2); + +# restart the server +--exec echo restart >> $expect_file_name +--enable_reconnect +--source include/wait_until_connected_again.inc + +call mtr.add_suppression(".*\\[ERROR\\] mariadbd: Table './test/t1' is marked as crashed and should be repaired"); +call mtr.add_suppression(".*\\[Warning\\] Checking table: './test/t1'"); +set spider_same_server_link= 1; +--disable_ps_protocol +select * from t2; +--enable_ps_protocol +drop server srv; +drop table t1, t2; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index 6bbf0252619..6a76f03c1b0 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -2598,7 +2598,17 @@ int spider_internal_xa_commit_by_xid( SPIDER_Open_tables_backup open_tables_backup; bool table_xa_opened = FALSE; bool table_xa_member_opened = FALSE; + bool created_tmp_thd = FALSE; DBUG_ENTER("spider_internal_xa_commit_by_xid"); + if (!thd) + { + if (!(thd = spider_create_tmp_thd())) + { + error_num = HA_ERR_OUT_OF_MEM; + goto error; + } + created_tmp_thd= TRUE; + } /* select status @@ -2798,6 +2808,8 @@ xa_delete: goto error; spider_close_sys_table(thd, table_xa, &open_tables_backup, TRUE); table_xa_opened = FALSE; + if (created_tmp_thd) + spider_free_tmp_thd(thd); DBUG_RETURN(0); error: @@ -2806,6 +2818,8 @@ error: if (table_xa_member_opened) spider_close_sys_table(thd, table_xa_member, &open_tables_backup, TRUE); error_open_table: + if (created_tmp_thd) + spider_free_tmp_thd(thd); DBUG_RETURN(error_num); } @@ -2830,7 +2844,17 @@ int spider_internal_xa_rollback_by_xid( SPIDER_Open_tables_backup open_tables_backup; bool table_xa_opened = FALSE; bool table_xa_member_opened = FALSE; + bool created_tmp_thd= FALSE; DBUG_ENTER("spider_internal_xa_rollback_by_xid"); + if (!thd) + { + if (!(thd = spider_create_tmp_thd())) + { + error_num = HA_ERR_OUT_OF_MEM; + goto error; + } + created_tmp_thd= TRUE; + } /* select status @@ -3028,6 +3052,8 @@ xa_delete: goto error; spider_close_sys_table(thd, table_xa, &open_tables_backup, TRUE); table_xa_opened = FALSE; + if (created_tmp_thd) + spider_free_tmp_thd(thd); DBUG_RETURN(0); error: @@ -3036,6 +3062,8 @@ error: if (table_xa_member_opened) spider_close_sys_table(thd, table_xa_member, &open_tables_backup, TRUE); error_open_table: + if (created_tmp_thd) + spider_free_tmp_thd(thd); DBUG_RETURN(error_num); } @@ -3360,15 +3388,12 @@ int spider_xa_commit_by_xid( DBUG_ENTER("spider_xa_commit_by_xid"); if (!(trx = spider_get_trx(thd, TRUE, &error_num))) - goto error_get_trx; + DBUG_RETURN(error_num); - if ((error_num = spider_internal_xa_commit_by_xid(thd, trx, xid))) - goto error; + error_num = spider_internal_xa_commit_by_xid(thd, trx, xid); - DBUG_RETURN(0); - -error: -error_get_trx: + if (!thd) + spider_free_trx(trx, FALSE); DBUG_RETURN(error_num); } @@ -3382,15 +3407,12 @@ int spider_xa_rollback_by_xid( DBUG_ENTER("spider_xa_rollback_by_xid"); if (!(trx = spider_get_trx(thd, TRUE, &error_num))) - goto error_get_trx; + DBUG_RETURN(error_num); - if ((error_num = spider_internal_xa_rollback_by_xid(thd, trx, xid))) - goto error; + error_num = spider_internal_xa_rollback_by_xid(thd, trx, xid); - DBUG_RETURN(0); - -error: -error_get_trx: + if (!thd) + spider_free_trx(trx, FALSE); DBUG_RETURN(error_num); } From c05e7c4e0eff174a1f2b5e6efd53d80954f9e34b Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Wed, 4 Dec 2024 19:56:46 +0300 Subject: [PATCH 050/118] MDEV-35708 lock_rec_get_prev() returns only the first record lock It's supposed that the function gets the previous lock set on a record. But if there are several locks set on a record, it will return only the first one. Continue locks list iteration till the certain lock even if the certain bit in lock bitmap is set. --- storage/innobase/lock/lock0lock.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 94eeef57bd7..4601fb4394d 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -984,13 +984,14 @@ lock_rec_get_prev( ut_ad(!in_lock->is_table()); const page_id_t id{in_lock->un_member.rec_lock.page_id}; hash_cell_t *cell= lock_sys.hash_get(in_lock->type_mode).cell_get(id.fold()); + lock_t *prev_lock= nullptr; for (lock_t *lock= lock_sys_t::get_first(*cell, id); lock != in_lock; lock= lock_rec_get_next_on_page(lock)) if (lock_rec_get_nth_bit(lock, heap_no)) - return lock; + prev_lock= lock; - return nullptr; + return prev_lock; } /*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/ From 43c36b3c884f2ece37ab9c3475d27027a36fc9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 15 Jan 2025 09:44:30 +0200 Subject: [PATCH 051/118] MDEV-35852 : ASAN heap-use-after-free in WSREP_DEBUG after INSERT DELAYED Problem was that in case of INSERT DELAYED thd->query() is freed before we call trans_rollback where WSREP_DEBUG could access thd->query() in wsrep_thd_query(). Fix is to reset thd->query() to NULL in delayed_insert destructor after it is freed. There is already null guard at wsrep_thd_query(). Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-35852.result | 8 ++++++++ mysql-test/suite/galera/t/MDEV-35852.cnf | 4 ++++ mysql-test/suite/galera/t/MDEV-35852.test | 9 +++++++++ sql/handler.cc | 13 ++++++++----- sql/service_wsrep.cc | 4 +++- sql/sql_insert.cc | 1 + 6 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/galera/r/MDEV-35852.result create mode 100644 mysql-test/suite/galera/t/MDEV-35852.cnf create mode 100644 mysql-test/suite/galera/t/MDEV-35852.test diff --git a/mysql-test/suite/galera/r/MDEV-35852.result b/mysql-test/suite/galera/r/MDEV-35852.result new file mode 100644 index 00000000000..f9d07043cf9 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-35852.result @@ -0,0 +1,8 @@ +connection node_2; +connection node_1; +CREATE TABLE t (a INT) ENGINE=InnoDB; +INSERT DELAYED INTO t VALUES (); +ERROR HY000: DELAYED option not supported for table 't' +DROP TABLE t; +INSERT DELAYED t1 () VALUES (); +ERROR 42S02: Table 'test.t1' doesn't exist diff --git a/mysql-test/suite/galera/t/MDEV-35852.cnf b/mysql-test/suite/galera/t/MDEV-35852.cnf new file mode 100644 index 00000000000..ebd79612b81 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-35852.cnf @@ -0,0 +1,4 @@ +!include ../galera_2nodes.cnf + +[mysqld] +wsrep-debug=1 diff --git a/mysql-test/suite/galera/t/MDEV-35852.test b/mysql-test/suite/galera/t/MDEV-35852.test new file mode 100644 index 00000000000..6dce2974dd4 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-35852.test @@ -0,0 +1,9 @@ +--source include/galera_cluster.inc + +CREATE TABLE t (a INT) ENGINE=InnoDB; +--error ER_DELAYED_NOT_SUPPORTED +INSERT DELAYED INTO t VALUES (); +DROP TABLE t; + +--error ER_NO_SUCH_TABLE +INSERT DELAYED t1 () VALUES (); diff --git a/sql/handler.cc b/sql/handler.cc index 50bcf86f25c..a6e5043a636 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2158,8 +2158,10 @@ int ha_rollback_trans(THD *thd, bool all) my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; #ifdef WITH_WSREP - WSREP_WARN("handlerton rollback failed, thd %lld %lld conf %d SQL %s", + WSREP_WARN("handlerton rollback failed, thd %lld %lld " + "conf %d wsrep_err %s SQL %s", thd->thread_id, thd->query_id, thd->wsrep_trx().state(), + wsrep::to_c_string(thd->wsrep_cs().current_error()), thd->query()); #endif /* WITH_WSREP */ } @@ -2172,11 +2174,12 @@ int ha_rollback_trans(THD *thd, bool all) } #ifdef WITH_WSREP - if (thd->is_error()) + if (WSREP(thd) && thd->is_error()) { - WSREP_DEBUG("ha_rollback_trans(%lld, %s) rolled back: %s: %s; is_real %d", - thd->thread_id, all?"TRUE":"FALSE", wsrep_thd_query(thd), - thd->get_stmt_da()->message(), is_real_trans); + WSREP_DEBUG("ha_rollback_trans(%lld, %s) rolled back: msg %s is_real %d wsrep_err %s", + thd->thread_id, all? "TRUE" : "FALSE", + thd->get_stmt_da()->message(), is_real_trans, + wsrep::to_c_string(thd->wsrep_cs().current_error())); } // REPLACE|INSERT INTO ... SELECT uses TOI in consistency check diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index 6aab1bec99b..d1e0260d53c 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -1,4 +1,4 @@ -/* Copyright 2018-2024 Codership Oy +/* Copyright 2018-2025 Codership Oy 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 @@ -86,7 +86,9 @@ extern "C" const char *wsrep_thd_query(const THD *thd) return "SET PASSWORD"; /* fallthrough */ default: + { return (thd->query() ? thd->query() : "NULL"); + } } return "NULL"; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 2a978640122..0182ca0ee1b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2421,6 +2421,7 @@ public: delayed_insert_threads--; my_free(thd.query()); + thd.reset_query_inner(); thd.security_ctx->user= 0; thd.security_ctx->host= 0; } From d32ec7d48e1c942773da2a1a4d2233d755a8e58e Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Mon, 20 Jan 2025 12:14:46 +0100 Subject: [PATCH 052/118] MDEV-35852 : ASAN heap-use-after-free in WSREP_DEBUG after INSERT DELAYED Post-fix: remove unnecessary warning messages when wrep is not used. --- sql/handler.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index a6e5043a636..979e9315571 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2158,11 +2158,14 @@ int ha_rollback_trans(THD *thd, bool all) my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err); error=1; #ifdef WITH_WSREP - WSREP_WARN("handlerton rollback failed, thd %lld %lld " - "conf %d wsrep_err %s SQL %s", - thd->thread_id, thd->query_id, thd->wsrep_trx().state(), - wsrep::to_c_string(thd->wsrep_cs().current_error()), - thd->query()); + if (WSREP(thd)) + { + WSREP_WARN("handlerton rollback failed, thd %lld %lld " + "conf %d wsrep_err %s SQL %s", + thd->thread_id, thd->query_id, thd->wsrep_trx().state(), + wsrep::to_c_string(thd->wsrep_cs().current_error()), + thd->query()); + } #endif /* WITH_WSREP */ } status_var_increment(thd->status_var.ha_rollback_count); From b056ed6d985cf3b649a3b9f000ad228f543ff894 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 20 Jan 2025 14:07:23 +0100 Subject: [PATCH 053/118] MDEV-35891 mtr, Windows - fix multi-process append for stdout and stderr This backports https://github.com/mysql/mysql-server/commit/e2f685972985, which works around perl issue https://github.com/Perl/perl5/issues/17570 MySQL fix ensures that FILE_APPEND_DATA is used in redirected stdout/stderr open flags, rather than FILE_GENERIC_WRITE. Only this gives lossless append behavior, if multiple processes use the same file. --- .../lib/My/SafeProcess/safe_process_win.cc | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc index 8a5bb60a3f5..6e1fd414287 100644 --- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc @@ -152,6 +152,24 @@ void handle_signal (int signal) } } +/** + Sets the append flag (FILE_APPEND_DATA) so that the handle inherited by the + child process will be in append mode. + Workaround for perl bug https://github.com/Perl/perl5/issues/17570 +*/ +static void fix_file_append_flag_inheritance(DWORD std_handle) +{ + HANDLE old_handle = GetStdHandle(std_handle); + HANDLE new_handle = ReOpenFile(old_handle, FILE_APPEND_DATA, + FILE_SHARE_WRITE | FILE_SHARE_READ, 0); + if (new_handle != INVALID_HANDLE_VALUE) + { + SetHandleInformation(new_handle, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); + SetStdHandle(std_handle, new_handle); + CloseHandle(old_handle); + } +} + int main(int argc, const char** argv ) { @@ -270,6 +288,9 @@ int main(int argc, const char** argv ) SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + fix_file_append_flag_inheritance(STD_OUTPUT_HANDLE); + fix_file_append_flag_inheritance(STD_ERROR_HANDLE); + #if 0 /* Setup stdin, stdout and stderr redirect */ si.dwFlags= STARTF_USESTDHANDLES; From 0301ef38b4569c811a0813e49dfe585a7bd66f2b Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 21 Jan 2025 18:52:33 +0530 Subject: [PATCH 054/118] MDEV-35445 Disable foreign key column nullability check for strict sql mode - MDEV-34392(commit cc810e64d40367208b3f3f35c0277f0c8586a293) adds the check for nullability of foreign key column when foreign key relation is of UPDATE_CASCADE or UPDATE SET NULL. This check makes DDL fail when it violates foreign key nullability. This patch basically does the nullability check for foreign key column only for strict sql mode --- .../r/foreign_sql_mode,COPY,NON-STRICT.rdiff | 57 ++++++++ .../r/foreign_sql_mode,COPY,NOSTRICT.rdiff | 55 ++++++++ .../foreign_sql_mode,INPLACE,NON-STRICT.rdiff | 39 ++++++ .../suite/innodb/r/foreign_sql_mode.result | 65 +++++++++ .../innodb/t/foreign_sql_mode.combinations | 2 + .../suite/innodb/t/foreign_sql_mode.test | 129 ++++++++++++++++++ sql/sql_table.cc | 3 +- storage/innobase/dict/dict0crea.cc | 4 +- storage/innobase/handler/handler0alter.cc | 18 ++- 9 files changed, 364 insertions(+), 8 deletions(-) create mode 100644 mysql-test/suite/innodb/r/foreign_sql_mode,COPY,NON-STRICT.rdiff create mode 100644 mysql-test/suite/innodb/r/foreign_sql_mode,COPY,NOSTRICT.rdiff create mode 100644 mysql-test/suite/innodb/r/foreign_sql_mode,INPLACE,NON-STRICT.rdiff create mode 100644 mysql-test/suite/innodb/r/foreign_sql_mode.result create mode 100644 mysql-test/suite/innodb/t/foreign_sql_mode.combinations create mode 100644 mysql-test/suite/innodb/t/foreign_sql_mode.test diff --git a/mysql-test/suite/innodb/r/foreign_sql_mode,COPY,NON-STRICT.rdiff b/mysql-test/suite/innodb/r/foreign_sql_mode,COPY,NON-STRICT.rdiff new file mode 100644 index 00000000000..66e39ca633e --- /dev/null +++ b/mysql-test/suite/innodb/r/foreign_sql_mode,COPY,NON-STRICT.rdiff @@ -0,0 +1,57 @@ +--- foreign_sql_mode.result ++++ foreign_sql_mode,COPY,NON-STRICT.rdiff +@@ -3,14 +3,14 @@ + CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; + CREATE TABLE t2(f1 INT, FOREIGN KEY(f1) REFERENCES t1(f2) ON UPDATE CASCADE)ENGINE=InnoDB; + ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL; +-ERROR HY000: Column 'f1' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(1); + UPDATE t1 SET f2= NULL; ++ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE) + DELETE FROM t2; + SELECT * FROM t1; + f1 f2 +-1 NULL ++1 1 + UPDATE t1 SET f2 = NULL; + SELECT * FROM t1; + f1 f2 +@@ -20,7 +20,7 @@ + CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; + CREATE TABLE t2(f1 INT, f2 INT, FOREIGN KEY(f1) REFERENCES t1(f1) ON UPDATE SET NULL)ENGINE=InnoDB; + ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL; +-ERROR HY000: Column 'f1' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL ++ERROR HY000: Error on rename of 'OLD_FILE_NAME' to 'NEW_FILE_NAME' (errno: 150 "Foreign key constraint is incorrectly formed") + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(1, 1); + UPDATE t1 SET f1= 2; +@@ -32,7 +32,7 @@ + CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; + CREATE TABLE t2(f1 INT, f2 INT, FOREIGN KEY (f2) REFERENCES t1(f2) ON DELETE SET NULL)ENGINE=InnoDB; + ALTER TABLE t2 MODIFY COLUMN f2 INT NOT NULL; +-ERROR HY000: Column 'f2' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL ++ERROR HY000: Error on rename of 'OLD_FILE_NAME' to 'NEW_FILE_NAME' (errno: 150 "Foreign key constraint is incorrectly formed") + DROP TABLE t2, t1; + # modify parent column NULL ON UPDATE CASCADE child column NOT NULL + CREATE TABLE `t#1`(f1 INT, f2 INT NOT NULL, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +@@ -40,11 +40,10 @@ + FOREIGN KEY(f1) REFERENCES `t#1`(f2) + ON UPDATE CASCADE)ENGINE=InnoDB; + ALTER TABLE `t#1` MODIFY COLUMN f2 INT; +-ERROR HY000: Cannot change column 'f2': used in a foreign key constraint 't#2_ibfk_1' of table 'test.t#2' + INSERT INTO `t#1` VALUES(1, 1); + INSERT INTO `t#2` VALUES(1); + UPDATE `t#1` SET f2= NULL; +-ERROR 23000: Column 'f2' cannot be null ++ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t#2`, CONSTRAINT `t#2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t#1` (`f2`) ON UPDATE CASCADE) + DELETE FROM `t#2`; + SELECT * FROM `t#1`; + f1 f2 +@@ -60,6 +59,5 @@ + PRIMARY KEY(f1, f2), + FOREIGN KEY(f2, f3) REFERENCES t1(f2, f1) + ON UPDATE CASCADE)ENGINE=InnoDB; +-ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") + DROP TABLE IF EXISTS t2; + DROP TABLE IF EXISTS t1; diff --git a/mysql-test/suite/innodb/r/foreign_sql_mode,COPY,NOSTRICT.rdiff b/mysql-test/suite/innodb/r/foreign_sql_mode,COPY,NOSTRICT.rdiff new file mode 100644 index 00000000000..95df1bfa7d3 --- /dev/null +++ b/mysql-test/suite/innodb/r/foreign_sql_mode,COPY,NOSTRICT.rdiff @@ -0,0 +1,55 @@ +--- foreign_sql_mode.result 2025-01-21 17:23:46.014938931 +0530 ++++ foreign_sql_mode.reject 2025-01-21 17:24:11.783981181 +0530 +@@ -3,20 +3,20 @@ + CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; + CREATE TABLE t2(f1 INT, FOREIGN KEY(f1) REFERENCES t1(f2) ON UPDATE CASCADE)ENGINE=InnoDB; + ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL; +-ERROR HY000: Column 'f1' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(1); + UPDATE t1 SET f2= NULL; ++ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE) + DELETE FROM t2; + SELECT * FROM t1; + f1 f2 +-1 NULL ++1 1 + DROP TABLE t2, t1; + # modify child column NOT NULL ON UPDATE SET NULL + CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; + CREATE TABLE t2(f1 INT, f2 INT, FOREIGN KEY(f1) REFERENCES t1(f1) ON UPDATE SET NULL)ENGINE=InnoDB; + ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL; +-ERROR HY000: Column 'f1' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL ++ERROR HY000: Error on rename of 'OLD_FILE_NAME' to 'NEW_FILE_NAME' (errno: 150 "Foreign key constraint is incorrectly formed") + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(1, 1); + UPDATE t1 SET f1= 2; +@@ -28,7 +28,7 @@ + CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; + CREATE TABLE t2(f1 INT, f2 INT, FOREIGN KEY (f2) REFERENCES t1(f2) ON DELETE SET NULL)ENGINE=InnoDB; + ALTER TABLE t2 MODIFY COLUMN f2 INT NOT NULL; +-ERROR HY000: Column 'f2' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL ++ERROR HY000: Error on rename of 'OLD_FILE_NAME' to 'NEW_FILE_NAME' (errno: 150 "Foreign key constraint is incorrectly formed") + DROP TABLE t2, t1; + # modify parent column NULL ON UPDATE CASCADE child column NOT NULL + CREATE TABLE `t#1`(f1 INT, f2 INT NOT NULL, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +@@ -36,11 +36,10 @@ + FOREIGN KEY(f1) REFERENCES `t#1`(f2) + ON UPDATE CASCADE)ENGINE=InnoDB; + ALTER TABLE `t#1` MODIFY COLUMN f2 INT; +-ERROR HY000: Cannot change column 'f2': used in a foreign key constraint 't#2_ibfk_1' of table 'test.t#2' + INSERT INTO `t#1` VALUES(1, 1); + INSERT INTO `t#2` VALUES(1); + UPDATE `t#1` SET f2= NULL; +-ERROR 23000: Column 'f2' cannot be null ++ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t#2`, CONSTRAINT `t#2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t#1` (`f2`) ON UPDATE CASCADE) + DELETE FROM `t#2`; + SELECT * FROM `t#1`; + f1 f2 +@@ -56,6 +55,5 @@ + PRIMARY KEY(f1, f2), + FOREIGN KEY(f2, f3) REFERENCES t1(f2, f1) + ON UPDATE CASCADE)ENGINE=InnoDB; +-ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") + DROP TABLE IF EXISTS t2; + DROP TABLE IF EXISTS t1; diff --git a/mysql-test/suite/innodb/r/foreign_sql_mode,INPLACE,NON-STRICT.rdiff b/mysql-test/suite/innodb/r/foreign_sql_mode,INPLACE,NON-STRICT.rdiff new file mode 100644 index 00000000000..8919244e810 --- /dev/null +++ b/mysql-test/suite/innodb/r/foreign_sql_mode,INPLACE,NON-STRICT.rdiff @@ -0,0 +1,39 @@ +--- foreign_sql_mode.result ++++ foreign_sql_mode,INPLACE,NON-STRICT.rdiff +@@ -3,14 +3,14 @@ + CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; + CREATE TABLE t2(f1 INT, FOREIGN KEY(f1) REFERENCES t1(f2) ON UPDATE CASCADE)ENGINE=InnoDB; + ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL; +-ERROR HY000: Column 'f1' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(1); + UPDATE t1 SET f2= NULL; ++ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE) + DELETE FROM t2; + SELECT * FROM t1; + f1 f2 +-1 NULL ++1 1 + UPDATE t1 SET f2 = NULL; + SELECT * FROM t1; + f1 f2 +@@ -40,11 +40,10 @@ + FOREIGN KEY(f1) REFERENCES `t#1`(f2) + ON UPDATE CASCADE)ENGINE=InnoDB; + ALTER TABLE `t#1` MODIFY COLUMN f2 INT; +-ERROR HY000: Cannot change column 'f2': used in a foreign key constraint 't#2_ibfk_1' of table 'test.t#2' + INSERT INTO `t#1` VALUES(1, 1); + INSERT INTO `t#2` VALUES(1); + UPDATE `t#1` SET f2= NULL; +-ERROR 23000: Column 'f2' cannot be null ++ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t#2`, CONSTRAINT `t#2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t#1` (`f2`) ON UPDATE CASCADE) + DELETE FROM `t#2`; + SELECT * FROM `t#1`; + f1 f2 +@@ -60,6 +59,5 @@ + PRIMARY KEY(f1, f2), + FOREIGN KEY(f2, f3) REFERENCES t1(f2, f1) + ON UPDATE CASCADE)ENGINE=InnoDB; +-ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") + DROP TABLE IF EXISTS t2; + DROP TABLE IF EXISTS t1; diff --git a/mysql-test/suite/innodb/r/foreign_sql_mode.result b/mysql-test/suite/innodb/r/foreign_sql_mode.result new file mode 100644 index 00000000000..7044e402745 --- /dev/null +++ b/mysql-test/suite/innodb/r/foreign_sql_mode.result @@ -0,0 +1,65 @@ +call mtr.add_suppression("InnoDB: In ALTER TABLE .* has or is referenced in foreign key constraints which are not compatible with the new table definition."); +# modify child column NOT NULL on UPDATE CASCADE..parent column NULL +CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT, FOREIGN KEY(f1) REFERENCES t1(f2) ON UPDATE CASCADE)ENGINE=InnoDB; +ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL; +ERROR HY000: Column 'f1' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t2 VALUES(1); +UPDATE t1 SET f2= NULL; +DELETE FROM t2; +SELECT * FROM t1; +f1 f2 +1 NULL +UPDATE t1 SET f2 = NULL; +SELECT * FROM t1; +f1 f2 +1 NULL +DROP TABLE t2, t1; +# modify child column NOT NULL ON UPDATE SET NULL +CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT, f2 INT, FOREIGN KEY(f1) REFERENCES t1(f1) ON UPDATE SET NULL)ENGINE=InnoDB; +ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL; +ERROR HY000: Column 'f1' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t2 VALUES(1, 1); +UPDATE t1 SET f1= 2; +SELECT * FROM t2; +f1 f2 +NULL 1 +DROP TABLE t2, t1; +# modify child column NOT NULL ON DELETE SET NULL +CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT, f2 INT, FOREIGN KEY (f2) REFERENCES t1(f2) ON DELETE SET NULL)ENGINE=InnoDB; +ALTER TABLE t2 MODIFY COLUMN f2 INT NOT NULL; +ERROR HY000: Column 'f2' cannot be NOT NULL: needed in a foreign key constraint 't2_ibfk_1' SET NULL +DROP TABLE t2, t1; +# modify parent column NULL ON UPDATE CASCADE child column NOT NULL +CREATE TABLE `t#1`(f1 INT, f2 INT NOT NULL, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +CREATE TABLE `t#2`(f1 INT NOT NULL, +FOREIGN KEY(f1) REFERENCES `t#1`(f2) +ON UPDATE CASCADE)ENGINE=InnoDB; +ALTER TABLE `t#1` MODIFY COLUMN f2 INT; +ERROR HY000: Cannot change column 'f2': used in a foreign key constraint 't#2_ibfk_1' of table 'test.t#2' +INSERT INTO `t#1` VALUES(1, 1); +INSERT INTO `t#2` VALUES(1); +UPDATE `t#1` SET f2= NULL; +ERROR 23000: Column 'f2' cannot be null +DELETE FROM `t#2`; +SELECT * FROM `t#1`; +f1 f2 +1 1 +DROP TABLE `t#2`, `t#1`; +CREATE TABLE t1(f1 INT NOT NULL AUTO_INCREMENT, +f2 INT DEFAULT NULL, +PRIMARY KEY(f1), +FOREIGN KEY(f2) REFERENCES t1(f1))ENGINE=InnoDB; +CREATE TABLE t2 (f1 INT NOT NULL, +f2 INT NOT NULL, +f3 INT DEFAULT NULL, +PRIMARY KEY(f1, f2), +FOREIGN KEY(f2, f3) REFERENCES t1(f2, f1) +ON UPDATE CASCADE)ENGINE=InnoDB; +ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t1; diff --git a/mysql-test/suite/innodb/t/foreign_sql_mode.combinations b/mysql-test/suite/innodb/t/foreign_sql_mode.combinations new file mode 100644 index 00000000000..e84e17b06ac --- /dev/null +++ b/mysql-test/suite/innodb/t/foreign_sql_mode.combinations @@ -0,0 +1,2 @@ +[COPY] +[INPLACE] diff --git a/mysql-test/suite/innodb/t/foreign_sql_mode.test b/mysql-test/suite/innodb/t/foreign_sql_mode.test new file mode 100644 index 00000000000..1569348df07 --- /dev/null +++ b/mysql-test/suite/innodb/t/foreign_sql_mode.test @@ -0,0 +1,129 @@ +--source include/have_innodb.inc +--source alter_sql_mode.inc +call mtr.add_suppression("InnoDB: In ALTER TABLE .* has or is referenced in foreign key constraints which are not compatible with the new table definition."); + +let $combination=`select regexp_replace('$MTR_COMBINATIONS', 'innodb,\|,innodb', '')`; + +let $copy_algo=`select ((strcmp(substring_index('$combination', ",", 1), "COPY") = 0) or (strcmp(substring_index('$combination', ",", -1), "COPY") = 0))`; + +let $inplace_algo=`select ((strcmp(substring_index('$combination', ",", 1), "INPLACE") = 0) or (strcmp(substring_index('$combination', ",", -1), "INPLACE") = 0))`; + +let $algorithm=COPY; +if ($inplace_algo) +{ + let $algorithm=INPLACE; +} +let $sql_mode = `SELECT @@SQL_MODE`; +let $error_code = 0; +if ($sql_mode == "STRICT_TRANS_TABLES") { + let $error_code = ER_FK_COLUMN_NOT_NULL; +} + +--echo # modify child column NOT NULL on UPDATE CASCADE..parent column NULL +CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT, FOREIGN KEY(f1) REFERENCES t1(f2) ON UPDATE CASCADE)ENGINE=InnoDB; +replace_result ,ALGORITHM=COPY '' ,ALGORITHM=INPLACE ''; +--error $error_code +eval ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL,ALGORITHM=$algorithm; +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t2 VALUES(1); + +let $dml_error_code = ER_ROW_IS_REFERENCED_2; +if ($sql_mode == "STRICT_TRANS_TABLES") +{ + let $dml_error_code = 0; +} + +--error $dml_error_code +UPDATE t1 SET f2= NULL; +DELETE FROM t2; +SELECT * FROM t1; +UPDATE t1 SET f2 = NULL; +SELECT * FROM t1; +DROP TABLE t2, t1; + +let $error_code= ER_ERROR_ON_RENAME; +if ($algorithm == "INPLACE") +{ + let $error_code= ER_FK_COLUMN_NOT_NULL; +} + +if ($sql_mode == "STRICT_TRANS_TABLES") +{ + let $error_code = ER_FK_COLUMN_NOT_NULL; +} + +# Modifying referenced column from NULL to NOT NULL fails when foreign +# clause is ON UPDATE SET NULL or ON DELETE SET NULL irrespective +# of SQL_MODE variable. This is the behaviour even before MDEV-34392 + +--echo # modify child column NOT NULL ON UPDATE SET NULL +CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT, f2 INT, FOREIGN KEY(f1) REFERENCES t1(f1) ON UPDATE SET NULL)ENGINE=InnoDB; +replace_result ,ALGORITHM=COPY '' ,ALGORITHM=INPLACE ''; +--replace_regex /Error on rename of '.*' to '.*'/Error on rename of 'OLD_FILE_NAME' to 'NEW_FILE_NAME'/ +--error $error_code +eval ALTER TABLE t2 MODIFY COLUMN f1 INT NOT NULL,ALGORITHM=$algorithm; +INSERT INTO t1 VALUES(1, 1); +INSERT INTO t2 VALUES(1, 1); +UPDATE t1 SET f1= 2; +SELECT * FROM t2; +DROP TABLE t2, t1; + +--echo # modify child column NOT NULL ON DELETE SET NULL +CREATE TABLE t1(f1 INT, f2 INT, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +CREATE TABLE t2(f1 INT, f2 INT, FOREIGN KEY (f2) REFERENCES t1(f2) ON DELETE SET NULL)ENGINE=InnoDB; +replace_result ,ALGORITHM=COPY '' ,ALGORITHM=INPLACE ''; +--replace_regex /Error on rename of '.*' to '.*'/Error on rename of 'OLD_FILE_NAME' to 'NEW_FILE_NAME'/ +--error $error_code +eval ALTER TABLE t2 MODIFY COLUMN f2 INT NOT NULL,ALGORITHM=$algorithm; +DROP TABLE t2, t1; + +if ($sql_mode == "STRICT_TRANS_TABLES") +{ + let $dml_error_code = ER_BAD_NULL_ERROR; +} + +let $error_code= 0; +if ($sql_mode == "STRICT_TRANS_TABLES") +{ + let $error_code = ER_FK_COLUMN_CANNOT_CHANGE_CHILD; +} + +--echo # modify parent column NULL ON UPDATE CASCADE child column NOT NULL +CREATE TABLE `t#1`(f1 INT, f2 INT NOT NULL, PRIMARY KEY(f1), KEY(f2))ENGINE=InnoDB; +CREATE TABLE `t#2`(f1 INT NOT NULL, + FOREIGN KEY(f1) REFERENCES `t#1`(f2) + ON UPDATE CASCADE)ENGINE=InnoDB; +replace_result ,ALGORITHM=COPY '' ,ALGORITHM=INPLACE ''; +--error $error_code +eval ALTER TABLE `t#1` MODIFY COLUMN f2 INT,ALGORITHM=$algorithm; +INSERT INTO `t#1` VALUES(1, 1); +INSERT INTO `t#2` VALUES(1); +--error $dml_error_code +UPDATE `t#1` SET f2= NULL; +DELETE FROM `t#2`; +SELECT * FROM `t#1`; +DROP TABLE `t#2`, `t#1`; + +let $error_code= 0; +if ($sql_mode == "STRICT_TRANS_TABLES") +{ + let $error_code = ER_CANT_CREATE_TABLE; +} + +CREATE TABLE t1(f1 INT NOT NULL AUTO_INCREMENT, + f2 INT DEFAULT NULL, + PRIMARY KEY(f1), + FOREIGN KEY(f2) REFERENCES t1(f1))ENGINE=InnoDB; +--error $error_code +CREATE TABLE t2 (f1 INT NOT NULL, + f2 INT NOT NULL, + f3 INT DEFAULT NULL, + PRIMARY KEY(f1, f2), + FOREIGN KEY(f2, f3) REFERENCES t1(f2, f1) + ON UPDATE CASCADE)ENGINE=InnoDB; +--disable_warnings +DROP TABLE IF EXISTS t2; +--enable_warnings +DROP TABLE IF EXISTS t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index aec81d8941e..e906d8a2a62 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9677,6 +9677,7 @@ fk_check_column_changes(THD *thd, const TABLE *table, *bad_column_name= NULL; enum fk_column_change_type result= FK_COLUMN_NO_CHANGE; + bool strict_mode= thd->is_strict_mode(); while ((column= column_it++)) { @@ -9722,7 +9723,7 @@ fk_check_column_changes(THD *thd, const TABLE *table, goto func_exit; } - if (old_field_not_null != new_field_not_null) + if (strict_mode && old_field_not_null != new_field_not_null) { if (referenced && !new_field_not_null) { diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index f0e47938178..45a76243f8a 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -44,6 +44,7 @@ Created 1/8/1996 Heikki Tuuri #include "dict0priv.h" #include "fts0priv.h" #include "srv0start.h" +#include "ha_innodb.h" /*****************************************************************//** Based on a table object, this function builds the entry to be inserted @@ -1890,6 +1891,7 @@ dict_create_add_foreigns_to_dictionary( error = DB_SUCCESS; + bool strict_mode = thd_is_strict_mode(trx->mysql_thd); for (dict_foreign_set::const_iterator it = local_fk_set.begin(); it != local_fk_set.end(); ++it) { @@ -1897,7 +1899,7 @@ dict_create_add_foreigns_to_dictionary( foreign = *it; ut_ad(foreign->id != NULL); - if (!foreign->check_fk_constraint_valid()) { + if (strict_mode && !foreign->check_fk_constraint_valid()) { error = DB_CANNOT_ADD_CONSTRAINT; } else { error = dict_create_add_foreign_to_dictionary( diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index d30c88414cd..e5824dcdb86 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4246,13 +4246,15 @@ declared as NOT NULL @param n_drop_fk number of constraints that are being dropped @param col_name modified column name @param new_field_flags Modified field flags +@param strict_mode Whether the sql_mode is strict @retval true Not allowed (will call my_error()) @retval false Allowed */ static bool check_foreigns_nullability(const dict_table_t *user_table, dict_foreign_t **drop_fk, ulint n_drop_fk, - const char *col_name, uint32_t new_field_flags) + const char *col_name, uint32_t new_field_flags, + bool strict_mode) { ut_ad(mutex_own(&dict_sys.mutex)); @@ -4264,7 +4266,7 @@ bool check_foreigns_nullability(const dict_table_t *user_table, if (innobase_dropping_foreign(foreign, drop_fk, n_drop_fk)) continue; - if (foreign->on_update_cascade_null(col_name)) + if (strict_mode && foreign->on_update_cascade_null(col_name)) goto non_null_error; if (foreign->type & (foreign->DELETE_SET_NULL | @@ -4286,7 +4288,7 @@ non_null_error: { for (dict_foreign_t *foreign : user_table->referenced_set) { - if (foreign->on_update_cascade_not_null(col_name)) + if (strict_mode && foreign->on_update_cascade_not_null(col_name)) { char display_name[FN_REFLEN]; const int dblen= int(table_name_t(const_cast(foreign-> @@ -4388,6 +4390,7 @@ column that is being dropped or modified to NOT NULL. @param user_table InnoDB table as it is before the ALTER operation @param drop_fk constraints being dropped @param n_drop_fk number of constraints that are being dropped +@param strict_mode Whether the strict sql_mode is set @retval true Not allowed (will call my_error()) @retval false Allowed */ @@ -4399,7 +4402,8 @@ innobase_check_foreigns( const TABLE* old_table, const dict_table_t* user_table, dict_foreign_t** drop_fk, - ulint n_drop_fk) + ulint n_drop_fk, + bool strict_mode) { for (Field** fp = old_table->field; *fp; fp++) { ut_ad(!(*fp)->real_maybe_null() @@ -4424,7 +4428,8 @@ innobase_check_foreigns( if (check_foreigns_nullability(user_table, drop_fk, n_drop_fk, (*fp)->field_name.str, - it->flags)) { + it->flags, + strict_mode)) { return true; } } @@ -6462,7 +6467,8 @@ prepare_inplace_alter_table_dict( if (new_clustered) { if (innobase_check_foreigns( ha_alter_info, old_table, - user_table, ctx->drop_fk, ctx->num_to_drop_fk)) { + user_table, ctx->drop_fk, ctx->num_to_drop_fk, + thd_is_strict_mode(ctx->trx->mysql_thd))) { new_clustered_failed: DBUG_ASSERT(ctx->trx != ctx->prebuilt->trx); ctx->trx->rollback(); From fa74c1a40ff75ab8041103b81ec3fc44ef286de1 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 21 Jan 2025 19:19:46 +0200 Subject: [PATCH 055/118] Non partitioned table could be marked as partitioned in ddl.log partion_engine_name was not reset when looping over tables in mysql_rm_table_no_locks. This could cause maria_backup to think that at normal droped table was partitioned. This issue was discovered in 11.8 as part of atomic created and replace and only the fix was backported. --- sql/sql_table.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 59508887e6e..fccdde8a4bc 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1176,7 +1176,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, char path[FN_REFLEN + 1]; LEX_CSTRING alias= null_clex_str; LEX_CUSTRING version; - LEX_CSTRING partition_engine_name= {NULL, 0}; StringBuffer<160> unknown_tables(system_charset_info); DDL_LOG_STATE local_ddl_log_state; const char *comment_start; @@ -1263,6 +1262,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, const LEX_CSTRING db= table->db; const LEX_CSTRING table_name= table->table_name; LEX_CSTRING cpath= {0,0}; + LEX_CSTRING partition_engine_name= {NULL, 0}; handlerton *hton= 0; Table_type table_type; size_t path_length= 0; From 068d061454f1146e39b26a9a8c7058d067b36412 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 3 Jan 2025 17:40:05 +1100 Subject: [PATCH 056/118] MDEV-34813 A simple implementation of ha_partition::compare_key_parts It is not clear that the three Compare_key enums form a hierarchy like alter algorithms do. So on the safe side (in case MDEV-22168 gets implemented without looking at this code) we should return NotEqual if partition engines do not return the same enum value. There's a static merge function that merges these enums, but it is used to merge the Compare_keys of different key parts (horizontally), rather than different partitions (vertically). --- mysql-test/suite/parts/r/alter_table.result | 14 ++++++++++++++ mysql-test/suite/parts/t/alter_table.test | 19 +++++++++++++++++++ sql/ha_partition.cc | 18 ++++++++++++++++++ sql/ha_partition.h | 5 +++++ 4 files changed, 56 insertions(+) diff --git a/mysql-test/suite/parts/r/alter_table.result b/mysql-test/suite/parts/r/alter_table.result index ac8eba12f1b..5f532455219 100644 --- a/mysql-test/suite/parts/r/alter_table.result +++ b/mysql-test/suite/parts/r/alter_table.result @@ -59,4 +59,18 @@ index_name comment PRIMARY i2 disabled drop table t1; +# +# MDEV-34813 ALGORITHM=INSTANT does not work for partitioned tables on indexed column +# +CREATE TABLE `t1` ( +`f1` datetime , +`f2` VARCHAR(2) , +`f3` VARCHAR(200) , +`f4` VARCHAR(100) , +INDEX `i3` (`f4`) ) +PARTITION BY RANGE COLUMNS(`f2`) +(PARTITION `p_01` VALUES LESS THAN ('02') ENGINE = InnoDB, +PARTITION `p_31` VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB); +ALTER online TABLE t1 MODIFY COLUMN `f4` VARCHAR(500) , ALGORITHM=INSTANT, LOCK=NONE; +drop table t1; # End of 10.5 tests diff --git a/mysql-test/suite/parts/t/alter_table.test b/mysql-test/suite/parts/t/alter_table.test index 37adb424d75..00ac3f0265e 100644 --- a/mysql-test/suite/parts/t/alter_table.test +++ b/mysql-test/suite/parts/t/alter_table.test @@ -52,4 +52,23 @@ alter table t1 add partition (partition p4); select index_name, comment from information_schema.statistics where table_schema='test' and table_name='t1'; drop table t1; +--echo # +--echo # MDEV-34813 ALGORITHM=INSTANT does not work for partitioned tables on indexed column +--echo # + +--source include/have_innodb.inc +CREATE TABLE `t1` ( + `f1` datetime , + `f2` VARCHAR(2) , + `f3` VARCHAR(200) , + `f4` VARCHAR(100) , + INDEX `i3` (`f4`) ) + PARTITION BY RANGE COLUMNS(`f2`) + (PARTITION `p_01` VALUES LESS THAN ('02') ENGINE = InnoDB, + PARTITION `p_31` VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB); + +ALTER online TABLE t1 MODIFY COLUMN `f4` VARCHAR(500) , ALGORITHM=INSTANT, LOCK=NONE; + +drop table t1; + --echo # End of 10.5 tests diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 197f4fa51d6..95763eaf477 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3178,6 +3178,24 @@ err1: DBUG_RETURN(true); } +Compare_keys ha_partition::compare_key_parts( + const Field &old_field, + const Column_definition &new_field, + const KEY_PART_INFO &old_part, + const KEY_PART_INFO &new_part) const +{ + Compare_keys res= m_file[0]->compare_key_parts(old_field, new_field, + old_part, new_part); + /* + Partitions have the same storage engine (until MDEV-22168) so the + calls should all return the same value for now. + */ + for (uint i= 1; i < m_tot_parts; i++) + if (res != m_file[i]->compare_key_parts(old_field, new_field, + old_part, new_part)) + return Compare_keys::NotEqual; + return res; +} /** Setup m_engine_array diff --git a/sql/ha_partition.h b/sql/ha_partition.h index b0321578d30..b8524dd15fb 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -481,6 +481,11 @@ public: m_part_info= part_info; m_is_sub_partitioned= part_info->is_sub_partitioned(); } + Compare_keys compare_key_parts( + const Field &old_field, + const Column_definition &new_field, + const KEY_PART_INFO &old_part, + const KEY_PART_INFO &new_part) const override; void return_record_by_parent() override; From 7358cbe6277da9ce749d179b01a2d46a5c699bd9 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Fri, 17 Jan 2025 18:15:04 +1100 Subject: [PATCH 057/118] MDEV-28526 Spider: remove conn_kind member variables The conn_kind, which stands for "connection kind", is no longer useful because the HandlerSocket support is deleted and Spider now has only one connection kind, SPIDER_CONN_KIND_MYSQL. Remove conn_kind and related code. Signed-off-by: Yuchen Pei Reviewed-by: Nayuta Yanagisawa --- storage/spider/ha_spider.cc | 44 +++++++------------------------ storage/spider/ha_spider.h | 8 ++---- storage/spider/spd_conn.cc | 37 ++++++++++---------------- storage/spider/spd_conn.h | 3 --- storage/spider/spd_copy_tables.cc | 9 +++---- storage/spider/spd_db_conn.cc | 14 +++++----- storage/spider/spd_db_conn.h | 3 +-- storage/spider/spd_db_include.h | 2 -- storage/spider/spd_db_mysql.cc | 4 +-- storage/spider/spd_direct_sql.cc | 2 -- storage/spider/spd_include.h | 1 - storage/spider/spd_ping_table.cc | 8 +++--- storage/spider/spd_table.cc | 32 +++++++--------------- storage/spider/spd_trx.cc | 36 +++++++++---------------- storage/spider/spd_trx.h | 6 +---- 15 files changed, 65 insertions(+), 144 deletions(-) diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 8aff2858c3a..54a2fd110f3 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -209,7 +209,6 @@ int ha_spider::open( DBUG_PRINT("info",("spider this=%p", this)); dup_key_idx = (uint) -1; - conn_kinds = SPIDER_CONN_KIND_MYSQL; #ifdef WITH_PARTITION_STORAGE_ENGINE table->file->get_no_parts("", &part_num); if (part_num) @@ -639,22 +638,7 @@ int ha_spider::check_access_kind_for_connection( int error_num, roop_count; DBUG_ENTER("ha_spider::check_access_kind_for_connection"); DBUG_PRINT("info",("spider this=%p", this)); - conn_kinds = 0; - switch (wide_handler->sql_command) - { - case SQLCOM_UPDATE: - case SQLCOM_UPDATE_MULTI: - case SQLCOM_DELETE: - case SQLCOM_DELETE_MULTI: - default: - conn_kinds |= SPIDER_CONN_KIND_MYSQL; - for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) - { - conn_kind[roop_count] = SPIDER_CONN_KIND_MYSQL; - } - break; - } - if ((error_num = spider_check_trx_and_get_conn(thd, this, TRUE))) + if ((error_num= spider_check_trx_and_get_conn(thd, this))) { DBUG_RETURN(error_num); } @@ -980,7 +964,7 @@ int ha_spider::external_lock( } } - if ((error_num= spider_check_trx_and_get_conn(thd, this, FALSE))) + if ((error_num= spider_check_trx_and_get_conn(thd, this))) DBUG_RETURN(error_num); if (!partition_handler || !partition_handler->handlers) { @@ -1113,8 +1097,6 @@ int ha_spider::reset() if (check_error_mode(error_num2)) error_num = error_num2; } - - conn_kind[roop_count] = SPIDER_CONN_KIND_MYSQL; } result_list.bulk_update_mode = 0; result_list.bulk_update_size = 0; @@ -1140,7 +1122,6 @@ int ha_spider::reset() result_list.use_union = FALSE; result_list.use_both_key = FALSE; pt_clone_last_searcher = NULL; - conn_kinds = SPIDER_CONN_KIND_MYSQL; use_index_merge = FALSE; init_rnd_handler = FALSE; #ifdef HA_MRR_USE_DEFAULT_IMPL @@ -5232,7 +5213,7 @@ int ha_spider::rnd_next( DBUG_RETURN(error_num); use_pre_call = FALSE; } - if ((error_num= spider_check_trx_and_get_conn(ha_thd(), this, FALSE))) + if ((error_num= spider_check_trx_and_get_conn(ha_thd(), this))) DBUG_RETURN(error_num); DBUG_RETURN(rnd_next_internal(buf)); } @@ -5797,8 +5778,7 @@ int ha_spider::info( pthread_mutex_lock(&share->sts_mutex); if (difftime(tmp_time, share->sts_get_time) >= sts_interval) { - if ((error_num = spider_check_trx_and_get_conn(ha_thd(), this, - FALSE))) + if ((error_num= spider_check_trx_and_get_conn(ha_thd(), this))) { pthread_mutex_unlock(&share->sts_mutex); if (!share->sts_init) @@ -6361,7 +6341,7 @@ int ha_spider::check_crd() } if (crd_mode == 3) crd_mode = 1; - if ((error_num = spider_check_trx_and_get_conn(ha_thd(), this, FALSE))) + if ((error_num= spider_check_trx_and_get_conn(ha_thd(), this))) { DBUG_RETURN(check_error_mode(error_num)); } @@ -7748,7 +7728,7 @@ int ha_spider::truncate() DBUG_RETURN(ER_SPIDER_READ_ONLY_NUM); } wide_handler->sql_command = SQLCOM_TRUNCATE; - if ((error_num = spider_check_trx_and_get_conn(thd, this, FALSE))) + if ((error_num= spider_check_trx_and_get_conn(thd, this))) { DBUG_RETURN(error_num); } @@ -9334,13 +9314,11 @@ int ha_spider::drop_tmp_tables() } bool ha_spider::handler_opened( - int link_idx, - uint tgt_conn_kind + int link_idx ) { DBUG_ENTER("ha_spider::handler_opened"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider link_idx=%d", link_idx)); - DBUG_PRINT("info",("spider tgt_conn_kind=%u", tgt_conn_kind)); if ( spider_bit_is_set(m_handler_opened, link_idx) ) { @@ -9361,8 +9339,7 @@ void ha_spider::set_handler_opened( } void ha_spider::clear_handler_opened( - int link_idx, - uint tgt_conn_kind + int link_idx ) { DBUG_ENTER("ha_spider::clear_handler_opened"); DBUG_PRINT("info",("spider this=%p", this)); @@ -9381,7 +9358,7 @@ int ha_spider::close_opened_handler( if (spider_bit_is_set(m_handler_opened, link_idx)) { if ((error_num = spider_db_close_handler(this, - conns[link_idx], link_idx, SPIDER_CONN_KIND_MYSQL)) + conns[link_idx], link_idx)) ) { error_num= spider_maybe_ping_1(this, link_idx, error_num); } @@ -11568,8 +11545,7 @@ int ha_spider::append_lock_tables_list() if (!(wide_handler->trx = spider_get_trx(ha_thd(), TRUE, &error_num))) DBUG_RETURN(error_num); - if ((error_num = spider_check_trx_and_get_conn(wide_handler->trx->thd, this, - FALSE))) + if ((error_num = spider_check_trx_and_get_conn(wide_handler->trx->thd, this))) { DBUG_RETURN(error_num); } diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h index 34fad7eee96..d794bfa0cc4 100644 --- a/storage/spider/ha_spider.h +++ b/storage/spider/ha_spider.h @@ -62,8 +62,6 @@ public: uint sql_kinds; uint *sql_kind; ulonglong *connection_ids; - uint conn_kinds; - uint *conn_kind; char *conn_keys_first_ptr; char **conn_keys; SPIDER_CONN **conns; @@ -632,15 +630,13 @@ public: int check_ha_range_eof(); int drop_tmp_tables(); bool handler_opened( - int link_idx, - uint tgt_conn_kind + int link_idx ); void set_handler_opened( int link_idx ); void clear_handler_opened( - int link_idx, - uint tgt_conn_kind + int link_idx ); int close_opened_handler( int link_idx, diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 2faeba56b23..e37df5027bd 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -112,7 +112,6 @@ const uchar *spider_conn_get_key( auto conn= static_cast(conn_); DBUG_ENTER("spider_conn_get_key"); *length = conn->conn_key_length; - DBUG_PRINT("info",("spider conn_kind=%u", conn->conn_kind)); #ifdef DBUG_TRACE spider_print_keys(conn->conn_key, conn->conn_key_length); #endif @@ -402,7 +401,6 @@ SPIDER_CONN *spider_create_conn( ha_spider *spider, int link_idx, int base_link_idx, - uint conn_kind, int *error_num ) { int *need_mon; @@ -556,7 +554,6 @@ SPIDER_CONN *spider_create_conn( conn->semi_trx_isolation_chk = FALSE; conn->semi_trx_chk = FALSE; conn->link_idx = base_link_idx; - conn->conn_kind = conn_kind; conn->conn_need_mon = need_mon; if (spider) conn->need_mon = &spider->need_mons[base_link_idx]; @@ -643,13 +640,11 @@ SPIDER_CONN *spider_get_conn( ha_spider *spider, bool another, bool thd_chg, - uint conn_kind, int *error_num ) { SPIDER_CONN *conn = NULL; int base_link_idx = link_idx; DBUG_ENTER("spider_get_conn"); - DBUG_PRINT("info",("spider conn_kind=%u", conn_kind)); if (spider) link_idx = spider->conn_link_idx[base_link_idx]; @@ -688,7 +683,8 @@ SPIDER_CONN *spider_get_conn( pthread_mutex_unlock(&spider_conn_mutex); if (spider_param_max_connections()) { /* enable connection pool */ - conn = spider_get_conn_from_idle_connection(share, link_idx, conn_key, spider, conn_kind, base_link_idx, error_num); + conn= spider_get_conn_from_idle_connection( + share, link_idx, conn_key, spider, base_link_idx, error_num); /* failed get conn, goto error */ if (!conn) goto error; @@ -697,8 +693,8 @@ SPIDER_CONN *spider_get_conn( else { /* did not enable conncetion pool , create_conn */ DBUG_PRINT("info",("spider create new conn")); - if (!(conn = spider_create_conn(share, spider, link_idx, - base_link_idx, conn_kind, error_num))) + if (!(conn= spider_create_conn(share, spider, link_idx, + base_link_idx, error_num))) goto error; *conn->conn_key = *conn_key; if (spider) @@ -722,8 +718,8 @@ SPIDER_CONN *spider_get_conn( } else { DBUG_PRINT("info",("spider create new conn")); /* conn_recycle_strict = 0 and conn_recycle_mode = 0 or 2 */ - if (!(conn = spider_create_conn(share, spider, link_idx, base_link_idx, - conn_kind, error_num))) + if (!(conn= spider_create_conn(share, spider, link_idx, base_link_idx, + error_num))) goto error; *conn->conn_key = *conn_key; if (spider) @@ -872,8 +868,7 @@ int spider_check_and_get_casual_read_conn( '0' + spider->result_list.casual_read[link_idx]; if (!(spider->conns[link_idx]= spider_get_conn( spider->share, link_idx, spider->conn_keys[link_idx], - spider->wide_handler->trx, spider, FALSE, TRUE, - SPIDER_CONN_KIND_MYSQL, &error_num))) + spider->wide_handler->trx, spider, FALSE, TRUE, &error_num))) { *spider->conn_keys[link_idx] = first_byte_bak; DBUG_RETURN(error_num); @@ -3023,9 +3018,8 @@ void *spider_bg_sts_action( if (!conns[spider.search_link_idx]) { spider_get_conn(share, spider.search_link_idx, - share->conn_keys[spider.search_link_idx], - trx, &spider, FALSE, FALSE, SPIDER_CONN_KIND_MYSQL, - &error_num); + share->conn_keys[spider.search_link_idx], trx, + &spider, FALSE, FALSE, &error_num); conns[spider.search_link_idx]->error_mode = 0; spider.search_link_idx = -1; } @@ -3298,9 +3292,8 @@ void *spider_bg_crd_action( if (!conns[spider.search_link_idx]) { spider_get_conn(share, spider.search_link_idx, - share->conn_keys[spider.search_link_idx], - trx, &spider, FALSE, FALSE, SPIDER_CONN_KIND_MYSQL, - &error_num); + share->conn_keys[spider.search_link_idx], trx, + &spider, FALSE, FALSE, &error_num); conns[spider.search_link_idx]->error_mode = 0; spider.search_link_idx = -1; } @@ -3854,8 +3847,6 @@ bool spider_conn_use_handler( spider->share->use_handlers[link_idx]); DBUG_ENTER("spider_conn_use_handler"); DBUG_PRINT("info",("spider use_handler=%d", use_handler)); - DBUG_PRINT("info",("spider spider->conn_kind[link_idx]=%u", - spider->conn_kind[link_idx])); if (spider->do_direct_update) { spider->sql_kinds |= SPIDER_SQL_KIND_SQL; @@ -3921,7 +3912,7 @@ bool spider_conn_need_open_handler( ) { DBUG_ENTER("spider_conn_need_open_handler"); DBUG_PRINT("info",("spider spider=%p", spider)); - if (spider->handler_opened(link_idx, spider->conn_kind[link_idx])) + if (spider->handler_opened(link_idx)) { DBUG_PRINT("info",("spider HA already opened")); DBUG_RETURN(FALSE); @@ -3934,7 +3925,6 @@ SPIDER_CONN* spider_get_conn_from_idle_connection( int link_idx, char *conn_key, ha_spider *spider, - uint conn_kind, int base_link_idx, int *error_num ) @@ -4022,7 +4012,8 @@ SPIDER_CONN* spider_get_conn_from_idle_connection( if (ip_port_conn) pthread_mutex_unlock(&ip_port_conn->mutex); DBUG_PRINT("info",("spider create new conn")); - if (!(conn = spider_create_conn(share, spider, link_idx, base_link_idx, conn_kind, error_num))) + if (!(conn= spider_create_conn(share, spider, link_idx, base_link_idx, + error_num))) DBUG_RETURN(conn); *conn->conn_key = *conn_key; if (spider) diff --git a/storage/spider/spd_conn.h b/storage/spider/spd_conn.h index ba02178a608..ba3ca0ab62c 100644 --- a/storage/spider/spd_conn.h +++ b/storage/spider/spd_conn.h @@ -124,7 +124,6 @@ SPIDER_CONN *spider_create_conn( ha_spider *spider, int link_id, int base_link_id, - uint conn_kind, int *error_num ); @@ -136,7 +135,6 @@ SPIDER_CONN *spider_get_conn( ha_spider *spider, bool another, bool thd_chg, - uint conn_kind, int *error_num ); @@ -451,7 +449,6 @@ SPIDER_CONN* spider_get_conn_from_idle_connection int link_idx, char *conn_key, ha_spider *spider, - uint conn_kind, int base_link_idx, int *error_num ); diff --git a/storage/spider/spd_copy_tables.cc b/storage/spider/spd_copy_tables.cc index d9cf32b3923..0ea7b0dcf0c 100644 --- a/storage/spider/spd_copy_tables.cc +++ b/storage/spider/spd_copy_tables.cc @@ -501,11 +501,10 @@ int spider_udf_get_copy_tgt_conns( while (table_conn) { share = table_conn->share; - if ( - !(table_conn->conn = spider_get_conn( - share, 0, share->conn_keys[0], trx, NULL, FALSE, FALSE, - SPIDER_CONN_KIND_MYSQL, &error_num)) - ) { + if (!(table_conn->conn= + spider_get_conn(share, 0, share->conn_keys[0], trx, NULL, + FALSE, FALSE, &error_num))) + { my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), share->server_names[0]); DBUG_RETURN(ER_CONNECT_TO_FOREIGN_DATA_SOURCE); } diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 72489a1777e..1c1aa308e82 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -73,7 +73,7 @@ int spider_db_connect( THD* thd = current_thd; longlong connect_retry_interval; DBUG_ENTER("spider_db_connect"); - DBUG_ASSERT(conn->conn_kind != SPIDER_CONN_KIND_MYSQL || conn->need_mon); + DBUG_ASSERT(conn->need_mon); DBUG_PRINT("info",("spider link_idx=%d", link_idx)); DBUG_PRINT("info",("spider conn=%p", conn)); @@ -221,7 +221,6 @@ void spider_db_disconnect( ) { DBUG_ENTER("spider_db_disconnect"); DBUG_PRINT("info",("spider conn=%p", conn)); - DBUG_PRINT("info",("spider conn->conn_kind=%u", conn->conn_kind)); if (conn->db_conn->is_connected()) { conn->db_conn->disconnect(); @@ -10361,9 +10360,9 @@ int spider_db_open_handler( spider_db_handler *dbton_hdl = spider->dbton_handler[conn->dbton_id]; DBUG_ENTER("spider_db_open_handler"); spider_lock_before_query(conn, &spider->need_mons[link_idx]); - if (!spider->handler_opened(link_idx, conn->conn_kind)) + if (!spider->handler_opened(link_idx)) *handler_id_ptr = conn->opened_handlers; - if (!spider->handler_opened(link_idx, conn->conn_kind)) + if (!spider->handler_opened(link_idx)) my_sprintf(spider->m_handler_cid[link_idx], (spider->m_handler_cid[link_idx], SPIDER_SQL_HANDLER_CID_FORMAT, @@ -10388,7 +10387,7 @@ int spider_db_open_handler( goto error; } dbton_hdl->reset_sql(SPIDER_SQL_TYPE_HANDLER); - if (!spider->handler_opened(link_idx, conn->conn_kind)) + if (!spider->handler_opened(link_idx)) { if ((error_num = dbton_hdl->insert_opened_handler(conn, link_idx))) goto error; @@ -10405,15 +10404,14 @@ error: int spider_db_close_handler( ha_spider *spider, SPIDER_CONN *conn, - int link_idx, - uint tgt_conn_kind + int link_idx ) { int error_num= 0; spider_db_handler *dbton_hdl = spider->dbton_handler[conn->dbton_id]; DBUG_ENTER("spider_db_close_handler"); DBUG_PRINT("info",("spider conn=%p", conn)); spider_lock_before_query(conn, &spider->need_mons[link_idx]); - if (spider->handler_opened(link_idx, tgt_conn_kind)) + if (spider->handler_opened(link_idx)) { dbton_hdl->reset_sql(SPIDER_SQL_TYPE_HANDLER); if ((error_num = dbton_hdl->append_close_handler_part( diff --git a/storage/spider/spd_db_conn.h b/storage/spider/spd_db_conn.h index 6e94e2d1517..b9e06e3f219 100644 --- a/storage/spider/spd_db_conn.h +++ b/storage/spider/spd_db_conn.h @@ -1175,8 +1175,7 @@ int spider_db_open_handler( int spider_db_close_handler( ha_spider *spider, SPIDER_CONN *conn, - int link_idx, - uint tgt_conn_kind + int link_idx ); diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 430cd8479be..bcb16ab391b 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -174,8 +174,6 @@ typedef st_spider_result SPIDER_RESULT; #define SPIDER_SQL_LOP_CHK_PRM_PRF_STR "spider_lc_" #define SPIDER_SQL_LOP_CHK_PRM_PRF_LEN (sizeof(SPIDER_SQL_LOP_CHK_PRM_PRF_STR) - 1) -#define SPIDER_CONN_KIND_MYSQL (1 << 0) - #define SPIDER_SQL_KIND_SQL (1 << 0) #define SPIDER_SQL_KIND_HANDLER (1 << 1) diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 5fd215de341..b0c56b0376a 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -3193,7 +3193,7 @@ void spider_db_mbase::reset_opened_handler() { tmp_spider = (*tmp_link_for_hash)->spider; tmp_link_idx = (*tmp_link_for_hash)->link_idx; - tmp_spider->clear_handler_opened(tmp_link_idx, conn->conn_kind); + tmp_spider->clear_handler_opened(tmp_link_idx); } DBUG_VOID_RETURN; } @@ -7377,7 +7377,7 @@ int spider_mbase_share::discover_table_structure( int *need_mon= &need_mon_deref; if (!(conn = spider_get_conn( spider_share, 0, spider_share->conn_keys[roop_count], trx, NULL, FALSE, - FALSE, SPIDER_CONN_KIND_MYSQL, &error_num)) + FALSE, &error_num)) ) { DBUG_RETURN(error_num); } diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index 5aabb5c07fc..f0661bdd4c0 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -416,7 +416,6 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( conn->semi_trx_isolation = -2; conn->semi_trx_isolation_chk = FALSE; conn->semi_trx_chk = FALSE; - conn->conn_kind = SPIDER_CONN_KIND_MYSQL; if (mysql_mutex_init(spd_key_mutex_mta_conn, &conn->mta_conn_mutex, MY_MUTEX_INIT_FAST)) @@ -561,7 +560,6 @@ SPIDER_CONN *spider_udf_direct_sql_get_conn( conn->queued_ping = FALSE; DBUG_PRINT("info",("spider conn=%p", conn)); - DBUG_PRINT("info",("spider conn->conn_kind=%u", conn->conn_kind)); DBUG_RETURN(conn); error: diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index bb3dc92ed3a..17877040358 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -589,7 +589,6 @@ typedef struct st_spider_conn_loop_check SPIDER_CONN_LOOP_CHECK; /* database connection */ typedef struct st_spider_conn { - uint conn_kind; char *conn_key; uint conn_key_length; my_hash_value_type conn_key_hash_value; diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc index 8e4f8a2214b..68254a636e5 100644 --- a/storage/spider/spd_ping_table.cc +++ b/storage/spider/spd_ping_table.cc @@ -648,11 +648,9 @@ SPIDER_CONN *spider_get_ping_table_tgt_conn( ) { SPIDER_CONN *conn; DBUG_ENTER("spider_get_ping_table_tgt_conn"); - if ( - !(conn = spider_get_conn( - share, 0, share->conn_keys[0], trx, NULL, FALSE, FALSE, - SPIDER_CONN_KIND_MYSQL, error_num)) - ) { + if (!(conn= spider_get_conn(share, 0, share->conn_keys[0], trx, NULL, FALSE, + FALSE, error_num))) + { my_error(ER_CONNECT_TO_FOREIGN_DATA_SOURCE, MYF(0), share->server_names[0]); *error_num = ER_CONNECT_TO_FOREIGN_DATA_SOURCE; diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 9a4924c42d1..5aa49cbc327 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -4517,7 +4517,6 @@ SPIDER_SHARE *spider_get_share( &spider->conn_can_fo, sizeof(uchar) * share->link_bitmap_size, &spider->sql_kind, sizeof(uint) * share->link_count, &spider->connection_ids, sizeof(ulonglong) * share->link_count, - &spider->conn_kind, sizeof(uint) * share->link_count, &spider->db_request_id, sizeof(ulonglong) * share->link_count, &spider->db_request_phase, sizeof(uchar) * share->link_bitmap_size, &spider->m_handler_opened, sizeof(uchar) * share->link_bitmap_size, @@ -4558,7 +4557,6 @@ SPIDER_SHARE *spider_get_share( tmp_cid += SPIDER_SQL_HANDLER_CID_LEN + 1; result_list->upd_tmp_tbl_prms[roop_count].init(); result_list->upd_tmp_tbl_prms[roop_count].field_count = 1; - spider->conn_kind[roop_count] = SPIDER_CONN_KIND_MYSQL; } spider_trx_set_link_idx_for_all(spider); @@ -4613,7 +4611,6 @@ SPIDER_SHARE *spider_get_share( !(spider->conns[roop_count] = spider_get_conn(share, roop_count, spider->conn_keys[roop_count], spider->wide_handler->trx, spider, FALSE, TRUE, - SPIDER_CONN_KIND_MYSQL, error_num)) ) { if ( @@ -4993,7 +4990,6 @@ SPIDER_SHARE *spider_get_share( &spider->conn_can_fo, sizeof(uchar) * share->link_bitmap_size, &spider->sql_kind, sizeof(uint) * share->link_count, &spider->connection_ids, sizeof(ulonglong) * share->link_count, - &spider->conn_kind, sizeof(uint) * share->link_count, &spider->db_request_id, sizeof(ulonglong) * share->link_count, &spider->db_request_phase, sizeof(uchar) * share->link_bitmap_size, &spider->m_handler_opened, sizeof(uchar) * share->link_bitmap_size, @@ -5031,7 +5027,6 @@ SPIDER_SHARE *spider_get_share( tmp_cid += SPIDER_SQL_HANDLER_CID_LEN + 1; result_list->upd_tmp_tbl_prms[roop_count].init(); result_list->upd_tmp_tbl_prms[roop_count].field_count = 1; - spider->conn_kind[roop_count] = SPIDER_CONN_KIND_MYSQL; } spider_trx_set_link_idx_for_all(spider); @@ -5083,7 +5078,6 @@ SPIDER_SHARE *spider_get_share( !(spider->conns[roop_count] = spider_get_conn(share, roop_count, spider->conn_keys[roop_count], spider->wide_handler->trx, spider, FALSE, TRUE, - SPIDER_CONN_KIND_MYSQL, error_num)) ) { if ( @@ -5703,11 +5697,9 @@ int spider_open_all_tables( } /* create conn */ - if ( - !(conn = spider_get_conn( - &tmp_share, 0, tmp_share.conn_keys[0], trx, NULL, FALSE, FALSE, - SPIDER_CONN_KIND_MYSQL, &error_num)) - ) { + if (!(conn= spider_get_conn(&tmp_share, 0, tmp_share.conn_keys[0], trx, + NULL, FALSE, FALSE, &error_num))) + { spider_sys_index_end(table_tables); spider_close_sys_table(thd, table_tables, &open_tables_backup, TRUE); @@ -5801,11 +5793,9 @@ int spider_open_all_tables( } /* create another conn */ - if ( - (!(conn = spider_get_conn( - &tmp_share, 0, tmp_share.conn_keys[0], trx, spider, TRUE, FALSE, - SPIDER_CONN_KIND_MYSQL, &error_num))) - ) { + if ((!(conn= spider_get_conn(&tmp_share, 0, tmp_share.conn_keys[0], trx, + spider, TRUE, FALSE, &error_num)))) + { spider_free_tmp_dbton_handler(spider); spider_free(trx, share, MYF(0)); delete spider; @@ -8850,9 +8840,8 @@ void *spider_table_bg_sts_action( if (!conns[spider->search_link_idx]) { spider_get_conn(share, spider->search_link_idx, - share->conn_keys[spider->search_link_idx], - trx, spider, FALSE, FALSE, SPIDER_CONN_KIND_MYSQL, - &error_num); + share->conn_keys[spider->search_link_idx], trx, + spider, FALSE, FALSE, &error_num); if (conns[spider->search_link_idx]) { conns[spider->search_link_idx]->error_mode = 0; @@ -9003,9 +8992,8 @@ void *spider_table_bg_crd_action( if (!conns[spider->search_link_idx]) { spider_get_conn(share, spider->search_link_idx, - share->conn_keys[spider->search_link_idx], - trx, spider, FALSE, FALSE, SPIDER_CONN_KIND_MYSQL, - &error_num); + share->conn_keys[spider->search_link_idx], trx, + spider, FALSE, FALSE, &error_num); if (conns[spider->search_link_idx]) { conns[spider->search_link_idx]->error_mode = 0; diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index 105cf7b744b..af690e7ff5f 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -2673,13 +2673,11 @@ int spider_internal_xa_commit_by_xid( goto error; } - if ( - !(conn = spider_get_conn( - &tmp_share, 0, tmp_share.conn_keys[0], trx, NULL, FALSE, FALSE, - SPIDER_CONN_KIND_MYSQL, &error_num)) && - (force_commit == 0 || - (force_commit == 1 && error_num != ER_XAER_NOTA)) - ) { + if (!(conn= spider_get_conn(&tmp_share, 0, tmp_share.conn_keys[0], trx, + NULL, FALSE, FALSE, &error_num)) && + (force_commit == 0 || + (force_commit == 1 && error_num != ER_XAER_NOTA))) + { spider_sys_index_end(table_xa_member); spider_free_tmp_share_alloc(&tmp_share); free_root(&mem_root, MYF(0)); @@ -2903,13 +2901,11 @@ int spider_internal_xa_rollback_by_xid( goto error; } - if ( - !(conn = spider_get_conn( - &tmp_share, 0, tmp_share.conn_keys[0], trx, NULL, FALSE, FALSE, - SPIDER_CONN_KIND_MYSQL, &error_num)) && - (force_commit == 0 || - (force_commit == 1 && error_num != ER_XAER_NOTA)) - ) { + if (!(conn= spider_get_conn(&tmp_share, 0, tmp_share.conn_keys[0], trx, + NULL, FALSE, FALSE, &error_num)) && + (force_commit == 0 || + (force_commit == 1 && error_num != ER_XAER_NOTA))) + { spider_sys_index_end(table_xa_member); spider_free_tmp_share_alloc(&tmp_share); free_root(&mem_root, MYF(0)); @@ -3409,8 +3405,7 @@ int spider_end_trx( int spider_check_trx_and_get_conn( THD *thd, - ha_spider *spider, - bool use_conn_kind + ha_spider *spider ) { int error_num, roop_count, search_link_idx; SPIDER_TRX *trx; @@ -3500,7 +3495,7 @@ int spider_check_trx_and_get_conn( *spider->conn_keys[0] = first_byte; for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) { - if (!spider->handler_opened(roop_count, SPIDER_CONN_KIND_MYSQL)) + if (!spider->handler_opened(roop_count)) spider->conns[roop_count] = NULL; } bool search_link_idx_is_checked = FALSE; @@ -3513,12 +3508,9 @@ int spider_check_trx_and_get_conn( spider->conn_link_idx, roop_count, share->link_count, SPIDER_LINK_STATUS_RECOVERY) ) { - uint tgt_conn_kind = (use_conn_kind ? spider->conn_kind[roop_count] : - SPIDER_CONN_KIND_MYSQL); if (roop_count == spider->search_link_idx) search_link_idx_is_checked = TRUE; if ( - tgt_conn_kind == SPIDER_CONN_KIND_MYSQL && !spider->conns[roop_count] ) { *spider->conn_keys[roop_count] = first_byte; @@ -3527,8 +3519,6 @@ int spider_check_trx_and_get_conn( spider_get_conn(share, roop_count, spider->conn_keys[roop_count], trx, spider, FALSE, TRUE, - use_conn_kind ? spider->conn_kind[roop_count] : - SPIDER_CONN_KIND_MYSQL, &error_num)) ) { if ( @@ -3607,8 +3597,6 @@ int spider_check_trx_and_get_conn( spider_get_conn(share, roop_count, spider->conn_keys[roop_count], trx, spider, FALSE, TRUE, - use_conn_kind ? spider->conn_kind[roop_count] : - SPIDER_CONN_KIND_MYSQL, &error_num)) ) { if ( diff --git a/storage/spider/spd_trx.h b/storage/spider/spd_trx.h index 2055a49717e..93b03fcec21 100644 --- a/storage/spider/spd_trx.h +++ b/storage/spider/spd_trx.h @@ -227,11 +227,7 @@ int spider_end_trx( SPIDER_CONN *conn ); -int spider_check_trx_and_get_conn( - THD *thd, - ha_spider *spider, - bool use_conn_kind -); +int spider_check_trx_and_get_conn(THD *thd, ha_spider *spider); THD *spider_create_tmp_thd(); From 402b1374a7e0333969564c814679a1e1f8356b21 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Mon, 20 Jan 2025 13:41:53 +1100 Subject: [PATCH 058/118] MDEV-34849 Spider: do not change the first byte of a connection key Each spider connection is identified with a connection key, which is an encoding of the backend parameters. The first byte of the key is by default 0, and in rare circumstances it is changed to a different value: when semi_table_lock is set to 1; and when using casual read. When this happens, often a new connection is created with the new key. Neither case is useful: the description of semi_table_lock has nothing to do with creation of new connections and the parameter itself was deprecated for 10.7+ (MDEV-28829) and marked for deletion (MDEV-28830); while new threads created by non-zero spider_casual_read causes only threads to be idle, thus not achieving any gain, see MDEV-26151, and the param has also been deprecated in 11.5+ (MDEV-31789). The relevant code adds unnecessary complexity to the spider code. This change does not reduce parallelism, because already when bgs mode is on a background thread is created per partition, and there is no evidence spider creates multiple threads for one partition. If the needs of such cases arise it will be a separate issue. --- storage/spider/ha_spider.cc | 3 --- storage/spider/spd_conn.cc | 5 ----- storage/spider/spd_table.cc | 19 ------------------- storage/spider/spd_trx.cc | 22 +--------------------- 4 files changed, 1 insertion(+), 48 deletions(-) diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 54a2fd110f3..0089b1fa0f6 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -1006,9 +1006,6 @@ int ha_spider::reset() THD *thd = ha_thd(); SPIDER_TRX *tmp_trx, *trx_bak; SPIDER_CONDITION *tmp_cond; -/* - char first_byte, first_byte_bak; -*/ backup_error_status(); DBUG_ENTER("ha_spider::reset"); DBUG_PRINT("info",("spider this=%p", this)); diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index e37df5027bd..5019e5ece11 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -863,17 +863,12 @@ int spider_check_and_get_casual_read_conn( if (conn->casual_read_current_id > 63) conn->casual_read_current_id = 2; } - char first_byte_bak = *spider->conn_keys[link_idx]; - *spider->conn_keys[link_idx] = - '0' + spider->result_list.casual_read[link_idx]; if (!(spider->conns[link_idx]= spider_get_conn( spider->share, link_idx, spider->conn_keys[link_idx], spider->wide_handler->trx, spider, FALSE, TRUE, &error_num))) { - *spider->conn_keys[link_idx] = first_byte_bak; DBUG_RETURN(error_num); } - *spider->conn_keys[link_idx] = first_byte_bak; spider->conns[link_idx]->casual_read_base_conn = conn; spider_check_and_set_autocommit(thd, spider->conns[link_idx], NULL); DBUG_RETURN(0); diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 5aa49cbc327..347a3074325 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -4227,8 +4227,6 @@ SPIDER_SHARE *spider_get_share( #ifdef WITH_PARTITION_STORAGE_ENGINE int crd_sync; #endif - char first_byte; - int semi_table_lock_conn; int search_link_idx; uint sql_command = thd_sql_command(thd); SPIDER_Open_tables_backup open_tables_backup; @@ -4425,13 +4423,6 @@ SPIDER_SHARE *spider_get_share( pthread_mutex_unlock(&share->mutex); } - semi_table_lock_conn = spider_param_semi_table_lock_connection(thd, - share->semi_table_lock_conn); - if (semi_table_lock_conn) - first_byte = '0' + - spider_param_semi_table_lock(thd, share->semi_table_lock); - else - first_byte = '0'; if (!(spider->wide_handler->trx = spider_get_trx(thd, TRUE, error_num))) { @@ -4551,7 +4542,6 @@ SPIDER_SHARE *spider_get_share( for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) { spider->conn_keys[roop_count] = tmp_name; - *tmp_name = first_byte; tmp_name += share->conn_keys_lengths[roop_count] + 1; spider->m_handler_cid[roop_count] = tmp_cid; tmp_cid += SPIDER_SQL_HANDLER_CID_LEN + 1; @@ -4909,14 +4899,6 @@ SPIDER_SHARE *spider_get_share( pthread_mutex_unlock(&share->mutex); } - semi_table_lock_conn = spider_param_semi_table_lock_connection(thd, - share->semi_table_lock_conn); - if (semi_table_lock_conn) - first_byte = '0' + - spider_param_semi_table_lock(thd, share->semi_table_lock); - else - first_byte = '0'; - spider->share = share; if (!(spider->wide_handler->trx = spider_get_trx(thd, TRUE, error_num))) { @@ -5021,7 +5003,6 @@ SPIDER_SHARE *spider_get_share( for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) { spider->conn_keys[roop_count] = tmp_name; - *tmp_name = first_byte; tmp_name += share->conn_keys_lengths[roop_count] + 1; spider->m_handler_cid[roop_count] = tmp_cid; tmp_cid += SPIDER_SQL_HANDLER_CID_LEN + 1; diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index af690e7ff5f..e46b8cc289a 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -3411,9 +3411,6 @@ int spider_check_trx_and_get_conn( SPIDER_TRX *trx; SPIDER_SHARE *share = spider->share; SPIDER_CONN *conn; - char first_byte, first_byte_bak; - int semi_table_lock_conn = spider_param_semi_table_lock_connection(thd, - share->semi_table_lock_conn); DBUG_ENTER("spider_check_trx_and_get_conn"); if (!(trx = spider_get_trx(thd, TRUE, &error_num))) { @@ -3428,28 +3425,15 @@ int spider_check_trx_and_get_conn( if (!trx_ha || trx_ha->wait_for_reusing) spider_trx_set_link_idx_for_all(spider); - - if (semi_table_lock_conn) - first_byte = '0' + - spider_param_semi_table_lock(thd, share->semi_table_lock); - else - first_byte = '0'; - DBUG_PRINT("info",("spider semi_table_lock_conn = %d", - semi_table_lock_conn)); - DBUG_PRINT("info",("spider semi_table_lock = %d", - spider_param_semi_table_lock(thd, share->semi_table_lock))); - DBUG_PRINT("info",("spider first_byte = %d", first_byte)); if ( !trx_ha || trx_ha->wait_for_reusing || trx->spider_thread_id != spider->spider_thread_id || trx->trx_conn_adjustment != spider->trx_conn_adjustment || - first_byte != *spider->conn_keys[0] || share->link_statuses[spider->conn_link_idx[spider->search_link_idx]] == SPIDER_LINK_STATUS_NG ) { - DBUG_PRINT("info",(first_byte != *spider->conn_keys[0] ? - "spider change conn type" : trx != spider->wide_handler->trx ? + DBUG_PRINT("info",(trx != spider->wide_handler->trx ? "spider change thd" : "spider next trx")); spider->wide_handler->trx = trx; spider->trx_conn_adjustment = trx->trx_conn_adjustment; @@ -3491,8 +3475,6 @@ int spider_check_trx_and_get_conn( } spider->spider_thread_id = trx->spider_thread_id; - first_byte_bak = *spider->conn_keys[0]; - *spider->conn_keys[0] = first_byte; for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) { if (!spider->handler_opened(roop_count)) @@ -3513,7 +3495,6 @@ int spider_check_trx_and_get_conn( if ( !spider->conns[roop_count] ) { - *spider->conn_keys[roop_count] = first_byte; if ( !(conn = spider_get_conn(share, roop_count, @@ -3543,7 +3524,6 @@ int spider_check_trx_and_get_conn( ); } DBUG_PRINT("info",("spider get conn error")); - *spider->conn_keys[0] = first_byte_bak; spider->spider_thread_id = 0; DBUG_RETURN(error_num); } From e3c768dc8a2de78aa0c096ea1d821c7d801eed44 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 21 Jan 2025 10:41:20 +1100 Subject: [PATCH 059/118] MDEV-34849 Clean up spider_check_trx_and_get_conn() Factoring out parts and documentation. Does not change the logic of the code. --- storage/spider/spd_conn.cc | 6 - storage/spider/spd_include.h | 17 +- storage/spider/spd_trx.cc | 361 ++++++++++++++++------------------- 3 files changed, 176 insertions(+), 208 deletions(-) diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 5019e5ece11..9f2624b4bc7 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -2995,12 +2995,6 @@ void *spider_bg_sts_action( if (spider.search_link_idx < 0) { spider_trx_set_link_idx_for_all(&spider); -/* - spider.search_link_idx = spider_conn_next_link_idx( - thd, share->link_statuses, share->access_balances, - spider.conn_link_idx, spider.search_link_idx, share->link_count, - SPIDER_LINK_STATUS_OK); -*/ spider.search_link_idx = spider_conn_first_link_idx(thd, share->link_statuses, share->access_balances, spider.conn_link_idx, share->link_count, SPIDER_LINK_STATUS_OK); diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 17877040358..47373a7fea5 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -939,6 +939,10 @@ typedef struct st_spider_transaction uint trx_ha_reuse_count; XID_STATE internal_xid_state; SPIDER_CONN *join_trx_top; + /* + Assigned from the global variable `spider_thread_id', which + starts from 1 and increments + */ ulonglong spider_thread_id; ulonglong trx_conn_adjustment; uint locked_connections; @@ -1079,10 +1083,6 @@ typedef struct st_spider_share MEM_ROOT mem_root; -/* - volatile bool auto_increment_init; - volatile ulonglong auto_increment_lclval; -*/ ha_statistics stat; longlong static_records_for_status; @@ -1570,7 +1570,14 @@ typedef struct st_spider_trx_ha */ uint *conn_link_idx; uchar *conn_can_fo; - /* TODO: document */ + /* + TODO: better documentation of this field. + + By assigning true to wait_for_reusing, in + spider_check_trx_and_get_conn the fields of the spider handler + will be updated using the trx, as well as some other small + behavioural differences there. + */ bool wait_for_reusing; } SPIDER_TRX_HA; diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index e46b8cc289a..290b1fb1127 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -48,6 +48,10 @@ extern struct charset_info_st *spd_charset_utf8mb3_bin; extern handlerton *spider_hton_ptr; extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; pthread_mutex_t spider_thread_id_mutex; +/* + Starts from 1 and increment by 1 whenever a new SPIDER_TRX is + created. +*/ ulonglong spider_thread_id; #ifdef HAVE_PSI_INTERFACE @@ -3188,6 +3192,12 @@ int spider_rollback( conn->db_conn->reset_lock_table_hash(); } + /* + We do (almost) nothing if the following two conditions are both met: + + * This is just the end of a statement, not an explicit rollback. + * The autocommit is OFF or we are in an explicit transaction. + */ if (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { if (trx->trx_start) @@ -3403,14 +3413,160 @@ int spider_end_trx( DBUG_RETURN(error_num); } +/* + Report a table error. + + The error_msg requires two format params, db name and table name. +*/ +static int spider_report_table_error(ha_spider *spider, + int error_num, const char *error_msg) +{ + TABLE *table = spider->get_table(); + TABLE_SHARE *table_share = table->s; + char *db = (char *) my_alloca( + table_share->db.length + 1 + table_share->table_name.length + 1); + if (!db) + { + my_error(HA_ERR_OUT_OF_MEM, MYF(0)); + return HA_ERR_OUT_OF_MEM; + } + char *table_name = db + table_share->db.length + 1; + memcpy(db, table_share->db.str, table_share->db.length); + db[table_share->db.length] = '\0'; + memcpy(table_name, table_share->table_name.str, + table_share->table_name.length); + table_name[table_share->table_name.length] = '\0'; + my_printf_error(error_num, error_msg, MYF(0), db, table_name); + my_afree(db); + return error_num; +} + +/* Only called from spider_check_trx_and_get_conn. */ +static int spider_trx_update(THD *thd, ha_spider *spider, SPIDER_TRX *trx) +{ + int search_link_idx, roop_count; + SPIDER_SHARE *share = spider->share; + DBUG_ENTER("spider_trx_update"); + DBUG_PRINT("info", ("spider next trx")); + spider->trx_conn_adjustment = trx->trx_conn_adjustment; + if ( + spider->spider_thread_id != trx->spider_thread_id || + spider->search_link_query_id != thd->query_id + ) { + search_link_idx = spider_conn_first_link_idx(thd, + share->link_statuses, share->access_balances, spider->conn_link_idx, + share->link_count, SPIDER_LINK_STATUS_OK); + if (search_link_idx == -1) + DBUG_RETURN(spider_report_table_error(spider, + ER_SPIDER_ALL_LINKS_FAILED_NUM, + ER_SPIDER_ALL_LINKS_FAILED_STR)); + else if (search_link_idx == -2) + { + my_error(HA_ERR_OUT_OF_MEM, MYF(0)); + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + spider->search_link_idx = search_link_idx; + spider->search_link_query_id = thd->query_id; + } + spider->spider_thread_id = trx->spider_thread_id; + + for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) + { + if (!spider->handler_opened(roop_count)) + spider->conns[roop_count] = NULL; + } + DBUG_RETURN(0); +} + +/* + Only called from spider_check_trx_and_get_conn + + TODO: this function comes from a refactoring, and the from_if param + is true iff the call is from the "if" branch, for lack of a better + name. This needs to be further understood and explained or removed + accordingly. +*/ +static int spider_trx_get_conn(ha_spider *spider, SPIDER_TRX *trx, + bool from_if) +{ + int roop_count, error_num; + bool search_link_idx_is_checked = FALSE; + SPIDER_CONN *conn; + SPIDER_SHARE *share = spider->share; + DBUG_ENTER("spider_trx_get_conn"); + for ( + roop_count = spider_conn_link_idx_next(share->link_statuses, + spider->conn_link_idx, -1, share->link_count, + SPIDER_LINK_STATUS_RECOVERY); + roop_count < (int) share->link_count; + roop_count = spider_conn_link_idx_next(share->link_statuses, + spider->conn_link_idx, roop_count, share->link_count, + SPIDER_LINK_STATUS_RECOVERY) + ) { + if (roop_count == spider->search_link_idx) + search_link_idx_is_checked = TRUE; + if ((conn= spider->conns[roop_count])) + { + /* TODO: do we need the check for !from_if here? */ + if (!from_if) + conn->error_mode&= spider->error_mode; + } + else if (!(conn = + spider_get_conn(share, roop_count, + spider->conn_keys[roop_count], trx, + spider, FALSE, TRUE, + &error_num))) + { + if ( + share->monitoring_kind[roop_count] && + spider->need_mons[roop_count] + ) { + error_num = spider_ping_table_mon_from_table( + trx, + trx->thd, + share, + roop_count, + (uint32) share->monitoring_sid[roop_count], + share->table_name, + share->table_name_length, + spider->conn_link_idx[roop_count], + NULL, + 0, + share->monitoring_kind[roop_count], + share->monitoring_limit[roop_count], + share->monitoring_flag[roop_count], + TRUE + ); + } + DBUG_PRINT("info",("spider get conn error")); + /* + Flag for another update (trx->spider_thread_id is at least + 1, causing the next check spider->spider_thread_id != + trx->spider_thread_id to return true). + + TODO: do we need the check for from_if here? + */ + if (from_if) + spider->spider_thread_id = 0; + DBUG_RETURN(error_num); + } + else + conn->error_mode &= spider->error_mode; + } + if (!search_link_idx_is_checked) + DBUG_RETURN(spider_report_table_error(spider, + ER_SPIDER_LINK_MON_JUST_NG_NUM, + ER_SPIDER_LINK_MON_JUST_NG_STR)); + DBUG_RETURN(0); +} + int spider_check_trx_and_get_conn( THD *thd, ha_spider *spider ) { - int error_num, roop_count, search_link_idx; + int error_num; SPIDER_TRX *trx; SPIDER_SHARE *share = spider->share; - SPIDER_CONN *conn; DBUG_ENTER("spider_check_trx_and_get_conn"); if (!(trx = spider_get_trx(thd, TRUE, &error_num))) { @@ -3433,202 +3589,13 @@ int spider_check_trx_and_get_conn( share->link_statuses[spider->conn_link_idx[spider->search_link_idx]] == SPIDER_LINK_STATUS_NG ) { - DBUG_PRINT("info",(trx != spider->wide_handler->trx ? - "spider change thd" : "spider next trx")); - spider->wide_handler->trx = trx; - spider->trx_conn_adjustment = trx->trx_conn_adjustment; - if ( - spider->spider_thread_id != trx->spider_thread_id || - spider->search_link_query_id != thd->query_id - ) { - search_link_idx = spider_conn_first_link_idx(thd, - share->link_statuses, share->access_balances, spider->conn_link_idx, - share->link_count, SPIDER_LINK_STATUS_OK); - if (search_link_idx == -1) - { - TABLE *table = spider->get_table(); - TABLE_SHARE *table_share = table->s; - char *db = (char *) my_alloca( - table_share->db.length + 1 + table_share->table_name.length + 1); - if (!db) - { - my_error(HA_ERR_OUT_OF_MEM, MYF(0)); - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - char *table_name = db + table_share->db.length + 1; - memcpy(db, table_share->db.str, table_share->db.length); - db[table_share->db.length] = '\0'; - memcpy(table_name, table_share->table_name.str, - table_share->table_name.length); - table_name[table_share->table_name.length] = '\0'; - my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM, - ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name); - my_afree(db); - DBUG_RETURN(ER_SPIDER_ALL_LINKS_FAILED_NUM); - } else if (search_link_idx == -2) - { - my_error(HA_ERR_OUT_OF_MEM, MYF(0)); - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - spider->search_link_idx = search_link_idx; - spider->search_link_query_id = thd->query_id; - } - spider->spider_thread_id = trx->spider_thread_id; - - for (roop_count = 0; roop_count < (int) share->link_count; roop_count++) - { - if (!spider->handler_opened(roop_count)) - spider->conns[roop_count] = NULL; - } - bool search_link_idx_is_checked = FALSE; - for ( - roop_count = spider_conn_link_idx_next(share->link_statuses, - spider->conn_link_idx, -1, share->link_count, - SPIDER_LINK_STATUS_RECOVERY); - roop_count < (int) share->link_count; - roop_count = spider_conn_link_idx_next(share->link_statuses, - spider->conn_link_idx, roop_count, share->link_count, - SPIDER_LINK_STATUS_RECOVERY) - ) { - if (roop_count == spider->search_link_idx) - search_link_idx_is_checked = TRUE; - if ( - !spider->conns[roop_count] - ) { - if ( - !(conn = - spider_get_conn(share, roop_count, - spider->conn_keys[roop_count], trx, - spider, FALSE, TRUE, - &error_num)) - ) { - if ( - share->monitoring_kind[roop_count] && - spider->need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - spider->conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_PRINT("info",("spider get conn error")); - spider->spider_thread_id = 0; - DBUG_RETURN(error_num); - } - conn->error_mode &= spider->error_mode; - } - } - if (!search_link_idx_is_checked) - { - TABLE *table = spider->get_table(); - TABLE_SHARE *table_share = table->s; - char *db = (char *) my_alloca( - table_share->db.length + 1 + table_share->table_name.length + 1); - if (!db) - { - my_error(HA_ERR_OUT_OF_MEM, MYF(0)); - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - char *table_name = db + table_share->db.length + 1; - memcpy(db, table_share->db.str, table_share->db.length); - db[table_share->db.length] = '\0'; - memcpy(table_name, table_share->table_name.str, - table_share->table_name.length); - table_name[table_share->table_name.length] = '\0'; - my_printf_error(ER_SPIDER_LINK_MON_JUST_NG_NUM, - ER_SPIDER_LINK_MON_JUST_NG_STR, MYF(0), db, table_name); - my_afree(db); - DBUG_RETURN(ER_SPIDER_LINK_MON_JUST_NG_NUM); - } - } else { - DBUG_PRINT("info",("spider link_status = %ld", - share->link_statuses[spider->conn_link_idx[spider->search_link_idx]])); - bool search_link_idx_is_checked = FALSE; - for ( - roop_count = spider_conn_link_idx_next(share->link_statuses, - spider->conn_link_idx, -1, share->link_count, - SPIDER_LINK_STATUS_RECOVERY); - roop_count < (int) share->link_count; - roop_count = spider_conn_link_idx_next(share->link_statuses, - spider->conn_link_idx, roop_count, share->link_count, - SPIDER_LINK_STATUS_RECOVERY) - ) { - if (roop_count == spider->search_link_idx) - search_link_idx_is_checked = TRUE; - conn = spider->conns[roop_count]; - - if (!conn) - { - DBUG_PRINT("info",("spider get conn %d", roop_count)); - if ( - !(conn = - spider_get_conn(share, roop_count, - spider->conn_keys[roop_count], trx, - spider, FALSE, TRUE, - &error_num)) - ) { - if ( - share->monitoring_kind[roop_count] && - spider->need_mons[roop_count] - ) { - error_num = spider_ping_table_mon_from_table( - trx, - trx->thd, - share, - roop_count, - (uint32) share->monitoring_sid[roop_count], - share->table_name, - share->table_name_length, - spider->conn_link_idx[roop_count], - NULL, - 0, - share->monitoring_kind[roop_count], - share->monitoring_limit[roop_count], - share->monitoring_flag[roop_count], - TRUE - ); - } - DBUG_PRINT("info",("spider get conn error")); - DBUG_RETURN(error_num); - } - } - conn->error_mode &= spider->error_mode; - } - if (!search_link_idx_is_checked) - { - TABLE *table = spider->get_table(); - TABLE_SHARE *table_share = table->s; - char *db = (char *) my_alloca( - table_share->db.length + 1 + table_share->table_name.length + 1); - if (!db) - { - my_error(HA_ERR_OUT_OF_MEM, MYF(0)); - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - char *table_name = db + table_share->db.length + 1; - memcpy(db, table_share->db.str, table_share->db.length); - db[table_share->db.length] = '\0'; - memcpy(table_name, table_share->table_name.str, - table_share->table_name.length); - table_name[table_share->table_name.length] = '\0'; - my_printf_error(ER_SPIDER_LINK_MON_JUST_NG_NUM, - ER_SPIDER_LINK_MON_JUST_NG_STR, MYF(0), db, table_name); - my_afree(db); - DBUG_RETURN(ER_SPIDER_LINK_MON_JUST_NG_NUM); - } + if ((error_num= spider_trx_update(thd, spider, trx))) + DBUG_RETURN(error_num); + if ((error_num= spider_trx_get_conn(spider, trx, true))) + DBUG_RETURN(error_num); } + else if ((error_num= spider_trx_get_conn(spider, trx, false))) + DBUG_RETURN(error_num); spider->set_first_link_idx(); DBUG_RETURN(spider_create_trx_ha(trx, spider, trx_ha)); } From 1f306d395d00df158702d35b3338ccfe8663744e Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Mon, 20 Jan 2025 17:50:29 +1100 Subject: [PATCH 060/118] MDEV-34849 Spider: update conn->queue_connect_share when needed Update conn->queue_connect_share in spider_check_trx_and_get_conn to avoid use-after-free. There are two branches in spider_check_trx_and_get_conn, often called at the beginning of a spider DML, depending on whether an update of various spider fields is needed. If it is determined to be needed, the updating may NULL the connections associated with the spider handler, which subsequently causes a call to spider_get_conn() which updates conn->queued_connect_share with the SPIDER_SHARE associated with the spider handler. We make it so that conn->queued_connect_share is updated regardless of the branch it enters, so that it will not be a stale and potentially already freed one. --- .../spider/bugfix/r/mdev_34849.result | 24 +++++++++ .../spider/bugfix/t/mdev_34849.test | 52 +++++++++++++++++++ storage/spider/spd_trx.cc | 2 + 3 files changed, 78 insertions(+) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_34849.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_34849.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_34849.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_34849.result new file mode 100644 index 00000000000..9433dd7f679 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_34849.result @@ -0,0 +1,24 @@ +# +# MDEV-34849 SIGSEGV in server_mysql_real_connect, spider_db_connect, __strcmp_evex and __strnlen_evex, ASAN heap-use-after-free in spider_db_connect on INSERT +# +INSTALL SONAME 'ha_spider'; +CREATE TABLE t1 (c INT) ENGINE=Spider; +CREATE TABLE t2 (c INT) ENGINE=Spider; +SELECT * FROM t2; +ERROR HY000: Unable to connect to foreign data source: localhost +set @old_table_open_cache=@@global.table_open_cache; +SET GLOBAL table_open_cache=0; +Warnings: +Warning 1292 Truncated incorrect table_open_cache value: '0' +set autocommit=0; +/* 1 */ INSERT INTO t1 VALUES (0); +ERROR HY000: Unable to connect to foreign data source: localhost +/* 2 */ INSERT INTO t2 VALUES (0); +ERROR HY000: Unable to connect to foreign data source: localhost +set global spider_connect_error_interval=0; +/* 3 */ INSERT INTO t1 VALUES (0); +ERROR HY000: Unable to connect to foreign data source: localhost +drop table t1, t2; +set global table_open_cache=@old_table_open_cache; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_34849.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_34849.test new file mode 100644 index 00000000000..4890abf4c7d --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_34849.test @@ -0,0 +1,52 @@ +--echo # +--echo # MDEV-34849 SIGSEGV in server_mysql_real_connect, spider_db_connect, __strcmp_evex and __strnlen_evex, ASAN heap-use-after-free in spider_db_connect on INSERT +--echo # + +INSTALL SONAME 'ha_spider'; + +CREATE TABLE t1 (c INT) ENGINE=Spider; +CREATE TABLE t2 (c INT) ENGINE=Spider; + +# So that t2 is inserted into spider_init_error_tables and in INSERT +# INTO t2 we go into failure mode in spider_get_share() +--error 1429 +SELECT * FROM t2; + +# Resets the table cache so that the next two queries will call +# ha_spider::open() on t1 and t2 respectively +set @old_table_open_cache=@@global.table_open_cache; +SET GLOBAL table_open_cache=0; + +# This causes trx_ha->wait_for_reusing to remain false during the +# (non-)rollback at the end of the first INSERT INTO t1 statement, so +# that the second INSERT INTO t1 enters the branch in +# spider_check_trx_and_get_conn() that does not update spider fields +# including NULLing its associated connections. +set autocommit=0; + +# Misses the table cache when opening the table. Spider then opens the +# table so that the next INSERT INTO t1 causes a table cache hit and +# skips the call to open table with spider +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +/* 1 */ INSERT INTO t1 VALUES (0); + +# Spider opens the table and creates a t2 share, assigns it to +# conn->queued_connect_share, and frees the t2 share on failure +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +/* 2 */ INSERT INTO t2 VALUES (0); + +# So that the final INSERT INTO t1 will decide not to return the same +# error in spider_db_connect(), and move onto using the freed share +set global spider_connect_error_interval=0; + +# Skips call to ha_spider::open(), so it does not create a t1 share +# nor reassign it to conn->queued_connect_share, causing it to remain +# the freed t2 share, and using the share results in segv +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +/* 3 */ INSERT INTO t1 VALUES (0); + +drop table t1, t2; + +set global table_open_cache=@old_table_open_cache; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index 290b1fb1127..c52c781af8a 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -3510,6 +3510,8 @@ static int spider_trx_get_conn(ha_spider *spider, SPIDER_TRX *trx, /* TODO: do we need the check for !from_if here? */ if (!from_if) conn->error_mode&= spider->error_mode; + if (conn->queued_connect) + conn->queued_connect_share= share; } else if (!(conn = spider_get_conn(share, roop_count, From aef6f35989fb1c7710b93ce1472732cade6fae63 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 22 Jan 2025 10:53:44 +0400 Subject: [PATCH 061/118] MDEV-35549 UBSAN: runtime error: applying zero offset to null pointer on XA RECOVER With UBSAN builds the function my_string_repertoire_8bit() failed on "runtime error: applying zero offset to null pointer" when NULL wad passed as the str parameter. Fix: test str for NULL, and return MY_REPERTOIRE_ASCII if str is NULL. MTR: This problem made MTR tests - main.xa_sync - innodb.xa_debug - main.xa fail with the nullptr-with-offset UNSAN error. After this commit these tests do not fail anymore. This commit does not need any new MTR tests. --- strings/ctype.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/strings/ctype.c b/strings/ctype.c index ccc59a20fe8..eba1827e19a 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -842,6 +842,8 @@ my_string_repertoire_8bit(CHARSET_INFO *cs, const char *str, size_t length) const char *strend; if ((cs->state & MY_CS_NONASCII) && length > 0) return MY_REPERTOIRE_UNICODE30; + if (!str) // Avoid UBSAN nullptr-with-offset + return MY_REPERTOIRE_ASCII; for (strend= str + length; str < strend; str++) { if (((uchar) *str) > 0x7F) From b730abda097c98b5dda982666c8ab6447d80b686 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 8 Nov 2024 18:41:05 +0400 Subject: [PATCH 062/118] MDEV-33285 - Assertion `m_table' failed in ha_perfschema::rnd_end on CHECKSUM TABLE CHECKSUM TABLE causes variety of crashes when killed. This bug it not specific to PERFORMANCE_SCHEMA. Removed duplicate handler::ha_rnd_end() call. --- mysql-test/main/kill_debug.result | 26 ++++++++++++++++++++++ mysql-test/main/kill_debug.test | 36 +++++++++++++++++++++++++++++++ sql/handler.cc | 5 ++++- sql/sql_table.cc | 3 ++- 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/kill_debug.result b/mysql-test/main/kill_debug.result index 061e7602383..40047ef7eb7 100644 --- a/mysql-test/main/kill_debug.result +++ b/mysql-test/main/kill_debug.result @@ -237,3 +237,29 @@ kill $id; set debug_sync='now SIGNAL go3'; drop table t1; set debug_sync='reset'; +# +# MDEV-33285 - Assertion `m_table' failed in ha_perfschema::rnd_end on +# CHECKSUM TABLE +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES(1); +SET debug_sync='mysql_checksum_table_after_calculate_checksum SIGNAL parked WAIT_FOR go'; +CHECKSUM TABLE t1; +connect con1, localhost, root; +connection con1; +SET debug_sync='now WAIT_FOR parked'; +KILL QUERY id; +SET debug_sync='now SIGNAL go'; +connection default; +ERROR 70100: Query execution was interrupted +SET debug_sync='mysql_checksum_table_before_calculate_checksum SIGNAL parked WAIT_FOR go'; +CHECKSUM TABLE t1; +connection con1; +SET debug_sync='now WAIT_FOR parked'; +KILL QUERY id; +SET debug_sync='now SIGNAL go'; +connection default; +ERROR 70100: Query execution was interrupted +DROP TABLE t1; +disconnect con1; +SET debug_sync='RESET'; diff --git a/mysql-test/main/kill_debug.test b/mysql-test/main/kill_debug.test index 32a764004e3..0285fb48bd2 100644 --- a/mysql-test/main/kill_debug.test +++ b/mysql-test/main/kill_debug.test @@ -316,3 +316,39 @@ evalp kill $id; set debug_sync='now SIGNAL go3'; drop table t1; set debug_sync='reset'; + + +--echo # +--echo # MDEV-33285 - Assertion `m_table' failed in ha_perfschema::rnd_end on +--echo # CHECKSUM TABLE +--echo # +let $id= `select connection_id()`; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES(1); +SET debug_sync='mysql_checksum_table_after_calculate_checksum SIGNAL parked WAIT_FOR go'; +send CHECKSUM TABLE t1; + +connect con1, localhost, root; +connection con1; +SET debug_sync='now WAIT_FOR parked'; +replace_result $id id; +eval KILL QUERY $id; +SET debug_sync='now SIGNAL go'; +connection default; +error ER_QUERY_INTERRUPTED; +reap; + +SET debug_sync='mysql_checksum_table_before_calculate_checksum SIGNAL parked WAIT_FOR go'; +send CHECKSUM TABLE t1; +connection con1; +SET debug_sync='now WAIT_FOR parked'; +replace_result $id id; +eval KILL QUERY $id; +SET debug_sync='now SIGNAL go'; + +connection default; +error ER_QUERY_INTERRUPTED; +reap; +DROP TABLE t1; +disconnect con1; +SET debug_sync='RESET'; diff --git a/sql/handler.cc b/sql/handler.cc index 979e9315571..c3aa1c64906 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5584,7 +5584,10 @@ int handler::calculate_checksum() for (;;) { if (thd->killed) - return HA_ERR_ABORTED_BY_USER; + { + error= HA_ERR_ABORTED_BY_USER; + break; + } ha_checksum row_crc= 0; error= ha_rnd_next(table->record[0]); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e906d8a2a62..2162850172b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -12237,14 +12237,15 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, protocol->store_null(); else { + DEBUG_SYNC(thd, "mysql_checksum_table_before_calculate_checksum"); int error= t->file->calculate_checksum(); + DEBUG_SYNC(thd, "mysql_checksum_table_after_calculate_checksum"); if (thd->killed) { /* we've been killed; let handler clean up, and remove the partial current row from the recordset (embedded lib) */ - t->file->ha_rnd_end(); thd->protocol->remove_last_row(); goto err; } From 82310f926b7c6547f25dd80e4edf3f38b22913e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 22 Jan 2025 17:22:07 +0200 Subject: [PATCH 063/118] MDEV-29182 Assertion fld->field_no < table->n_v_def failed on cascade row_ins_cascade_calc_update_vec(): Skip any virtual columns in the update vector of the parent table. Based on mysql/mysql-server@0ac176453bfef7fb1fdfa70af74618c32910181c Reviewed by: Debarun Banerjee --- mysql-test/suite/innodb/r/foreign_key.result | 17 +++++++++++++++++ mysql-test/suite/innodb/t/foreign_key.test | 15 +++++++++++++++ storage/innobase/row/row0ins.cc | 4 +++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 6fbea6883bf..7bb5c4ed5d6 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -1022,4 +1022,21 @@ t2 CREATE TABLE `t2` ( CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop tables t2, t1; +# +# MDEV-29182 Assertion fld->field_no < table->n_v_def failed on cascade +# +CREATE TABLE t1(a INT PRIMARY KEY, b VARCHAR(3), c INT AS (LENGTH(b)) VIRTUAL, +INDEX(c)) ENGINE=InnoDB; +CREATE TABLE t2(a INT REFERENCES t1(a) ON UPDATE CASCADE, +b INT GENERATED ALWAYS AS(a) VIRTUAL, INDEX(b)) ENGINE=InnoDB; +INSERT INTO t1 SET a=1,b='fu'; +INSERT INTO t2 SET a=1; +UPDATE t1 SET a=2,b='bar'; +SELECT * FROM t1; +a b c +2 bar 3 +SELECT * FROM t2; +a b +2 2 +DROP TABLE t2,t1; # End of 10.5 tests diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 5b72dd4096a..3b97fa0e588 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -1063,6 +1063,21 @@ alter table t2 add foreign key(a) references t1; show create table t2; drop tables t2, t1; + +--echo # +--echo # MDEV-29182 Assertion fld->field_no < table->n_v_def failed on cascade +--echo # +CREATE TABLE t1(a INT PRIMARY KEY, b VARCHAR(3), c INT AS (LENGTH(b)) VIRTUAL, + INDEX(c)) ENGINE=InnoDB; +CREATE TABLE t2(a INT REFERENCES t1(a) ON UPDATE CASCADE, + b INT GENERATED ALWAYS AS(a) VIRTUAL, INDEX(b)) ENGINE=InnoDB; +INSERT INTO t1 SET a=1,b='fu'; +INSERT INTO t2 SET a=1; +UPDATE t1 SET a=2,b='bar'; +SELECT * FROM t1; +SELECT * FROM t2; +DROP TABLE t2,t1; + --echo # End of 10.5 tests --source include/wait_until_count_sessions.inc diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index ca43e9045e1..59a2ebd6830 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -479,7 +479,9 @@ row_ins_cascade_calc_update_vec( const upd_field_t* parent_ufield = &parent_update->fields[j]; - if (parent_ufield->field_no == parent_field_no) { + if (parent_ufield->field_no == parent_field_no + && !(parent_ufield->new_val.type.prtype + & DATA_VIRTUAL)) { ulint min_size; const dict_col_t* col; From b214ca72191eb9194a8131e3ff1c92cfb6ece81f Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 23 Jan 2025 11:29:52 +0100 Subject: [PATCH 064/118] MDEV-35090 (Item_func_current_user) Assertion `typeid(*copy) == typeid(*this)' failed in Item_func_or_sum::do_build_clone Added missing do_get_copy of Item_func_current_user. --- mysql-test/main/view.result | 11 +++++++++++ mysql-test/main/view.test | 13 +++++++++++++ sql/item_strfunc.h | 2 ++ 3 files changed, 26 insertions(+) diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result index 3d3efd041c3..1686a6c0026 100644 --- a/mysql-test/main/view.result +++ b/mysql-test/main/view.result @@ -6990,4 +6990,15 @@ View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` from `t1` union (select 1 AS `1` from DUAL where 1 group by 1 having 1 for update) latin1 latin1_swedish_ci DROP VIEW v1; DROP TABLE t1; +# +# MDEV-35090: (Item_func_current_user) Assertion +# `typeid(*copy) == typeid(*this)' failed in +# Item_func_or_sum::do_build_clone +# +CREATE VIEW v AS SELECT 1; +SELECT * FROM v WHERE UpdateXML('N/A','/a',CURRENT_USER()); +1 +Warnings: +Warning 1292 Truncated incorrect INTEGER value: 'N/A' +DROP VIEW v; # End of 10.5 tests diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test index 20aaba8e52a..3c6117c0e36 100644 --- a/mysql-test/main/view.test +++ b/mysql-test/main/view.test @@ -6755,4 +6755,17 @@ SHOW CREATE VIEW v1; DROP VIEW v1; DROP TABLE t1; +--echo # +--echo # MDEV-35090: (Item_func_current_user) Assertion +--echo # `typeid(*copy) == typeid(*this)' failed in +--echo # Item_func_or_sum::do_build_clone +--echo # + +CREATE VIEW v AS SELECT 1; + +SELECT * FROM v WHERE UpdateXML('N/A','/a',CURRENT_USER()); + +# Cleanup +DROP VIEW v; + --echo # End of 10.5 tests diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index e40eed1adf2..24c19b2914a 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1029,6 +1029,8 @@ public: return mark_unsupported_function(fully_qualified_func_name(), arg, VCOL_SESSION_FUNC); } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } }; From 136e866119779668736a4d52ae3301e1f6e3eff2 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 23 Jan 2025 00:03:04 +0100 Subject: [PATCH 065/118] Update WolfSSL to the latest release 5.7.6 Workaround build bugs with preprocessor flags du-jour 1. OPENSSL_ALL does not work anymore (error in ssl.h) nor WOLFSSL_MYSQL_COMPATIBLE, would work, when building library. 2. OPENSSL_EXTRA has to be used instead of OPENSSL_ALL now. WOLFSSL_MYSQL_COMPATIBLE needs to be used to workaround their conflicting definition of protocol_version, which is used in server code. 3. -D_CRT_USE_CONFORMING_ANNEX_K_TIME to force C11-correct definition of gmtime_s on Windows, set some other flags WOLFSSL_MYSQL_COMPATIBLE was previously defining 4. Use HAVE_EMPTY_AGGREGATES=0 to workaround build error on clang (error: struct has size 0 in C, size 1 in C++ [-Werror,-Wextern-c-compat] WOLF_AGG_DUMMY_MEMBER;) --- extra/wolfssl/CMakeLists.txt | 2 ++ extra/wolfssl/user_settings.h.in | 17 ++++++++++++++++- extra/wolfssl/wolfssl | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/extra/wolfssl/CMakeLists.txt b/extra/wolfssl/CMakeLists.txt index e3f8da21f76..85fb06bd128 100644 --- a/extra/wolfssl/CMakeLists.txt +++ b/extra/wolfssl/CMakeLists.txt @@ -130,6 +130,8 @@ if(MSVC) if(CMAKE_C_COMPILER_ID MATCHES Clang) target_compile_options(wolfssl PRIVATE $<$:-Wno-incompatible-function-pointer-types>) endif() + target_compile_definitions(wolfssl PRIVATE + _CRT_USE_CONFORMING_ANNEX_K_TIME HAVE_GMTIME_S WOLFSSL_HAVE_MIN WOLFSSL_HAVE_MAX) endif() CONFIGURE_FILE(user_settings.h.in user_settings.h) diff --git a/extra/wolfssl/user_settings.h.in b/extra/wolfssl/user_settings.h.in index 489118b33b4..92e92d04e4a 100644 --- a/extra/wolfssl/user_settings.h.in +++ b/extra/wolfssl/user_settings.h.in @@ -3,7 +3,21 @@ #define HAVE_CRL #define WOLFSSL_HAVE_ERROR_QUEUE + +/* + Workaround bug in 5.7.6 + WOLFSSL_MYSQL_COMPATIBLE breaks building wolfssl + + But it is needed to avoid redefinition of protocol_version + when its public header ssl.h is included +*/ +#ifndef BUILDING_WOLFSSL #define WOLFSSL_MYSQL_COMPATIBLE +#endif + +#define SP_INT_BITS 8192 +#define HAVE_EMPTY_AGGREGATES 0 + #define HAVE_ECC #define ECC_TIMING_RESISTANT #define HAVE_HASHDRBG @@ -24,7 +38,8 @@ #define HAVE_THREAD_LS #define WOLFSSL_AES_COUNTER #define NO_WOLFSSL_STUB -#define OPENSSL_ALL +// #define OPENSSL_ALL +#define OPENSSL_EXTRA #define WOLFSSL_ALLOW_TLSV10 #define NO_OLD_TIMEVAL_NAME #define HAVE_SECURE_RENEGOTIATION diff --git a/extra/wolfssl/wolfssl b/extra/wolfssl/wolfssl index 00e42151ca0..239b85c8043 160000 --- a/extra/wolfssl/wolfssl +++ b/extra/wolfssl/wolfssl @@ -1 +1 @@ -Subproject commit 00e42151ca061463ba6a95adb2290f678cbca472 +Subproject commit 239b85c80438bf60d9a5b9e0ebe9ff097a760d0d From d4da659b432f47fcbc86ff446f72ce42fc535dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 23 Jan 2025 14:38:08 +0200 Subject: [PATCH 066/118] MDEV-35854: Simplify dict_get_referenced_table() innodb_convert_name(): Convert a schema or table name to my_charset_filename compatible format. dict_table_lookup(): Replaces dict_get_referenced_table(). Make the callers responsible for invoking innodb_convert_name(). innobase_casedn_str(): Remove. Let us invoke my_casedn_str() directly. dict_table_rename_in_cache(): Do not duplicate a call to dict_mem_foreign_table_name_lookup_set(). innobase_convert_to_filename_charset(): Defined static in the only compilation unit that needs it. dict_scan_id(): Remove the constant parameters table_id=FALSE, accept_also_dot=TRUE. Invoke strconvert() directly. innobase_convert_from_id(): Remove; only called from dict_scan_id(). innobase_convert_from_table_id(): Remove (dead code). table_name_t::dblen(), table_name_t::basename(): In non-debug builds, tolerate names that may miss a '/' separator. Reviewed by: Debarun Banerjee --- mysql-test/suite/innodb/r/foreign_key.result | 24 ++ mysql-test/suite/innodb/t/foreign_key.test | 17 ++ storage/innobase/dict/dict0dict.cc | 163 +++---------- storage/innobase/dict/dict0mem.cc | 8 +- storage/innobase/handler/ha_innodb.cc | 243 ++++++++++--------- storage/innobase/handler/handler0alter.cc | 17 +- storage/innobase/include/dict0dict.h | 16 -- storage/innobase/include/dict0mem.h | 2 +- storage/innobase/include/dict0types.h | 14 +- storage/innobase/include/ha_prototypes.h | 63 ++--- storage/innobase/row/row0mysql.cc | 2 +- 11 files changed, 245 insertions(+), 324 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 80a0afb8d06..0404ab81c61 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -1118,5 +1118,29 @@ test.binaries check status OK test.collections check status OK disconnect con1; DROP TABLE binaries, collections; +CREATE SCHEMA `#mysql50##mysql50#d-b`; +CREATE TABLE `#mysql50##mysql50#d-b`.t1 (a INT PRIMARY KEY, b INT UNIQUE) engine=InnoDB; +USE `#mysql50##mysql50#d-b`; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT UNIQUE REFERENCES t1(b)) ENGINE=InnoDB; +SET STATEMENT foreign_key_checks=0 FOR +ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` int(11) NOT NULL, + `b` int(11) DEFAULT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `b` (`b`), + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`b`), + CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`a`) REFERENCES `t1` (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +INSERT INTO t1 SET a=1; +INSERT INTO t2 SET a=1; +DELETE FROM t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`#mysql50#d-b`.`t2`, CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +DELETE FROM t2; +DELETE FROM t1; +DROP DATABASE `#mysql50##mysql50#d-b`; +USE test; # End of 10.6 tests SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 506cca3245c..e31320ee810 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -4,6 +4,7 @@ --disable_query_log call mtr.add_suppression("InnoDB: Transaction was aborted due to "); +call mtr.add_suppression("Invalid \\(old\\?\\) table or database name '#mysql50#d-b'"); --enable_query_log SET GLOBAL innodb_stats_persistent = 0; @@ -1188,6 +1189,22 @@ CHECK TABLE binaries, collections EXTENDED; # Cleanup DROP TABLE binaries, collections; +CREATE SCHEMA `#mysql50##mysql50#d-b`; +CREATE TABLE `#mysql50##mysql50#d-b`.t1 (a INT PRIMARY KEY, b INT UNIQUE) engine=InnoDB; +USE `#mysql50##mysql50#d-b`; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT UNIQUE REFERENCES t1(b)) ENGINE=InnoDB; +SET STATEMENT foreign_key_checks=0 FOR +ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a); +SHOW CREATE TABLE t2; +INSERT INTO t1 SET a=1; +INSERT INTO t2 SET a=1; +--error ER_ROW_IS_REFERENCED_2 +DELETE FROM t1; +DELETE FROM t2; +DELETE FROM t1; +DROP DATABASE `#mysql50##mysql50#d-b`; +USE test; + --echo # End of 10.6 tests SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index d97e26f7fca..dd0b4c714bf 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1467,6 +1467,26 @@ dict_table_t::rename_tablespace(span new_name, bool replace) const return err; } +/********************************************************************** +Converts an identifier from my_charset_filename to UTF-8 charset. +@return result string length, as returned by strconvert() */ +static +uint +innobase_convert_to_filename_charset( +/*=================================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len) /* in: length of 'to', in bytes */ +{ + uint errors; + CHARSET_INFO* cs_to = &my_charset_filename; + CHARSET_INFO* cs_from = system_charset_info; + + return(static_cast(strconvert( + cs_from, from, uint(strlen(from)), + cs_to, to, static_cast(len), &errors))); +} + /**********************************************************************//** Renames a table object. @return TRUE if success */ @@ -1599,19 +1619,20 @@ dict_table_rename_in_cache( foreign->referenced_table->referenced_set.erase(foreign); } - if (strlen(foreign->foreign_table_name) - < strlen(table->name.m_name)) { + const bool do_alloc = strlen(foreign->foreign_table_name) + < strlen(table->name.m_name); + + if (do_alloc) { /* Allocate a longer name buffer; TODO: store buf len to save memory */ foreign->foreign_table_name = mem_heap_strdup( foreign->heap, table->name.m_name); - dict_mem_foreign_table_name_lookup_set(foreign, TRUE); } else { strcpy(foreign->foreign_table_name, table->name.m_name); - dict_mem_foreign_table_name_lookup_set(foreign, FALSE); } + dict_mem_foreign_table_name_lookup_set(foreign, do_alloc); if (strchr(foreign->id, '/')) { /* This is a >= 4.0.18 format id */ @@ -3105,20 +3126,13 @@ dict_scan_id( mem_heap_t* heap, /*!< in: heap where to allocate the id (NULL=id will not be allocated, but it will point to string near ptr) */ - const char** id, /*!< out,own: the id; NULL if no id was + const char** id) /*!< out,own: the id; NULL if no id was scannable */ - ibool table_id,/*!< in: TRUE=convert the allocated id - as a table name; FALSE=convert to UTF-8 */ - ibool accept_also_dot) - /*!< in: TRUE if also a dot can appear in a - non-quoted id; in a quoted id it can appear - always */ { char quote = '\0'; ulint len = 0; const char* s; char* str; - char* dst; *id = NULL; @@ -3154,7 +3168,6 @@ dict_scan_id( } } else { while (!my_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')' - && (accept_also_dot || *ptr != '.') && *ptr != ',' && *ptr != '\0') { ptr++; @@ -3188,125 +3201,15 @@ dict_scan_id( str = mem_heap_strdupl(heap, s, len); } - if (!table_id) { -convert_id: - /* Convert the identifier from connection character set - to UTF-8. */ - len = 3 * len + 1; - *id = dst = static_cast(mem_heap_alloc(heap, len)); - - innobase_convert_from_id(cs, dst, str, len); - } else if (!strncmp(str, srv_mysql50_table_name_prefix, - sizeof(srv_mysql50_table_name_prefix) - 1)) { - /* This is a pre-5.1 table name - containing chars other than [A-Za-z0-9]. - Discard the prefix and use raw UTF-8 encoding. */ - str += sizeof(srv_mysql50_table_name_prefix) - 1; - len -= sizeof(srv_mysql50_table_name_prefix) - 1; - goto convert_id; - } else { - /* Encode using filename-safe characters. */ - len = 5 * len + 1; - *id = dst = static_cast(mem_heap_alloc(heap, len)); - - innobase_convert_from_table_id(cs, dst, str, len); - } - + ulint dstlen = 3 * len + 1; + char *dst = static_cast(mem_heap_alloc(heap, dstlen)); + *id = dst; + uint errors; + strconvert(cs, str, uint(len), system_charset_info, dst, + uint(dstlen), &errors); return(ptr); } -/*********************************************************************//** -Open a table from its database and table name, this is currently used by -foreign constraint parser to get the referenced table. -@return complete table name with database and table name, allocated from -heap memory passed in */ -char* -dict_get_referenced_table( - const char* name, /*!< in: foreign key table name */ - const char* database_name, /*!< in: table db name */ - ulint database_name_len, /*!< in: db name length */ - const char* table_name, /*!< in: table name */ - ulint table_name_len, /*!< in: table name length */ - dict_table_t** table, /*!< out: table object or NULL */ - mem_heap_t* heap, /*!< in/out: heap memory */ - CHARSET_INFO* from_cs) /*!< in: table name charset */ -{ - char* ref; - char db_name[MAX_DATABASE_NAME_LEN]; - char tbl_name[MAX_TABLE_NAME_LEN]; - CHARSET_INFO* to_cs = &my_charset_filename; - uint errors; - ut_ad(database_name || name); - ut_ad(table_name); - - if (!strncmp(table_name, srv_mysql50_table_name_prefix, - sizeof(srv_mysql50_table_name_prefix) - 1)) { - /* This is a pre-5.1 table name - containing chars other than [A-Za-z0-9]. - Discard the prefix and use raw UTF-8 encoding. */ - table_name += sizeof(srv_mysql50_table_name_prefix) - 1; - table_name_len -= sizeof(srv_mysql50_table_name_prefix) - 1; - - to_cs = system_charset_info; - } - - table_name_len = strconvert(from_cs, table_name, table_name_len, to_cs, - tbl_name, MAX_TABLE_NAME_LEN, &errors); - table_name = tbl_name; - - if (database_name) { - to_cs = &my_charset_filename; - if (!strncmp(database_name, srv_mysql50_table_name_prefix, - sizeof(srv_mysql50_table_name_prefix) - 1)) { - database_name - += sizeof(srv_mysql50_table_name_prefix) - 1; - database_name_len - -= sizeof(srv_mysql50_table_name_prefix) - 1; - to_cs = system_charset_info; - } - - database_name_len = strconvert( - from_cs, database_name, database_name_len, to_cs, - db_name, MAX_DATABASE_NAME_LEN, &errors); - database_name = db_name; - } else { - /* Use the database name of the foreign key table */ - - database_name = name; - database_name_len = dict_get_db_name_len(name); - } - - /* Copy database_name, '/', table_name, '\0' */ - const size_t len = database_name_len + table_name_len + 1; - ref = static_cast(mem_heap_alloc(heap, len + 1)); - memcpy(ref, database_name, database_name_len); - ref[database_name_len] = '/'; - memcpy(ref + database_name_len + 1, table_name, table_name_len + 1); - - /* Values; 0 = Store and compare as given; case sensitive - 1 = Store and compare in lower; case insensitive - 2 = Store as given, compare in lower; case semi-sensitive */ - if (lower_case_table_names == 2) { - innobase_casedn_str(ref); - *table = dict_sys.load_table({ref, len}); - memcpy(ref, database_name, database_name_len); - ref[database_name_len] = '/'; - memcpy(ref + database_name_len + 1, table_name, table_name_len + 1); - - } else { -#ifndef _WIN32 - if (lower_case_table_names == 1) { - innobase_casedn_str(ref); - } -#else - innobase_casedn_str(ref); -#endif /* !_WIN32 */ - *table = dict_sys.load_table({ref, len}); - } - - return(ref); -} - /*********************************************************************//** Removes MySQL comments from an SQL string. A comment is either (a) '#' to the end of the line, @@ -3563,7 +3466,7 @@ loop: } } - ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE); + ptr = dict_scan_id(cs, ptr, heap, &id); if (id == NULL) { diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 9de43abbb17..5aeb5d51728 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -816,7 +816,7 @@ void dict_mem_foreign_table_name_lookup_set( /*===================================*/ dict_foreign_t* foreign, /*!< in/out: foreign struct */ - ibool do_alloc) /*!< in: is an alloc needed */ + bool do_alloc) /*!< in: is an alloc needed */ { if (lower_case_table_names == 2) { if (do_alloc) { @@ -830,7 +830,8 @@ dict_mem_foreign_table_name_lookup_set( } strcpy(foreign->foreign_table_name_lookup, foreign->foreign_table_name); - innobase_casedn_str(foreign->foreign_table_name_lookup); + my_casedn_str(system_charset_info, + foreign->foreign_table_name_lookup); } else { foreign->foreign_table_name_lookup = foreign->foreign_table_name; @@ -860,7 +861,8 @@ dict_mem_referenced_table_name_lookup_set( } strcpy(foreign->referenced_table_name_lookup, foreign->referenced_table_name); - innobase_casedn_str(foreign->referenced_table_name_lookup); + my_casedn_str(system_charset_info, + foreign->referenced_table_name_lookup); } else { foreign->referenced_table_name_lookup = foreign->referenced_table_name; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 31c4f525adf..3229cb67241 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1320,9 +1320,7 @@ static void innodb_drop_database(handlerton*, char *path) namebuf[len] = '/'; namebuf[len + 1] = '\0'; -#ifdef _WIN32 - innobase_casedn_str(namebuf); -#endif /* _WIN32 */ + IF_WIN(my_casedn_str(system_charset_info, namebuf),); THD * const thd= current_thd; trx_t *trx= innobase_trx_allocate(thd); @@ -2435,21 +2433,6 @@ dtype_get_mblen( } } -/******************************************************************//** -Converts an identifier to a table name. */ -void -innobase_convert_from_table_id( -/*===========================*/ - CHARSET_INFO* cs, /*!< in: the 'from' character set */ - char* to, /*!< out: converted identifier */ - const char* from, /*!< in: identifier to convert */ - ulint len) /*!< in: length of 'to', in bytes */ -{ - uint errors; - - strconvert(cs, from, FN_REFLEN, &my_charset_filename, to, (uint) len, &errors); -} - /********************************************************************** Check if the length of the identifier exceeds the maximum allowed. return true when length of identifier is too long. */ @@ -2474,21 +2457,6 @@ innobase_check_identifier_length( DBUG_RETURN(false); } -/******************************************************************//** -Converts an identifier to UTF-8. */ -void -innobase_convert_from_id( -/*=====================*/ - CHARSET_INFO* cs, /*!< in: the 'from' character set */ - char* to, /*!< out: converted identifier */ - const char* from, /*!< in: identifier to convert */ - ulint len) /*!< in: length of 'to', in bytes */ -{ - uint errors; - - strconvert(cs, from, FN_REFLEN, system_charset_info, to, (uint) len, &errors); -} - /******************************************************************//** Compares NUL-terminated UTF-8 strings case insensitively. @return 0 if a=b, <0 if a1 if a>b */ @@ -2537,16 +2505,6 @@ innobase_basename( return((name) ? name : "null"); } -/******************************************************************//** -Makes all characters in a NUL-terminated UTF-8 string lower case. */ -void -innobase_casedn_str( -/*================*/ - char* a) /*!< in/out: string to put in lower case */ -{ - my_casedn_str(system_charset_info, a); -} - /** Determines the current SQL statement. Thread unsafe, can only be called from the thread owning the THD. @param[in] thd MySQL thread handle @@ -3683,13 +3641,13 @@ innobase_format_name( ulint buflen, /*!< in: length of buf, in bytes */ const char* name) /*!< in: table name to format */ { - const char* bufend; + char* bufend; bufend = innobase_convert_name(buf, buflen, name, strlen(name), NULL); ut_ad((ulint) (bufend - buf) < buflen); - buf[bufend - buf] = '\0'; + *bufend = '\0'; } /**********************************************************************//** @@ -5386,7 +5344,7 @@ normalize_table_name_c_low( memcpy(norm_name + db_len + 1, name_ptr, name_len + 1); if (set_lower_case) { - innobase_casedn_str(norm_name); + my_casedn_str(system_charset_info, norm_name); } } @@ -6261,7 +6219,7 @@ ha_innobase::open_dict_table( case name, including the partition separator "P" */ strcpy(par_case_name, norm_name); - innobase_casedn_str(par_case_name); + my_casedn_str(system_charset_info, par_case_name); #else /* On Windows platfrom, check whether there exists table name in @@ -12389,6 +12347,73 @@ public: const char* str() { return buf; } }; +/** Construct an InnoDB table name from a schema and table name. +@param table_name buffer InnoDB table name being constructed +@param db schema name +@param name table name +@return table_name filled in */ +static char *copy_name(char *table_name, LEX_CSTRING db, LEX_CSTRING name) + noexcept +{ + memcpy(table_name, db.str, db.length); + table_name[db.length] = '/'; + memcpy(table_name + db.length + 1, name.str, name.length + 1); + return table_name; +} + +char *dict_table_lookup(LEX_CSTRING db, LEX_CSTRING name, + dict_table_t **table, mem_heap_t *heap) noexcept +{ + const size_t len= db.length + name.length + 1; + char *ref= static_cast(mem_heap_alloc(heap, len + 1)); + copy_name(ref, db, name); + + switch (lower_case_table_names) { + case 2: /* store as given, compare in lower case */ + my_casedn_str(system_charset_info, ref); + *table= dict_sys.load_table({ref, len}); + return copy_name(ref, db, name); + case 0: /* store and compare as given; case sensitive */ +#ifndef _WIN32 /* On Windows, InnoDB treats 0 as lower_case_table_names=1 */ + break; +#endif + case 1: /* store and compare in lower case */ + my_casedn_str(system_charset_info, ref); + } + + *table = dict_sys.load_table({ref, len}); + return ref; +} + +/** Convert a schema or table name to InnoDB (and file system) format. +@param cs source character set +@param name name encoded in cs +@param buf output buffer (MAX_TABLE_NAME_LEN + 1 bytes) +@return the converted string (within buf) */ +LEX_CSTRING innodb_convert_name(CHARSET_INFO *cs, LEX_CSTRING name, char *buf) + noexcept +{ + CHARSET_INFO *to_cs= &my_charset_filename; + if (!strncmp(name.str, srv_mysql50_table_name_prefix, + sizeof srv_mysql50_table_name_prefix - 1)) + { + /* Before MySQL 5.1 introduced my_charset_filename, schema and + table names were stored in the file system as specified by the + user, hopefully in ASCII encoding, but it could also be in ISO + 8859-1 or UTF-8. Such schema or table names are distinguished by + the #mysql50# prefix. + + Let us discard that prefix and convert the name to UTF-8 + (system_charset_info). */ + name.str+= sizeof srv_mysql50_table_name_prefix - 1; + name.length-= sizeof srv_mysql50_table_name_prefix - 1; + to_cs= system_charset_info; + } + uint errors; + return LEX_CSTRING{buf, strconvert(cs, name.str, name.length, to_cs, + buf, MAX_TABLE_NAME_LEN, &errors)}; +} + /** Create InnoDB foreign keys from MySQL alter_info. Collect all dict_foreign_t items into local_fk_set and then add into system table. @return DB_SUCCESS or specific error code */ @@ -12404,6 +12429,9 @@ create_table_info_t::create_foreign_keys() const char* ref_column_names[MAX_COLS_PER_FK]; char create_name[MAX_DATABASE_NAME_LEN + 1 + MAX_TABLE_NAME_LEN + 1]; + char db_name[MAX_DATABASE_NAME_LEN + 1]; + char t_name[MAX_TABLE_NAME_LEN + 1]; + static_assert(MAX_TABLE_NAME_LEN == MAX_DATABASE_NAME_LEN, ""); dict_index_t* index = NULL; fkerr_t index_error = FK_SUCCESS; dict_index_t* err_index = NULL; @@ -12411,59 +12439,57 @@ create_table_info_t::create_foreign_keys() const bool tmp_table = m_flags2 & DICT_TF2_TEMPORARY; const CHARSET_INFO* cs = thd_charset(m_thd); const char* operation = "Create "; - const char* name = m_table_name; enum_sql_command sqlcom = enum_sql_command(thd_sql_command(m_thd)); + LEX_CSTRING name= {m_table_name, strlen(m_table_name)}; if (sqlcom == SQLCOM_ALTER_TABLE) { - dict_table_t* table_to_alter; mem_heap_t* heap = mem_heap_create(10000); - ulint highest_id_so_far; - char* n = dict_get_referenced_table( - name, LEX_STRING_WITH_LEN(m_form->s->db), - LEX_STRING_WITH_LEN(m_form->s->table_name), - &table_to_alter, heap, cs); + LEX_CSTRING t{innodb_convert_name(cs, m_form->s->table_name, + t_name)}; + LEX_CSTRING d{innodb_convert_name(cs, m_form->s->db, db_name)}; + dict_table_t* alter_table; + char* n = dict_table_lookup(d, t, &alter_table, heap); /* Starting from 4.0.18 and 4.1.2, we generate foreign key id's in the format databasename/tablename_ibfk_[number], where [number] is local to the table; look for the highest [number] - for table_to_alter, so that we can assign to new constraints + for alter_table, so that we can assign to new constraints higher numbers. */ /* If we are altering a temporary table, the table name after ALTER TABLE does not correspond to the internal table name, and - table_to_alter is NULL. TODO: should we fix this somehow? */ + alter_table=nullptr. But, we do not support FOREIGN KEY + constraints for temporary tables. */ - if (table_to_alter) { - n = table_to_alter->name.m_name; - highest_id_so_far = dict_table_get_highest_foreign_id( - table_to_alter); - } else { - highest_id_so_far = 0; + if (alter_table) { + n = alter_table->name.m_name; + number = 1 + dict_table_get_highest_foreign_id( + alter_table); } char* bufend = innobase_convert_name( create_name, sizeof create_name, n, strlen(n), m_thd); - create_name[bufend - create_name] = '\0'; - number = highest_id_so_far + 1; + *bufend = '\0'; mem_heap_free(heap); operation = "Alter "; - } else if (strstr(name, "#P#") || strstr(name, "#p#")) { + } else if (strstr(m_table_name, "#P#") + || strstr(m_table_name, "#p#")) { /* Partitioned table */ create_name[0] = '\0'; } else { char* bufend = innobase_convert_name(create_name, sizeof create_name, - name, - strlen(name), m_thd); - create_name[bufend - create_name] = '\0'; + LEX_STRING_WITH_LEN(name), + m_thd); + *bufend = '\0'; } Alter_info* alter_info = m_create_info->alter_info; ut_ad(alter_info); List_iterator_fast key_it(alter_info->key_list); - dict_table_t* table = dict_sys.find_table({name,strlen(name)}); + dict_table_t* table = dict_sys.find_table({name.str, name.length}); if (!table) { ib_foreign_warn(m_trx, DB_CANNOT_ADD_CONSTRAINT, create_name, "%s table %s foreign key constraint" @@ -12510,27 +12536,27 @@ create_table_info_t::create_foreign_keys() col->field_name.length); success = find_col(table, column_names + i); if (!success) { - key_text k(fk); ib_foreign_warn( m_trx, DB_CANNOT_ADD_CONSTRAINT, create_name, "%s table %s foreign key %s constraint" " failed. Column %s was not found.", - operation, create_name, k.str(), + operation, create_name, + key_text(fk).str(), column_names[i]); dict_foreign_free(foreign); return (DB_CANNOT_ADD_CONSTRAINT); } ++i; if (i >= MAX_COLS_PER_FK) { - key_text k(fk); ib_foreign_warn( m_trx, DB_CANNOT_ADD_CONSTRAINT, create_name, "%s table %s foreign key %s constraint" " failed. Too many columns: %u (%u " "allowed).", - operation, create_name, k.str(), i, + operation, create_name, + key_text(fk).str(), i, MAX_COLS_PER_FK); dict_foreign_free(foreign); return (DB_CANNOT_ADD_CONSTRAINT); @@ -12542,9 +12568,9 @@ create_table_info_t::create_foreign_keys() &index_error, &err_col, &err_index); if (!index) { - key_text k(fk); foreign_push_index_error(m_trx, operation, create_name, - k.str(), column_names, + key_text(fk).str(), + column_names, index_error, err_col, err_index, table); dict_foreign_free(foreign); @@ -12610,14 +12636,12 @@ create_table_info_t::create_foreign_keys() memcpy(foreign->foreign_col_names, column_names, i * sizeof(void*)); - foreign->referenced_table_name = dict_get_referenced_table( - name, LEX_STRING_WITH_LEN(fk->ref_db), - LEX_STRING_WITH_LEN(fk->ref_table), - &foreign->referenced_table, foreign->heap, cs); - - if (!foreign->referenced_table_name) { - return (DB_OUT_OF_MEMORY); - } + LEX_CSTRING t{innodb_convert_name(cs, fk->ref_table, t_name)}; + LEX_CSTRING d = fk->ref_db.str + ? innodb_convert_name(cs, fk->ref_db, db_name) + : LEX_CSTRING{table->name.m_name, table->name.dblen()}; + foreign->referenced_table_name = dict_table_lookup( + d, t, &foreign->referenced_table, foreign->heap); if (!foreign->referenced_table && m_trx->check_foreigns) { char buf[MAX_TABLE_NAME_LEN + 1] = ""; @@ -12627,15 +12651,15 @@ create_table_info_t::create_foreign_keys() buf, MAX_TABLE_NAME_LEN, foreign->referenced_table_name, strlen(foreign->referenced_table_name), m_thd); - buf[bufend - buf] = '\0'; - key_text k(fk); + *bufend = '\0'; ib_foreign_warn(m_trx, DB_CANNOT_ADD_CONSTRAINT, create_name, "%s table %s with foreign key %s " "constraint failed. Referenced table " "%s not found in the data dictionary.", - operation, create_name, k.str(), buf); - return (DB_CANNOT_ADD_CONSTRAINT); + operation, create_name, + key_text(fk).str(), buf); + return DB_CANNOT_ADD_CONSTRAINT; } /* Don't allow foreign keys on partitioned tables yet. */ @@ -12658,7 +12682,6 @@ create_table_info_t::create_foreign_keys() success = find_col(foreign->referenced_table, ref_column_names + j); if (!success) { - key_text k(fk); ib_foreign_warn( m_trx, DB_CANNOT_ADD_CONSTRAINT, @@ -12667,9 +12690,9 @@ create_table_info_t::create_foreign_keys() "constraint failed. " "Column %s was not found.", operation, create_name, - k.str(), ref_column_names[j]); - - return (DB_CANNOT_ADD_CONSTRAINT); + key_text(fk).str(), + ref_column_names[j]); + return DB_CANNOT_ADD_CONSTRAINT; } } ++j; @@ -12689,16 +12712,15 @@ create_table_info_t::create_foreign_keys() &err_index); if (!index) { - key_text k(fk); foreign_push_index_error( - m_trx, operation, create_name, k.str(), + m_trx, operation, create_name, + key_text(fk).str(), column_names, index_error, err_col, err_index, foreign->referenced_table); - - return (DB_CANNOT_ADD_CONSTRAINT); + return DB_CANNOT_ADD_CONSTRAINT; } } else { - ut_a(m_trx->check_foreigns == FALSE); + ut_a(!m_trx->check_foreigns); index = NULL; } @@ -12735,7 +12757,6 @@ create_table_info_t::create_foreign_keys() NULL if the column is not allowed to be NULL! */ - key_text k(fk); ib_foreign_warn( m_trx, DB_CANNOT_ADD_CONSTRAINT, @@ -12746,9 +12767,9 @@ create_table_info_t::create_foreign_keys() "but column '%s' is defined as " "NOT NULL.", operation, create_name, - k.str(), col_name); + key_text(fk).str(), col_name); - return (DB_CANNOT_ADD_CONSTRAINT); + return DB_CANNOT_ADD_CONSTRAINT; } } } @@ -13596,7 +13617,7 @@ int ha_innobase::delete_table(const char *name) if (!table && lower_case_table_names == 1 && is_partition(norm_name)) { IF_WIN(normalize_table_name_c_low(norm_name, name, false), - innobase_casedn_str(norm_name)); + my_casedn_str(system_charset_info, norm_name)); table= dict_sys.load_table(n, DICT_ERR_IGNORE_DROP); } #endif @@ -13903,7 +13924,8 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from, case name, including the partition separator "P" */ strcpy(par_case_name, norm_from); - innobase_casedn_str(par_case_name); + my_casedn_str(system_charset_info, + par_case_name); #else /* On Windows platfrom, check whether there exists table name in @@ -20924,25 +20946,6 @@ const char* SET_TRANSACTION_MSG = const char* INNODB_PARAMETERS_MSG = "Please refer to https://mariadb.com/kb/en/library/innodb-system-variables/"; -/********************************************************************** -Converts an identifier from my_charset_filename to UTF-8 charset. -@return result string length, as returned by strconvert() */ -uint -innobase_convert_to_filename_charset( -/*=================================*/ - char* to, /* out: converted identifier */ - const char* from, /* in: identifier to convert */ - ulint len) /* in: length of 'to', in bytes */ -{ - uint errors; - CHARSET_INFO* cs_to = &my_charset_filename; - CHARSET_INFO* cs_from = system_charset_info; - - return(static_cast(strconvert( - cs_from, from, uint(strlen(from)), - cs_to, to, static_cast(len), &errors))); -} - /********************************************************************** Converts an identifier from my_charset_filename to UTF-8 charset. @return result string length, as returned by strconvert() */ diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index ff427297375..afcff2f3ea1 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -30,6 +30,7 @@ Smart ALTER TABLE #include #include #include +#include /* Include necessary InnoDB headers */ #include "btr0sea.h" @@ -3231,6 +3232,9 @@ innobase_get_foreign_key_info( ulint num_fk = 0; Alter_info* alter_info = ha_alter_info->alter_info; const CHARSET_INFO* cs = thd_charset(trx->mysql_thd); + char db_name[MAX_DATABASE_NAME_LEN + 1]; + char t_name[MAX_TABLE_NAME_LEN + 1]; + static_assert(MAX_TABLE_NAME_LEN == MAX_DATABASE_NAME_LEN, ""); DBUG_ENTER("innobase_get_foreign_key_info"); @@ -3295,14 +3299,15 @@ innobase_get_foreign_key_info( add_fk[num_fk] = dict_mem_foreign_create(); + LEX_CSTRING t = innodb_convert_name(cs, fk_key->ref_table, + t_name); + LEX_CSTRING d = fk_key->ref_db.str + ? innodb_convert_name(cs, fk_key->ref_db, db_name) + : LEX_CSTRING{table->name.m_name, table->name.dblen()}; dict_sys.lock(SRW_LOCK_CALL); - referenced_table_name = dict_get_referenced_table( - table->name.m_name, - LEX_STRING_WITH_LEN(fk_key->ref_db), - LEX_STRING_WITH_LEN(fk_key->ref_table), - &referenced_table, - add_fk[num_fk]->heap, cs); + referenced_table_name = dict_table_lookup( + d, t, &referenced_table, add_fk[num_fk]->heap); /* Test the case when referenced_table failed to open, if trx->check_foreigns is not set, we should diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 0197a790faa..519e1c5bd10 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -55,22 +55,6 @@ inline size_t dict_get_db_name_len(const char *name) } -/*********************************************************************//** -Open a table from its database and table name, this is currently used by -foreign constraint parser to get the referenced table. -@return complete table name with database and table name, allocated from -heap memory passed in */ -char* -dict_get_referenced_table( -/*======================*/ - const char* name, /*!< in: foreign key table name */ - const char* database_name, /*!< in: table db name */ - ulint database_name_len,/*!< in: db name length */ - const char* table_name, /*!< in: table name */ - ulint table_name_len, /*!< in: table name length */ - dict_table_t** table, /*!< out: table object or NULL */ - mem_heap_t* heap, /*!< in: heap memory */ - CHARSET_INFO* from_cs); /*!< in: table name charset */ /*********************************************************************//** Frees a foreign key struct. */ void diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 609aaf951ca..3b1ae66d861 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -431,7 +431,7 @@ void dict_mem_foreign_table_name_lookup_set( /*===================================*/ dict_foreign_t* foreign, /*!< in/out: foreign struct */ - ibool do_alloc); /*!< in: is an alloc needed */ + bool do_alloc); /*!< in: is an alloc needed */ /**********************************************************************//** Sets the referenced_table_name_lookup pointer based on the value of diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index ec50e8cd951..85eed8d416c 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -110,7 +110,7 @@ struct table_name_t table_name_t(char* name) : m_name(name) {} /** @return the end of the schema name */ - const char* dbend() const + const char* dbend() const noexcept { const char* sep = strchr(m_name, '/'); ut_ad(sep); @@ -118,11 +118,19 @@ struct table_name_t } /** @return the length of the schema name, in bytes */ - size_t dblen() const { return size_t(dbend() - m_name); } + size_t dblen() const noexcept + { + const char *end= dbend(); + return UNIV_LIKELY(end != nullptr) ? size_t(end - m_name) : 0; + } /** Determine the filename-safe encoded table name. @return the filename-safe encoded table name */ - const char* basename() const { return dbend() + 1; } + const char* basename() const noexcept + { + const char *end= dbend(); + return UNIV_LIKELY(end != nullptr) ? end + 1 : nullptr; + } /** The start of the table basename suffix for partitioned tables */ static const char part_suffix[4]; diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 96ce0cfe783..098986febdf 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -40,6 +40,8 @@ class Field; struct dict_table_t; struct dict_foreign_t; struct table_name_t; +struct mem_block_info_t; +typedef struct mem_block_info_t mem_heap_t; // JAN: TODO missing features: #undef MYSQL_FT_INIT_EXT @@ -156,33 +158,6 @@ const char* innobase_basename( const char* path_name); -/******************************************************************//** -Converts an identifier to a table name. */ -void -innobase_convert_from_table_id( -/*===========================*/ - CHARSET_INFO* cs, /*!< in: the 'from' character set */ - char* to, /*!< out: converted identifier */ - const char* from, /*!< in: identifier to convert */ - ulint len); /*!< in: length of 'to', in bytes; should - be at least 5 * strlen(to) + 1 */ -/******************************************************************//** -Converts an identifier to UTF-8. */ -void -innobase_convert_from_id( -/*=====================*/ - CHARSET_INFO* cs, /*!< in: the 'from' character set */ - char* to, /*!< out: converted identifier */ - const char* from, /*!< in: identifier to convert */ - ulint len); /*!< in: length of 'to', in bytes; - should be at least 3 * strlen(to) + 1 */ -/******************************************************************//** -Makes all characters in a NUL-terminated UTF-8 string lower case. */ -void -innobase_casedn_str( -/*================*/ - char* a); /*!< in/out: string to put in lower case */ - #ifdef WITH_WSREP ulint wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, ulint str_length, @@ -370,15 +345,6 @@ innobase_next_autoinc( MY_ATTRIBUTE((pure, warn_unused_result)); /********************************************************************** -Converts an identifier from my_charset_filename to UTF-8 charset. */ -uint -innobase_convert_to_system_charset( -/*===============================*/ - char* to, /* out: converted identifier */ - const char* from, /* in: identifier to convert */ - ulint len, /* in: length of 'to', in bytes */ - uint* errors); /* out: error return */ -/********************************************************************** Check if the length of the identifier exceeds the maximum allowed. The input to this function is an identifier in charset my_charset_filename. return true when length of identifier is too long. */ @@ -398,14 +364,13 @@ innobase_convert_to_system_charset( ulint len, /* in: length of 'to', in bytes */ uint* errors); /* out: error return */ -/********************************************************************** -Converts an identifier from my_charset_filename to UTF-8 charset. */ -uint -innobase_convert_to_filename_charset( -/*=================================*/ - char* to, /* out: converted identifier */ - const char* from, /* in: identifier to convert */ - ulint len); /* in: length of 'to', in bytes */ +/** Convert a schema or table name to InnoDB (and file system) format. +@param cs source character set +@param name name encoded in cs +@param buf output buffer (MAX_TABLE_NAME_LEN + 1 bytes) +@return the converted string (within buf) */ +LEX_CSTRING innodb_convert_name(CHARSET_INFO *cs, LEX_CSTRING name, char *buf) + noexcept; /** Report that a table cannot be decrypted. @param thd connection context @@ -460,6 +425,16 @@ void destroy_background_thd(MYSQL_THD thd); void innobase_reset_background_thd(MYSQL_THD); +/** Open a table based on a database and table name. +@param db schema name +@param name table name within the schema +@param table table +@param heap memory heap for allocating a converted name +@return InnoDB format table name with database and table name, +allocated from heap */ +char *dict_table_lookup(LEX_CSTRING db, LEX_CSTRING name, + dict_table_t **table, mem_heap_t *heap) noexcept; + #ifdef WITH_WSREP /** Append table-level exclusive key. @param thd MySQL thread handle diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index ac5e08d4498..ac11ea56ad0 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2608,7 +2608,7 @@ row_rename_table_for_mysql( memcpy(par_case_name, old_name, strlen(old_name)); par_case_name[strlen(old_name)] = 0; - innobase_casedn_str(par_case_name); + my_casedn_str(system_charset_info, par_case_name); #else /* On Windows platfrom, check whether there exists table name in From 2543be69423b8a6582a4d2fa688d969359f8de3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 23 Jan 2025 14:38:35 +0200 Subject: [PATCH 067/118] MDEV-35854: Clarify row_rename_table_for_mysql() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit enum rename_fk: Replaces the "bool use_fk" parameter of row_rename_table_for_mysql() and innobase_rename_table(): RENAME_IGNORE_FK: Replaces use_fk=false when the operation cannot involve any FOREIGN KEY constraints, that is, it is a partitioned table or an internal table for FULLTEXT INDEX. RENAME_REBUILD: Replaces use_fk=false when the table may contain FOREIGN KEY constraints, which must not be modified in the data dictionary tables SYS_FOREIGN and SYS_FOREIGN_COLS. RENAME_ALTER_COPY: Replaces use_fk=true. This is only specified in ha_innobase::rename_table(), which may be invoked as part of ALTER TABLEโ€ฆALGORITHM=COPY, but also during RENAME TABLE. An alternative value RENAME_FK could be useful to specify in ha_innobase::rename_table() when it is executed as part of CREATE OR REPLACE TABLE, which currently is not an atomic operation. Reviewed by: Debarun Banerjee --- storage/innobase/fts/fts0fts.cc | 4 ++-- storage/innobase/handler/ha_innodb.cc | 15 +++++++++------ storage/innobase/handler/handler0alter.cc | 6 ++++-- storage/innobase/include/row0mysql.h | 11 ++++++++++- storage/innobase/row/row0mysql.cc | 15 ++++++++------- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index df2cb568d4d..83ae2827230 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1392,7 +1392,7 @@ static dberr_t fts_drop_table(trx_t *trx, const char *table_name, bool rename) char *tmp= dict_mem_create_temporary_tablename(heap, table->name.m_name, table->id); dberr_t err= row_rename_table_for_mysql(table->name.m_name, tmp, trx, - false); + RENAME_IGNORE_FK); mem_heap_free(heap); if (err != DB_SUCCESS) { @@ -1450,7 +1450,7 @@ fts_rename_one_aux_table( fts_table_new_name[table_new_name_len] = 0; return row_rename_table_for_mysql( - fts_table_old_name, fts_table_new_name, trx, false); + fts_table_old_name, fts_table_new_name, trx, RENAME_IGNORE_FK); } /****************************************************************//** diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3229cb67241..4dd7a9405dd 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13889,10 +13889,10 @@ err_exit: @param[in,out] trx InnoDB data dictionary transaction @param[in] from old table name @param[in] to new table name -@param[in] use_fk whether to enforce FOREIGN KEY +@param[in] fk how to handle FOREIGN KEY @return DB_SUCCESS or error code */ static dberr_t innobase_rename_table(trx_t *trx, const char *from, - const char *to, bool use_fk) + const char *to, rename_fk fk) { dberr_t error; char norm_to[FN_REFLEN]; @@ -13910,7 +13910,7 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from, ut_ad(trx->will_lock); - error = row_rename_table_for_mysql(norm_from, norm_to, trx, use_fk); + error = row_rename_table_for_mysql(norm_from, norm_to, trx, fk); if (error != DB_SUCCESS) { if (error == DB_TABLE_NOT_FOUND @@ -13936,7 +13936,8 @@ static dberr_t innobase_rename_table(trx_t *trx, const char *from, #endif /* _WIN32 */ trx_start_if_not_started(trx, true); error = row_rename_table_for_mysql( - par_case_name, norm_to, trx, false); + par_case_name, norm_to, trx, + RENAME_IGNORE_FK); } } @@ -14132,7 +14133,8 @@ int ha_innobase::truncate() if (error == DB_SUCCESS) { - error= innobase_rename_table(trx, ib_table->name.m_name, temp_name, false); + error= innobase_rename_table(trx, ib_table->name.m_name, temp_name, + RENAME_REBUILD); if (error == DB_SUCCESS) error= trx->drop_table(*ib_table); } @@ -14330,7 +14332,8 @@ ha_innobase::rename_table( row_mysql_lock_data_dictionary(trx); if (error == DB_SUCCESS) { - error = innobase_rename_table(trx, from, to, true); + error = innobase_rename_table(trx, from, to, + RENAME_ALTER_COPY); } DEBUG_SYNC(thd, "after_innobase_rename_table"); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index afcff2f3ea1..a967259a2ab 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -10414,10 +10414,12 @@ commit_try_rebuild( char* old_name= mem_heap_strdup(ctx->heap, user_table->name.m_name); dberr_t error = row_rename_table_for_mysql(user_table->name.m_name, - ctx->tmp_name, trx, false); + ctx->tmp_name, trx, + RENAME_REBUILD); if (error == DB_SUCCESS) { error = row_rename_table_for_mysql( - rebuilt_table->name.m_name, old_name, trx, false); + rebuilt_table->name.m_name, old_name, trx, + RENAME_REBUILD); if (error == DB_SUCCESS) { /* The statistics for the surviving indexes will be re-inserted in alter_stats_rebuild(). */ diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 8cbeed7d297..63858f25f02 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -370,6 +370,15 @@ row_import_tablespace_for_mysql( row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL */ MY_ATTRIBUTE((nonnull, warn_unused_result)); +enum rename_fk { + /** ignore FOREIGN KEY constraints */ + RENAME_IGNORE_FK= 0, + /** Rename a table as part of a native table-rebuilding DDL operation */ + RENAME_REBUILD, + /** Rename as part of ALTER TABLE...ALGORITHM=COPY */ + RENAME_ALTER_COPY +}; + /*********************************************************************//** Renames a table for MySQL. @return error code or DB_SUCCESS */ @@ -379,7 +388,7 @@ row_rename_table_for_mysql( const char* old_name, /*!< in: old table name */ const char* new_name, /*!< in: new table name */ trx_t* trx, /*!< in/out: transaction */ - bool use_fk) /*!< in: whether to parse and enforce + rename_fk fk) /*!< in: how to handle FOREIGN KEY constraints */ MY_ATTRIBUTE((nonnull, warn_unused_result)); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index ac11ea56ad0..c72e71bf047 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2554,7 +2554,7 @@ row_rename_table_for_mysql( const char* old_name, /*!< in: old table name */ const char* new_name, /*!< in: new table name */ trx_t* trx, /*!< in/out: transaction */ - bool use_fk) /*!< in: whether to parse and enforce + rename_fk fk) /*!< in: how to handle FOREIGN KEY constraints */ { dict_table_t* table = NULL; @@ -2579,6 +2579,8 @@ row_rename_table_for_mysql( old_is_tmp = dict_table_t::is_temporary_name(old_name); new_is_tmp = dict_table_t::is_temporary_name(new_name); + ut_ad(fk != RENAME_IGNORE_FK || !new_is_tmp); + table = dict_table_open_on_name(old_name, true, DICT_ERR_IGNORE_FK_NOKEY); @@ -2638,10 +2640,9 @@ row_rename_table_for_mysql( << TROUBLESHOOTING_MSG; goto funct_exit; - - } else if (use_fk && !old_is_tmp && new_is_tmp) { - /* MySQL is doing an ALTER TABLE command and it renames the - original table to a temporary table name. We want to preserve + } else if (fk == RENAME_ALTER_COPY && !old_is_tmp && new_is_tmp) { + /* Non-native ALTER TABLE is renaming the + original table to a temporary name. We want to preserve the original foreign key constraint definitions despite the name change. An exception is those constraints for which the ALTER TABLE contained DROP FOREIGN KEY .*/ @@ -2685,7 +2686,7 @@ row_rename_table_for_mysql( goto rollback_and_exit; } - if (!new_is_tmp) { + if (/* fk == RENAME_IGNORE_FK || */ !new_is_tmp) { /* Rename all constraints. */ char new_table_name[MAX_TABLE_NAME_LEN + 1]; char old_table_utf8[MAX_TABLE_NAME_LEN + 1]; @@ -2859,7 +2860,7 @@ row_rename_table_for_mysql( err = dict_load_foreigns( new_name, nullptr, trx->id, !old_is_tmp || trx->check_foreigns, - use_fk + fk == RENAME_ALTER_COPY ? DICT_ERR_IGNORE_NONE : DICT_ERR_IGNORE_FK_NOKEY, fk_tables); From 77ea99a4b5f0b275e1531419ef134da6237cb95a Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 23 Jan 2025 13:48:00 -0800 Subject: [PATCH 068/118] MDEV-35869 Wrong result using degenerated subquery with window function This bug affected queries containing degenerated single-value subqueries with window functions. The bug led mostly to wrong results for such queries. A subquery is called degenerated if it is of the form (SELECT ...). For degenerated subqueries of the form (SELECT ) the transformation (SELECT ) => usually is applied. However if contains set functions or window functions such rewriting is not valid for an obvious reason. The code before this patch erroneously applied the transformation when contained window functions and did not contain set functions. Approved by Rex Johnston --- mysql-test/main/win.result | 23 +++++++++++++++++++ mysql-test/main/win.test | 12 ++++++++++ .../encryption/r/tempfiles_encrypted.result | 23 +++++++++++++++++++ sql/item_subselect.cc | 1 + 4 files changed, 59 insertions(+) diff --git a/mysql-test/main/win.result b/mysql-test/main/win.result index f3b719d0a18..76d89340679 100644 --- a/mysql-test/main/win.result +++ b/mysql-test/main/win.result @@ -4601,4 +4601,27 @@ w2_total w1_total u 200 200 2 DROP VIEW v1; DROP TABLE t1; +# +# MDEV-35869: degenerated subquery with window function +# +CREATE TABLE t1 (a int DEFAULT 10); +INSERT INTO t1 VALUES (7), (2), (3); +SELECT * FROM t1 WHERE (SELECT AVG(3)) > 2; +a +7 +2 +3 +SELECT * FROM t1 WHERE (SELECT AVG(3) OVER ()) > 2; +a +7 +2 +3 +INSERT INTO t1 VALUES((SELECT avg(4) OVER ())); +SELECT * FROM t1; +a +7 +2 +3 +4 +DROP TABLE t1; # End of 10.5 tests diff --git a/mysql-test/main/win.test b/mysql-test/main/win.test index 5722cedab81..e80b55da089 100644 --- a/mysql-test/main/win.test +++ b/mysql-test/main/win.test @@ -3001,4 +3001,16 @@ eval $q3; DROP VIEW v1; DROP TABLE t1; +--echo # +--echo # MDEV-35869: degenerated subquery with window function +--echo # + +CREATE TABLE t1 (a int DEFAULT 10); +INSERT INTO t1 VALUES (7), (2), (3); +SELECT * FROM t1 WHERE (SELECT AVG(3)) > 2; +SELECT * FROM t1 WHERE (SELECT AVG(3) OVER ()) > 2; +INSERT INTO t1 VALUES((SELECT avg(4) OVER ())); +SELECT * FROM t1; +DROP TABLE t1; + --echo # End of 10.5 tests diff --git a/mysql-test/suite/encryption/r/tempfiles_encrypted.result b/mysql-test/suite/encryption/r/tempfiles_encrypted.result index e233c8fa3ef..aa66f01bc1e 100644 --- a/mysql-test/suite/encryption/r/tempfiles_encrypted.result +++ b/mysql-test/suite/encryption/r/tempfiles_encrypted.result @@ -4607,6 +4607,29 @@ w2_total w1_total u 200 200 2 DROP VIEW v1; DROP TABLE t1; +# +# MDEV-35869: degenerated subquery with window function +# +CREATE TABLE t1 (a int DEFAULT 10); +INSERT INTO t1 VALUES (7), (2), (3); +SELECT * FROM t1 WHERE (SELECT AVG(3)) > 2; +a +7 +2 +3 +SELECT * FROM t1 WHERE (SELECT AVG(3) OVER ()) > 2; +a +7 +2 +3 +INSERT INTO t1 VALUES((SELECT avg(4) OVER ())); +SELECT * FROM t1; +a +7 +2 +3 +4 +DROP TABLE t1; # End of 10.5 tests # # MDEV-23867: select crash in compute_window_func diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8da808ca3a0..05e98071947 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1215,6 +1215,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) !select_lex->table_list.elements && select_lex->item_list.elements == 1 && !select_lex->item_list.head()->with_sum_func() && + !select_lex->item_list.head()->with_window_func && /* We can't change name of Item_field or Item_ref, because it will prevent its correct resolving, but we should save name of From d261fa5c70372bcee79bbb57cfeab0de13265e44 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 8 Nov 2024 13:51:34 +0400 Subject: [PATCH 069/118] MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify Also fixes: MDEV-32190 Index corruption with unique key and nopad collation (without DESC or HASH keys) MDEV-28328 Assertion failures in btr0cur.cc upon INSERT or in row0sel.cc afterwards The code in strings/strcoll.inl when comparing an empty string to a string like 0x0001050001 did not take into account that the leftmost weight in the latter can be zero, while there are some more weights can follow the zero weight. Rewriting the code to treat the shorter string as smaller than a longer string. --- mysql-test/main/ctype_big5.result | 9 +++ mysql-test/main/ctype_big5.test | 7 +++ mysql-test/main/ctype_cp932.result | 9 +++ mysql-test/main/ctype_cp932.test | 7 +++ mysql-test/main/ctype_eucjpms.result | 9 +++ mysql-test/main/ctype_eucjpms.test | 7 +++ mysql-test/main/ctype_euckr.result | 9 +++ mysql-test/main/ctype_euckr.test | 7 +++ mysql-test/main/ctype_gb2312.result | 9 +++ mysql-test/main/ctype_gb2312.test | 7 +++ mysql-test/main/ctype_gbk.result | 9 +++ mysql-test/main/ctype_gbk.test | 7 +++ mysql-test/main/ctype_sjis.result | 9 +++ mysql-test/main/ctype_sjis.test | 7 +++ mysql-test/main/ctype_sjis_innodb.result | 23 ++++++++ mysql-test/main/ctype_sjis_innodb.test | 62 +++++++++++++++++++++ mysql-test/main/ctype_ucs.result | 9 +++ mysql-test/main/ctype_ucs.test | 7 +++ mysql-test/main/ctype_ujis.result | 15 +++++ mysql-test/main/ctype_ujis.test | 15 +++++ mysql-test/main/ctype_utf8.result | 9 +++ mysql-test/main/ctype_utf8.test | 6 ++ mysql-test/main/ctype_utf8mb3_innodb.result | 39 +++++++++++++ mysql-test/main/ctype_utf8mb3_innodb.test | 39 +++++++++++++ strings/strcoll.inl | 6 +- 25 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 mysql-test/main/ctype_sjis_innodb.result create mode 100644 mysql-test/main/ctype_sjis_innodb.test create mode 100644 mysql-test/main/ctype_utf8mb3_innodb.result create mode 100644 mysql-test/main/ctype_utf8mb3_innodb.test diff --git a/mysql-test/main/ctype_big5.result b/mysql-test/main/ctype_big5.result index a89f8a75dc0..c26758e2063 100644 --- a/mysql-test/main/ctype_big5.result +++ b/mysql-test/main/ctype_big5.result @@ -5445,5 +5445,14 @@ EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); ERROR HY000: Invalid big5 character string: '\xA3\xC0' SET sql_mode=DEFAULT; # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_big5'' collate big5_chinese_nopad_ci, _big5 0x0001050001) as c1; +c1 +-1 +select strcmp(_big5'' collate big5_nopad_bin, _big5 0x0001050001) as c1; +c1 +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_big5.test b/mysql-test/main/ctype_big5.test index 4b6203a2577..917a3c02a1a 100644 --- a/mysql-test/main/ctype_big5.test +++ b/mysql-test/main/ctype_big5.test @@ -290,6 +290,13 @@ SET NAMES big5; SET @seq=_big5 0xA3C0; --source include/ctype_ident_sys.inc +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_big5'' collate big5_chinese_nopad_ci, _big5 0x0001050001) as c1; +select strcmp(_big5'' collate big5_nopad_bin, _big5 0x0001050001) as c1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_cp932.result b/mysql-test/main/ctype_cp932.result index ed222c997da..4b6eda1bc86 100644 --- a/mysql-test/main/ctype_cp932.result +++ b/mysql-test/main/ctype_cp932.result @@ -653,5 +653,14 @@ EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); ERROR HY000: Invalid cp932 character string: '\x81' SET sql_mode=DEFAULT; # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_cp932'' collate cp932_japanese_nopad_ci, _cp932 0x0001050001) as c1; +c1 +-1 +select strcmp(_cp932'' collate cp932_nopad_bin, _cp932 0x0001050001) as c1; +c1 +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_cp932.test b/mysql-test/main/ctype_cp932.test index 0f5ff437d33..b4e33f517ca 100644 --- a/mysql-test/main/ctype_cp932.test +++ b/mysql-test/main/ctype_cp932.test @@ -61,6 +61,13 @@ SET NAMES cp932; SET @seq=_cp932 0x81AD; --source include/ctype_ident_sys.inc +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_cp932'' collate cp932_japanese_nopad_ci, _cp932 0x0001050001) as c1; +select strcmp(_cp932'' collate cp932_nopad_bin, _cp932 0x0001050001) as c1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_eucjpms.result b/mysql-test/main/ctype_eucjpms.result index b886e340671..5f81ec1a76b 100644 --- a/mysql-test/main/ctype_eucjpms.result +++ b/mysql-test/main/ctype_eucjpms.result @@ -34547,5 +34547,14 @@ EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); ERROR HY000: Invalid eucjpms character string: '\x8F\xA1\xA1' SET sql_mode=DEFAULT; # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_eucjpms'' collate eucjpms_japanese_nopad_ci, _eucjpms 0x0001050001) as c1; +c1 +-1 +select strcmp(_eucjpms'' collate eucjpms_nopad_bin, _eucjpms 0x0001050001) as c1; +c1 +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_eucjpms.test b/mysql-test/main/ctype_eucjpms.test index 0d002f769a8..aebb9e10930 100644 --- a/mysql-test/main/ctype_eucjpms.test +++ b/mysql-test/main/ctype_eucjpms.test @@ -612,6 +612,13 @@ SET NAMES eucjpms; SET @seq=_eucjpms 0x8FA1A1; --source include/ctype_ident_sys.inc +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_eucjpms'' collate eucjpms_japanese_nopad_ci, _eucjpms 0x0001050001) as c1; +select strcmp(_eucjpms'' collate eucjpms_nopad_bin, _eucjpms 0x0001050001) as c1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_euckr.result b/mysql-test/main/ctype_euckr.result index e7f02603786..cd72ffbab7c 100644 --- a/mysql-test/main/ctype_euckr.result +++ b/mysql-test/main/ctype_euckr.result @@ -26065,5 +26065,14 @@ EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); ERROR HY000: Invalid euckr character string: '\xA2\xE8' SET sql_mode=DEFAULT; # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_euckr'' collate euckr_korean_nopad_ci, _euckr 0x0001050001) as c1; +c1 +-1 +select strcmp(_euckr'' collate euckr_nopad_bin, _euckr 0x0001050001) as c1; +c1 +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_euckr.test b/mysql-test/main/ctype_euckr.test index 1154047fdb0..2196c5d3717 100644 --- a/mysql-test/main/ctype_euckr.test +++ b/mysql-test/main/ctype_euckr.test @@ -241,6 +241,13 @@ SET NAMES euckr; SET @seq=_euckr 0xA2E8; --source include/ctype_ident_sys.inc +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_euckr'' collate euckr_korean_nopad_ci, _euckr 0x0001050001) as c1; +select strcmp(_euckr'' collate euckr_nopad_bin, _euckr 0x0001050001) as c1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_gb2312.result b/mysql-test/main/ctype_gb2312.result index f0bbb48621d..136471d4f25 100644 --- a/mysql-test/main/ctype_gb2312.result +++ b/mysql-test/main/ctype_gb2312.result @@ -5135,5 +5135,14 @@ EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); ERROR HY000: Invalid gb2312 character string: '\xA2\xA1' SET sql_mode=DEFAULT; # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_gb2312'' collate gb2312_chinese_nopad_ci, _gb2312 0x0001050001) as c1; +c1 +-1 +select strcmp(_gb2312'' collate gb2312_nopad_bin, _gb2312 0x0001050001) as c1; +c1 +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_gb2312.test b/mysql-test/main/ctype_gb2312.test index b9147fdc420..15b69e00ea2 100644 --- a/mysql-test/main/ctype_gb2312.test +++ b/mysql-test/main/ctype_gb2312.test @@ -199,6 +199,13 @@ SET NAMES gb2312; SET @seq=_gb2312 0xA2A1; --source include/ctype_ident_sys.inc +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_gb2312'' collate gb2312_chinese_nopad_ci, _gb2312 0x0001050001) as c1; +select strcmp(_gb2312'' collate gb2312_nopad_bin, _gb2312 0x0001050001) as c1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_gbk.result b/mysql-test/main/ctype_gbk.result index cbf396e69ba..a1610969d73 100644 --- a/mysql-test/main/ctype_gbk.result +++ b/mysql-test/main/ctype_gbk.result @@ -6603,5 +6603,14 @@ EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); ERROR HY000: Invalid gbk character string: '\xAA\xA1' SET sql_mode=DEFAULT; # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_gbk'' collate gbk_chinese_nopad_ci, _gbk 0x0001050001); +strcmp(_gbk'' collate gbk_chinese_nopad_ci, _gbk 0x0001050001) +-1 +select strcmp(_gbk'' collate gbk_nopad_bin, _gbk 0x0001050001); +strcmp(_gbk'' collate gbk_nopad_bin, _gbk 0x0001050001) +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_gbk.test b/mysql-test/main/ctype_gbk.test index 9f6f6672952..8043e233e07 100644 --- a/mysql-test/main/ctype_gbk.test +++ b/mysql-test/main/ctype_gbk.test @@ -500,6 +500,13 @@ SET NAMES gbk; SET @seq=_gbk 0xAAA1; --source include/ctype_ident_sys.inc +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_gbk'' collate gbk_chinese_nopad_ci, _gbk 0x0001050001); +select strcmp(_gbk'' collate gbk_nopad_bin, _gbk 0x0001050001); + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_sjis.result b/mysql-test/main/ctype_sjis.result index f93a0b8be60..e6797950403 100644 --- a/mysql-test/main/ctype_sjis.result +++ b/mysql-test/main/ctype_sjis.result @@ -19389,5 +19389,14 @@ EXECUTE IMMEDIATE CONCAT('a.', @seq, ':=1'); ERROR HY000: Invalid sjis character string: '_x81' SET sql_mode=DEFAULT; # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_sjis'' collate sjis_japanese_nopad_ci, _sjis 0x0001050001) as c1; +c1 +-1 +select strcmp(_sjis'' collate sjis_nopad_bin, _sjis 0x0001050001) as c1; +c1 +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_sjis.test b/mysql-test/main/ctype_sjis.test index 951571ef523..83e12c85bda 100644 --- a/mysql-test/main/ctype_sjis.test +++ b/mysql-test/main/ctype_sjis.test @@ -328,6 +328,13 @@ SET NAMES sjis; SET @seq=_sjis 0x81AD; --source include/ctype_ident_sys.inc +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_sjis'' collate sjis_japanese_nopad_ci, _sjis 0x0001050001) as c1; +select strcmp(_sjis'' collate sjis_nopad_bin, _sjis 0x0001050001) as c1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_sjis_innodb.result b/mysql-test/main/ctype_sjis_innodb.result new file mode 100644 index 00000000000..6252848c8bb --- /dev/null +++ b/mysql-test/main/ctype_sjis_innodb.result @@ -0,0 +1,23 @@ +# Start of 10.5 tests +# +# MDEV-28328 Assertion failures in btr0cur.cc upon INSERT or in row0sel.cc afterwards +# +SET NAMES utf8mb3; +CREATE TABLE t ( +a year(4) DEFAULT NULL, +b varbinary(2545) DEFAULT '', +c mediumtext COLLATE sjis_japanese_nopad_ci NOT NULL, +d decimal(7,7) DEFAULT NULL, +e char(219) COLLATE sjis_japanese_nopad_ci DEFAULT '', +f bigint(25) DEFAULT 0, +g bigint(20) DEFAULT NULL, +h datetime(1) DEFAULT '1900-01-01 00:00:00.0', +PRIMARY KEY (c(25),e) +) ENGINE=InnoDB DEFAULT CHARSET=sjis COLLATE=sjis_japanese_nopad_ci; +INSERT IGNORE INTO t VALUES ... a mixture of non-ASCII and binary content +SELECT * FROM t /*output suppressed, just make sure it does not crash*/; +CHECK TABLE t; +Table Op Msg_type Msg_text +test.t check status OK +DROP TABLE t; +# End of 10.5 tests diff --git a/mysql-test/main/ctype_sjis_innodb.test b/mysql-test/main/ctype_sjis_innodb.test new file mode 100644 index 00000000000..80f3b4fec0a --- /dev/null +++ b/mysql-test/main/ctype_sjis_innodb.test @@ -0,0 +1,62 @@ +--source include/have_sjis.inc +--source include/have_innodb.inc + +--echo # Start of 10.5 tests + +--echo # +--echo # MDEV-28328 Assertion failures in btr0cur.cc upon INSERT or in row0sel.cc afterwards +--echo # + +SET NAMES utf8mb3; + +CREATE TABLE t ( + a year(4) DEFAULT NULL, + b varbinary(2545) DEFAULT '', + c mediumtext COLLATE sjis_japanese_nopad_ci NOT NULL, + d decimal(7,7) DEFAULT NULL, + e char(219) COLLATE sjis_japanese_nopad_ci DEFAULT '', + f bigint(25) DEFAULT 0, + g bigint(20) DEFAULT NULL, + h datetime(1) DEFAULT '1900-01-01 00:00:00.0', + PRIMARY KEY (c(25),e) +) ENGINE=InnoDB DEFAULT CHARSET=sjis COLLATE=sjis_japanese_nopad_ci; + +--echo INSERT IGNORE INTO t VALUES ... a mixture of non-ASCII and binary content + +--disable_query_log +INSERT IGNORE INTO t VALUES +(NULL,'tsls','ce License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHO',NULL,'g',0,4,'1979-03-20 13:59:42.0'), +(1972,'j','? y็˜ข?5๏พ› ~-๏ฝฒ๏พœ?\r?WC @๏พ” ?๏ฝฟ?=๏ฝณr!I๏พ—.%ๆข“?่“๏ฝท?dIT9%N๏พ›c*1i?๏พ‡ๆˆ‘๏ฝต4๏ฝง?)5ๆ…ด๏พ„?/rUGC๏ฝท|ๅˆˆ๏พY5๏พšๅฌถ?๏ฝฐ;ๆบ๏พ– ๏พŸ๏ฝน,Vๆ•|*9๏พ“V@๏ฝค2๏พ•ไฟฎ^ๅƒต!้›ซ๏ฝฆ็ฌต?^j๏ฝต๏พŸ?#Vc@1%B๏พ„?Lo_*๏ฝฆ๏พœF๏พ? ๏ฝจ?5c๏ฝฐ;็ซ™kJa๏ฝฒ?ไบ€๏พ’?~$็ญง?\0Yy ๏ฝน%?S๏พƒ๏พTzu๏พ…Q ๏พ{?$๏พ”??? v\nๅฎ๏ฝด6?้ฃ›?๏พ›่ฝฃ.๏ฝฏ}P๏พ‹๏ฝข่ฒผ๏พŽ_0ๆ“็žฝ๏ฝต๏ฝฆU5&[1iๆทb๏พ’8;๏ฝธ๏พ›?๏ฝช๏ฝธa??\0-\ru?>๏ฝง๏ฝง9๏พk๏พ??็ฆฎP๏ฝณ?ใƒ^=Y?{rRB~๏พ;?}?\r.{)ๅขฎ??#๏พ„็จฝๆ‚ฒ๏ฝฃ??็จท๏ฝง๏ฝจ๏พŸ$O้‡ถ๏ฝฏ๏พš}OS๏ฝถๆž?G?}๏ฝฆ๏พ‚+?1,๏พž&ๆ –๏ฝค๏ฝซ๏พ?@W?๏พ–?ๅปฃ?๏ฝน๏ฝจ้–Š็‘ณ\rN?Xๆ€Ž?\0๏พŸ๏ฝฅ0๏ฝฅ๏ฝค?*๏ฝฝ2}่ซก?๏พ—O๏ฝถ้‰‰+fqJ?๏ฝต\\้Š“๏พad?)๏ฝถh?๏พ๏พ”๏พ็งcT?X??yN ๏ฝซ๏พ>+๏ฝธcV\n[๏พ”4Q๏พˆ?๏พŸd? ?$@๏พ‰.็พƒ๏พŽU?{\"<๏พ–๏พ‘๏พ‰๏พ€๏ฝฐV๏ฝฅz?gP?(\Z>CๅŠช#l๏ฝจ?็”ซQ0่ฑข4=3\\๏พ‡Z!?๏ฝถ+oe$t B{ๆขณๆƒกๆฌง่ฃฒ๏พ‰๏พ€?่ผพ?4๏พ†๏ฝชๅขจ]+ๆท็—ŠlE๏พƒ;๏ฝฟๅ€‘็‹„๏ฝถ0๏ฝฒ๏ฝฑ๏ฝฉ?7๏พŽQ๏ฝซๆฟถl๏พ†> ๏ฝฅjK๏ฝฑ๏ฝฉ?๏พ‹?J่ŒฒX้ซ„F9๏พ„|?๏ฝฆ๏พ…T็ฆ๏ฝฑ๏ฝฅw?8Y๏ฝงB็ตƒ๏ฝฆ๏ฝจAZ?>?8[gvI๏ฝค๏ฝช๏พ‚๏ฝฃๆฟ˜่ฑผ๏พๆ–ฅ-๏ฝธX?๏ฝฅEI82K!?U๏พ˜dใฌBๆŽจ?*??9๏ฝฌt๏ฝธ่Šeไบ‚\0v๏ฝก๏ฝฃๅฅŽ??N?ๅคœV๏พ• 1๏พœ??\0๏ฝนXBo๏ฝฆ\\Dๅ†Š่†จ)5๏ฝฅM@๏พƒ?B?1๏พƒM?๏พŠ๏ฝฐ?6๏พ’้ป”2๏ฝฉoA?๏ฝธ่ฝ„??๏พ–\0E0๏ฝฏ๏พŸ๏ฝตA?RๅƒZU?s๏พau๏พ†?+?๏พŽ?๏พ”\0h?8:?/T?\r๏พ„๏ฝฎ็ฅWf็ฒ•o๏ฝถjjv?ๆฅฝ้‰„p?.8๏ฝฉ๏ฝฅ|ใƒผ*ๅ„บ๏พŒ*ๆ•่ฎCX๏พ’๏ฝฎ. b๏พ’s๏พš๏ฝฅ@๏พˆuๆกฃ?๏พ–&%#^๏พ‡๏ฝฉ?\0ๅญ‘๏ฝนm๏ฝป8?๏ฝญ๏ฝด้Œบ?็ฏ r???๏พ๏พ…?(๏พ€๏ฝง\"w๏ฝฎ๏พ?%๏พ™k๏ฝฐ๏พ†\rVWj๏พˆk?็™œ๏พŠ6m๏ฝฒ2๏ฝกI๏ฝต๏พ“๏พŒ๏พ„๏ฝคJ=๏ฝท๏ฝง??hx๏ฝก ๏พ—๏ฝน๏พƒO๏ฝฌ๏ฝณ*? ๏ฝงd้Š–c#!?0?s๏พ?%v?9๏พ’$\0?K่ฉข}๏ฝด??VT?u\'๏พ‡ ??$?\r๏ฝฟ็šบ.๏ฝกd?!่„›๏พˆ?2& ๆšน?6่ญZ๏พ™^k ๏พ—ๅ„ช๏ฝดi๏พ”๏ฝฑ?\0?<๏ฝด๏ฝทๅญ˜ๆ——ๅซa๏ฝด๏ฝท๏พ„๏พŒ??\0้ ‚ ๏พœ๏ฝค๏ฝฐ๏ฝกoๅฎถ?\0้„??&f?$โ€•?๏ฝบ๏พ’X?6Q๏พ›[r๏ฝŒ๏ฝฟv??๏พ๏ฝญ๏ฝฅ?>YrJ๏พŒ8.๏พ{ๅทฎ?F๏พ‚?v๏ฝฒ๏พ‚?/๏ฝผ๏ฝง???\0Ur๏ฝฃ?$๏พ›๏ฝฉ??\06็ฉข๏พ„^๏ฝต๏พœ?*/\Z?๏พ€i\n^ไบฅ๏ฝธ๏ฝง็นง#ๆฒ“y๏ฝต่ถ?\07c็ฐธ?๏ฝก>่Žช)็ซŸ๏พ„?#๏ฝฟrr&HT?<โ–ณwc๏พ”ๅปธIExA๏พ?๏ฝฆ๏พ†๏ฝฐ?โˆˆ?; U\0Q๏ฝพ๏พ˜๏พ—๏ฝจ\n๏ฝด\\Fi\rj็ฏณ?๏ฝธ?g?:ๆญปbRๅฉ‰ \'๏พ„๏พ„้›ฃ?็ฅบJ?e\0\n?๏ฝณ๏ฝฝ1้€“d๏พ˜๏ฝพ?-\\๏พ’??๏ฝถ๏ฝธ bnoJ?9<;?%w{%๏พ“s็•ช?ๅพช ๏ฝปๆ‘ๅคข?๏ฝชUS?8P๏พ็ด…๏พ„ๅŒ†้€3็ฅ—๏พ™E๏ฝฑ๏ฝค? dๅฎถ็ญ”๏ฝนYN๏พ?6*?๏ฝฒ๏พ—m>๏พ๏ฝฎ\\NAFๆ–Ÿ๏พ™m๏พˆๆ˜จ*๏พŒ๏พ™๏ฝณaWf๏พ?vl๏พ™๏ฝฑWc๏ฝน๏ฝทJ็ธฑb๏ฝฎ๏พ?๏ผธ๏พ…Vf๏พ…&N๏พ˜?*?๏ฝณb๏ฝฎ๏พ?6*?๏ฝณb๏ฝญ๏ฝฏ\\๏พ…H๏พ€๏พ™๏ฝซ้ชธ=r๏ฝณf๏พ…ๅฝ๏ฝท๏พuNT?9NๅŠ”๏ฝน\Z?S๏พ‘nl๏พ™๏ฝฐ๏ฝก๏พ™๏ฝณf๏พ…]?6lU๏พ™๏ฝณf๏พ…]?6lU๏พ™๏ฝณf๏พ…]?M๏ฝฑ๏ฝธ๏ฝช?๏พ†ๅ™ซ?็ฎ˜๏พ?6*?๏ฝณb๏ฝฎ๏พ?6*?๏ฝณb๏ฝฎ๏พ?6*?\ZๆŸJ?,pๆ“๏ฝฅqHh?๏พ?;6l๏พ˜๏ฝซ๏ฝณf๏พๆฃบ6l๏พ˜๏ฝซ๏ฝณf๏พ‹๏ฝก๏ฝซY๏ฝณf๏พ…]้Œซi\\๏ฝก๏พ—??;็ญง\\๏พ™๏ฝณb๏ฝฎ๏พ?6*?๏ฝณb๏ฝฎ๏พ?6*๏ฝธH@๏ฝฆ7๏ฝฎl๏ฝต48๏ฝซๆค›่ตด๏ฝณ1้šŽY๏ฝณf๏พ…๏พ?6*?๏ฝณb๏ฝฎ๏พ?6*?๏ฝณb๏ฝฎ๏พ?6*๏พŸ#๏พ“+6lU๏ฝง๏พ„๏ฝฒIF้ฉ58#้ง†็–ธr4f๏ฝซๆ•Wๆฅ b๏ฝช9๏ฝณf๏พ…]?6lU๏พ™๏ฝณf๏พ…]?6lU๏พ™๏ฝณf๏พ…]?6lU๏พ™๏ฝณf๏พ…]?6lU๏พ™๏ฝณf๏พ…S]:๏พ”J7๏พ‹๏ฝป๏ฝถ็ถด?Aใ€•๏ฝฏ 0}่คธ???,NVl๏พ˜๏พ™๏ฝณf๏พ…]?6lU๏พ™๏ฝณf๏พ…]?6lUZ fๆฅ™q7Bๅฆ็ˆฟ+๏ฝฏ๏ฝซ?9 f๏ฝฃL\'๏ฝฑX่‚„?&[๏พ‡ๅฐ‹๏พ€๏พ˜?f๏พ‹U,h2๏พ™\n\Z*๏พ๏พ‹d๏ฝฆP4๏พ‹-\\Unl๏พ™๏ฝฑWeโ€•๏ฝฌ|F?Ui๏พŠ๏พ…%?็ญฌๆƒฃๅ–˜๏พ’๏พ›๏พ–๏ฝธ?7\\-๏พ‡๏ฝจ๏ฝด๏พ€?&l๏พ™๏ฝฐ๏ฝก๏พ™๏ฝฐ็ฐฝNB\\aL้ฉšๆ——cJ๏ฝท,๏ฝฌ๏พ˜๏ฝช?? ?)่ถŠ.*mๅนกๆŒพ๏พš)+๏พ—๏ฝฏๅ…‰G\Zcd๏ฝœB1_Y0๏ฝพ/่Ÿ 01G๏ฝคไป„I?้ฉช$ๅ†‘ๆทป่ฆš?B?\";๏ฝฎ๏พ๏ฝพG&e๏ฝฑๆทปๅ„4Q๏พ‰?๏ฝช>{็—ž?XG๏พˆ๏ฝซๆ ซ๏ฝฟ่ฒV9iๅฟ?=}๏ฝฐ?๏ฝธ๏พ˜๏ฝจๅ‰Œๅฉ๏พ›ๅปฑy๏ฝจ?๏ฝฏ??\0+??๏พ›?d๏พ–-\n?๏พ•้ฐ’ๆฟคA?๏พƒ๏ฝง-๏พ…^\0l=๏ฝซ?_/?&?\0[?๏ฝฎm๏พ€่ฉ K\\๏ฝผf๏ฝต๏ฝจ=sB๏พŒ๏ฝญ๏พŽ6*๏พƒ๏ฝก?๏ฝธ?ไฝ— ๏ฝก?c?|&?๏ฝง็นš๏ฝขUdๆŸj??้šˆๅฐฝ๏ฝทO qq๏พ€RFๆพ‘?&ๆพ?็ฑฌ??-f๏พƒu๏พžๆ”ซ\n๏พ”W?\0๏ฝข1)QTaQ๏ฝทlXE๏พ…e๏ฝด๏ฝฏ๏พ”๏พ…๏พ’ๆฝ้Œ ๏พ•็‘ฉ#F๏ฝต44?P่จฃ&๏พž็ฉ‚?๏พ‰t?-5>O๏พ™_๏ฝฏ?Z?๏พ’?\0ๅน…J๏พ•??ๆ‘๏พŠ๏พ€๏ฝฏ_๏ฝธ?่ซก{๏พ€TGt๏ผ•โІ:ๆต„_?k๏พƒ?\n?I่น ๆ‘ฏๅป๏พ๏ฝถW???๏พŠg่ŒŽ่คถ3ๆฒ็ธฑa-๏ฝด๏ฝซ$ๅฟค่‚–?\04็Œด]n?๏พ…)๏พž๏ฝปๅ—น?\0*???-ๆฅซ??๏ฝง๏พ•๏ฝฏz~??)2A6ๆป,\r๏พ๏พ„่’‹?G6wi๏พ•๏ฝผ้ŒฏI๏ฝญ{ๆป•N,Y@็ฏฆ่œ??\0U๏ฝฒ9a|๏พ–๏พ€Gv๏ฝก|O?๏ฝฟ๏พ…?8{Cr๏ฝข@k?8๏ฝฑ/F๏พŸ๏พ‚ไป„J๏ฝด m\\๏ฝฆDZS?|๏ฝฏL2?G?*๏ฝจ๏พ„๏พ\0>9้†๏พ›|F61?ๆซšT?]๏ฝซ?๏ฝฌ.I่Ÿถ8๏พ๏พ’I๏พƒ !?|q๏ฝชๆšƒ๏ฝปas๏พ{SU้ ‘)๏พ…Szๆข๏ฝจ๏พq๏พœ๏ฝซ)?๏พš็™–๏ฝฌๅณป๏ฝง่ ฃ/z\\4๏ฝท๏พ”R้ง›๏ฝฉ?๏ฝง Gๆฝค?$UG๏พ€??X๏ฝฎ๏พš\Z$ๆง?๏ฝชR้ปป๏พ๏พ“๏พŸK๏ฝฎt?่พฒv๏พ๏ฝค๏ฝค๏ฝฟ? ๆˆก9&?ฮš่€?ๆจ‚]y? ๏พ›๏ฝฏ?U็ถฝz?๏พ—๏พ…ob๏พ’๏พ†)๏พ…๏ฝพ๏พ‰_ๆŸฎ}c๏พ‹3้ฐ“ๅœป;?\n๏พ“??\0๏พ‰๏พX=๏ฝฒN?)+B7?)็ท_๏พ‹UFTE?ๅ—ฝ๏พ‹!็ญ๏พœ๏พ„๏พ„๏พ‹??๏ฝงq้ฐฏ็ฆ€๏พ3๏ฝฟ]y>๏พ‚้ทฝrFm่ฆฏF?๏พƒ?c?/3?[[\\A?๏ฝช ?\n๏ฝญB??\0)๏พj?\0?p๏พŒ c๏พ€?E๏ฝจ๏พŸ|๏ฝฉ#่ŽŠ?Z๏ฝทๆบถt๏ฝท+,r/๏ฝผ่กฐ}?c\nJ๏พ่›Ÿฮป?%&h\Z๏ฝซ๏ฝฑ๏พ‰<\Z๏ฝฐ๏พ”๏พ€ๅ—ๆฌบ ๏พ#n๏พƒ?็Œ?\0๏ฝฎ๏พ™x๏พ?8๏พš้กณ0๏ฝจ,?๏พ”ๅญ—x๏พ‡3?RO?e[ๆข๏ฝฒK}่Œ˜mr๏พu]?;\n๏ฝผcb๏ฝญ?U?E ๏ฝญT๏พ“๏พ‡๏พ›?\\ๆšฎ?:่ณฆG๏ฝจY๏ฝบ๏ฝผjh๏พŒ๏ฝค๏พ€Lๆตน๏พ‹??%๏ฝฃc??I๏พŒ?๏พ˜Z?ๆฌฝ๏ฝญ?2๏พ‡๏พ‚?;่ฟซ?๏ฝฐ๏พ:?ๅญƒ4่’Kyๅ…ฌ๏ฝก? F๏พœ๏ฝธ;๏พ?!d็งฐ1??\r๏พ•$^?้ฃฝ?-๏ฝฏXj\Z)1๏ฝฃ?-e?A่‰ทๆ›?๏พ‹๏ฝฏ?W๏พ‚%๏ฝท\"ๅฒถ?=wO?=๏ฝฏๅƒญ๏ฝง/๏พ๏พ€๏ฝฃ๏ฝซT็จฎ?๏พ‹$v?๏ฝป๏ฝง๏พMๅ‡›4}e?\0๏พ–๏พ=้˜ฏ1๏พŠๆปฟ๏ฝชN๏พE่™Žz?9(๏พ“|?.ๆข…๏ฝญ้ซฏt?15?\0่ป|YT?Af ๏พ—\Z\0๏ฝญE?A๏พ›?๏พŸP\0?๏ฝด7?\0b๏พ‹?6๏ฝบ? ๅฃฑ2H๏ฝป๏ฝฆ๏พœ??k็ญฅ๏ฝซ๏ฝค๏พ‘ๆต…??๏ฝถA*QX?\0?4o๏พ‡??_??( Z๏พ“๏ฝฟo?h๏พ–@๏ฝข๏พ†S็šบ?J่ก„๏พŽK,ๆค้ค˜[๏ฝฏ็ฃ‹๏ฝฑT$Q๏พ‰?74?1@cๆ•ฐ๏ฝจ,:?๏พ่Ÿน1?7ๆ‹“ไนž๏ฝฒๆ‰ฟ_?ๆฆพys?็๏พŠๆต„็ญฌ^๏พ ๏ฝก??9?h๏พ๏พƒ๏ฝบ็’ฝ๏พ›ๆ‰‹F?๏ฝบ๏ฝฐ?็—ฐ็ญ†G๏พ’1V:?(ๅฑ‘๏พ„>๏ฝด๏ฝฎGu?,๏พ™k0 ๏ฝฑ๏พz?๏พ†๏พ™7๏ฝน๏พ’๏พ„โ”ซๆฃ}ๆท˜?OEy๏พ๏ฝฌ,๏พ‘๏ฝต*E?ใ‚ซ?๏พ‹ri2๏ฝฉ?={?\0๏ฝฒ๏พ‚3๏ฝจ๏พŸyr?๏ฝญ~??)๏พŸ?่Šญ?\0\Z?+P๏พ๏ฝฎ,ๅŒฏ๏ฝฃ]๏ฝน\0v?\0Z๏ฝน? ? Y็ตตC๏พ—08&Kv?(๏พ€bk?&+๏พƒc๏ฝช%?๏ฝญ? ๏พˆ=๏ฝฒ๏พ•A5๏ฝฎa?1kR๏ฝจ๏พ•ๅฝซ๏ฝด๏พ‚๏ฝซR\Z็ง๏พŸ๏พ‹๏พ“5๏ฝธ๏ฝธ่ƒ™๏ฝถ0F]?G)BH9๏พƒ๏พ‡t๏ฝงJ็ถบ6๏ฝฎ ๏ฝซQ|&ๆŒ‚?Fk๏พ…๏ฝจ}๏ฝฐ2๏ฝท๏ฝปS$\Z&๏ฝฝ5ๆŠ–\"J๏ฝง๏ฝช7?HๅฐŠP๏ฝข๏พ—?-?๏ฝจ?hq๏ฝซ \\FgRZๆฎ˜๏พ›๏ฝป๏ฝฒ\Z๏ฝซ๏ฝต๏พ…?5iWJR็ŒV-่“BK๏ฝฟB?F???6*๏พ‡>๏ฝฉ@A F5~้‘›ๅพณ(ๅฒซrf๏ฝต็ด ๏พ‰C๏ฝธ9๏พ–t๏ฝปhde๏ฝถ=+N??\0๏ฝฒ๏พ„|๏ฝฝ๏ฝฏK?]+ใพ?๏ฝฑ๏พ/\\vQ๏ฝฑz๏พ–๏ฝณ ๏พ‘Z๏ฝปๅ€ฌ?\0k?๏พ‡็–ไผz^ๆฆŽ?/๏ฝญ\'M๏พƒ+S??\0.๏ฝธdhKx๏พœๅญธๅณฐ้ณฉc?j?\0่‰‡8M$(^๏พ…๏ฝฝd?h(\0๏พ—?5๏ฝถ๏ฝญ๏ฝฏ)่‹‘T๏ฝฎ???\0๏พ†๏ฝธ๏ฝคๅฃฅ๏ฝถ?0[๏พˆ\r๏ฝปๆ”ฃ๏ฝง๏พ„๏ฝง??\r๏พ•(๏ฝฐ?๏ฝถ?0๏ฝบ?i๏พ…??ๆณจ>?y?,?๏ฝฌh๏พ”๏ฝธ๏ฝผ?z?*G๏พ”1๏ฝฆ๏พ”๏ฝฌไฝ?(ๆˆž่Ÿถ็ณข๏ฝด๏ฝฏG๏พ‰Pๅ›‚็ฒ˜S๏ฝฝ๏พˆ?0๏ฝช?ๆบฝ๏พ‰%ๅ‰›๏ฝฐ@mๆ…P(S่ฏ๏พ“๏พ‹!Zๅ†ข๏ฝค๏ฝปh่ซท?๏ฝชkQ?๏ฝฏ๏พš๏พ‰๏พ‡๏พ–fe๏ฝชn=?66*?2?X๏พ‹๏ฝจ๏ฝณO\r๏พ›๏พ‹0๏ฝฉ)57๏พŠๆฌก๏ฝต?5?1๏ฝผ๏ฝป?W??๏ฝฒ?ไน˜?)i~??่ณฝ?)?1๏พUc_่ฒข#?\\?>??+C%?-๏ฝข<็ฉฝZ็‹™๏ฝถ*๏ฝฟY ?; ?้น๏ฝถ๏ฝถ?:๏ฝผๅผ‰X#๏พ€jโ‰ก๏ฝง๏พšT\\K^๏ฝด๏ฝถ๏พ“/G้—?$$FW$๏ฝญeๆฐ›_y๏พFใ‚ฃ๏ฝนใ‚;?^ๅš‡?j?)j?๏พ„๏ฝบF๏ฝฏw?]:O?z?\0;|G?/๏ฝป?a่‰ช๏ฝณ๏ฝฒ๏ฝน๏พ•fFD่ทณH๏ฝซ\\?๏ผฃๅฉ€?๏ฝง๏พ‘i# Pๆ‰ฎ?s๏พ›[_^t?!yQ\\?๏ฝฟ??\0?4ๅฏ”๏พ’o๏พš-D๏พšd๏พ“\\๏พ“๏ฝฅ๏ฝป๏ฝตๆ„ฌ,ce#jๅพฉ๏ฝณ๏พ?bๆซ }B๏พ™L้‡fSJ?,#e๏ฝฐๅ•ผr๏พ“mh&๏ผฉ๏พ•jVM??๏ฝฃ๏ฝณr๏พŽ]๏ฝฌj๏ฝฆ็Ÿb5bj๏ฝชI?W-่”—?t?่ฎ’๏ฝฆd๏พƒ่››ๆ‰ฎ4๏พŠP ๏ฝก๏พ†?8?.๏ฝน๏ฝธ?๏พŽQZo็•ขxm๏ฝจp%j?:่”‘XไปŸH๏พ…\r๏พๅซ‰y?\'๏ฝฎ^)DC ๏พˆ2?\0=?\0็ถต๏พ—ๅน•ni๏พŒ@v ?\0๏พ„ ๏ฝฎ53\0F?mi๏พŸ๏พ…r\"ๅญค๏พ†๏ฝผ๏ฝฝ?/0G๏ฝธ๏พŒ$๏พž๏ฝง\Z๏ฝตUg$\0c๏พ›๏ฝถ\"C็‹‚W2N O๏ฝฒB?b๏ฝจd^g๏พŸEnjR๏ฝค\rๆฝค๏ฝฏ๏พš๏พ€๏พU59Bb6๏พžไพ†J?7\\๏พ‹๏พ‰๏ฝบ\n่Š[w#๏พ•่ญด?&๏ฝฟ/?๏พ‘๏พšz|็™œ?N?O?V|RTW}?ๆ—…|g\"?๏ฝจmๆŸ”|b?EI?0ZU?ไฟฅ%?๏พˆ&ๆg๏ฝถ?8๏พƒ?!||q็ตณ๏ฝธhM๏พ‰็ฎœ???Z๏ฝก\\??F๏พ›?็ฟก??%W?m๏พ‡? b๏ฝทZU๏พ๏ฝคbyzf? ??\0?ัŽ่‚„?)b~๏พˆ??6i๏ฝซIg้€ F๏พž๏ฝจ ๏ฝณ $?.๏พˆh=๏ฝฑ๏ฝด๏พŠ๏พƒJ๏ฝฌ\Z?I9|๏พŠW่ฏ?#๏ฝฅq?@๏พ?#๏พ›/iๆŒ™P7๏พ›?๏พŠT\'~๏พ˜mv๏พ—้ณณ+๏พ†ๅ…ถ\rA\0๏ฝฐ=๏พ™pๅ?0๏ฝจ๏พ›ๆŠ’?8?็ณŸq/^๏พ€t2GSH๏ฝก#๏พƒ๏ฝด๏ฝพX๏พ™}h๏พ’TP@V?\0๏ผฉ?;?.mZ6\rXๆ’ค??g็š€}ๆปธ๏ฝฐr้šง|M?0v^T?\rh็€พt?4\"?F๏พ‘้ฎฎ้ถฒ?-?ๅ„ผ๏พV/YY%~??\0๏พŠ่ƒas?!MG? ??nE?\n๏พ“๏พ‡?๏ฝท?4@yๅป\'?้Š€๏พ†๏ฝช้Š…๏พ”่ฝๆท‹ๆท˜P๏พ„t๏ฝฑ?\0c๏ฟฃ่ŽŽbๆž%๏ฝน?\'cLๅ‡‰f๏พO๏พ–๏พ–[[้œชr๏ฝฒ?P?/่คธ๏ฝพ?#?๏ฝง\\=๏ฝด็ˆฟ#SqJ?\0??๏ฝฎ7๏ฝฝ/ๅšฎ|ๅ‡–๏พ„??T~b?JD๏พ‘?๏พˆ่ตซ๏ฝจ?่ตKK๏ฝฉ?๏พl???x๏ฝปๆจžV่Œ/!?๏ฝถ??8z?*๏พ‘๏ฝตT๏ฝฅOๅฃฑ?>๏ฝปOn?ๅป)-wQ็œฆ?\rW๏ฝฃ-w\r1๏ฝฒZO\\??(Ykn?!?GR?\'?U?๏ฝฌ๏พ๏พ†๏ฝก๏ฝบ็ฝซK?๏พ‡?Jๆงจ๏พŸPp1ๆŽพ5>9๏พ’๏ฝณๆˆฒGQใƒ?๏ฝญN8๏ฝข๏ฝนnK?@)?๏ฝฌ๏พ…B๏พ•N?๏พ†-mh๏พ“)??\0vๆณŒ๏ฝฝ6๏พ… ๏พš๏พŠ๏ฝฐๅ–ถb?@็–‘๏พŒ๏พ??๏ฝถ,$\n)๏ฝขๆงจ?|๏พ’๏ฝท6b3bZ2T?gๅฅดPc๏ฝข๏ฝถๅ•ผ?\"Feะฟ๏ฝตq6r68?*่—ฅu๏พ_YD๏พ˜๏พ“??๏พŠ๏พ๏ฝฑ๏ฝฅD๏พ‰p+T๏พ„๏ฝธ๏ฝผ?rะผ|๏ฝฒ?9?6T3D???q?0;Lh็ƒ๏พ•~?\n๏ฝฌ๏ฝณFๆˆฒj>??*๏ฝฏJbq๏ฝบG ,9๏พ†%zT|๏ฝงu้™€?๏พ“๏พƒZS\'๏ฝต๏ฝท7r๏ฝฌ*UK\ZU?kx่Šณ๏ฝฆ่”Ÿ๏พ˜vh๏พ–,๏พ‹?๏ฝฏ5\0+๏ฝฝ๏ฝพ4๏ฝซ๏พ›Fo?3+๏พŠ@;J?q๏ฝฃqg?\\ๅœŸ?=>?๏พ–๏พš?i$๏ฝฑK\\ๆป“iG๏พ€๏พ??ๆธŸ๏พˆrN๏ผƒๅคฅ~-?CR[๏ฝฉ+\Z\0+๏ฝฐ๏ฝฎ\n๏พ6ๆ˜“๏ฝฎb๏ฝบ๏พžv?๏ฝซP@PP|???๏พ‚aๅฒฉ๏พO๏ฝค? ???๏พŸe๏ฝฐ๏ฝง๏พŒ?Yjs๏พ…\0? ๏พŠ๏ฝต๏ฝญ|I\\A้–ญ๏พžๆปด๏ฝป?๏ฝท๏ฝถ{่ฃ‚๏พ’ๅบ– ๏ฝฝ๏ฝณ๏พ‡๏ฝผ๏ฝธ?3ๆฉ˜?๏พž:Qไน‹?}๏ฝค?\0ๆฃ”๏พ?\n๏ฝฏๆฒธx/๏ฝข?\"G๏พ@j๏พ?\0็•ช๏พŽ๏ฝนe๏ฝฉ๏พ…w$?*89 H?้ฏค๏ฝฌๆณ“Mqv๏ฝฒD? 5๏ฝฆ๏พŒ๏พ„๏ฝณ?8o๏ฝฎ๏พ›CEo๏ฝผhv-J็ฉฃ่กž๏พcf]๏ฝฅ? $??๏ฝฏ?,T[0&Yๆ›ฝ๏ฝชzaNๅ…Ž%๏ฝฅ๏ฝด0<๏ฝขF๏ฝก?)?\"Z๏พ@๏ฝฟ?็…ขE๏พ‚๏ฝณY๏ฝฐ>๏ฝคgzq=~๏พ—๏พ…\\ZG๏ฝปๆ•๏พ—,m็•›2๏พ†?A?๏ฝฉ~,.๏ฝพ๏พ”๏ฝฃiqrz๏ฝช???็ฐ—z?e^\\ใฃ๏ฝฌ^% ๏พŽ๏พ‡่ฟ@%๏ฝฟ๏พ˜?ๅ›? ้ˆŽ๏พŽ๏พ\nโ„ซ๏ฝฌ@?4?\0ๅก๏พšS;๏พš๏ฝฌๆ‰DJ?็ถซ??l0๏ฝบ๏พ“^๏พ–๏พ•/Q?\0x่ฒŽ๏พ™1gไธถ๏ฝง้ก/{๏ฝงG๏ฝงI\rcๅ‚‘๏พ.๏พ‹็‡น๏ฝปE_?็ซŠa๏พ„?\0l\r๏ฝฆๅฉช๏ฝญK๏พ‰!๏ฝจ๏ฝขๅˆ??v๏พmJ g$?Q๏ฝฟ?๏พM๏ฝซ?2/๏ฝจ๏พ”P๏ฝฃa๏พ“2UI๏ฝฏ\\\"?$P้œl๏ฝจN?t;v๏ฝฆ*?^<่ฒก{?:๏พ”?$?\0G?qๅบท้…ฅๆฝ๏ฝฎMf๏ฝบY,\\๏พ˜?9k#*๏ฝต&๏ฝน ? ?3ๆ—บB2?^\n nN6๏พš๏พŒVsE\'๏ฝฉ๏พ„ๅฌฌ^?\rOlๅธ๏ฝฉ2๏ฝซJ b๏ฝด$๏พ“?็ชฎ๏พƒ็ฌฌ๏ฝญG๏ฝฆ<5c\"5๏ฝฝv?\0U+?๏ฝฅ?XxQ๏พ˜๏พ–??ไธŽY๏พ˜R?(2?L)??1่‡“FKgwๆผ‚J?๏ฝฐ?ๆ•ดL๏ฝขPๅธญ๏พ“๏ฝธ?#D{3Ic้ซ˜G๏พ?1 Az?๏พ–?2?7๏พ‹^~?๏ฝฉ??๏พ‡)๏พˆ๏พŽ,f?wpR\Z๏ฝธ๏ฝฏ\'?$0๏พŠ;?1๏พšjrr;๏ฝฌepO?)!\n๏พ–้นนF้Ÿฒ@? ??%? ๏พŒ่ ฃ3&๏พ‚ๆ–น O๏พš๏พ‰้€ธ๏ฝพ๏พo็ฅฟๅฎธ?Q๏ฝฟ \n๏พ”๏ฝง๏ฝฉ4๏พœๅฟ–๏พ“>๏พ๏พๆทณ๏ฝง?๏พ†?(??b๏พ…๏ฝธA\'๏ฝฐ?!8้‡h๏ฝซ๏พ›๏พ„ๆฝบ็Œซy?ฮต๏ผš่Ÿพ๏พž? ้š ๏ฝฝ๏ฝง?๏ฝค?\001๏พž๏ฝฉ๏ฝฉๆผ†[๏ฝชX?$p๏ฝณๅŠฉ๏พ‚\0๏ฝด?ๆ”ฟ๏พ•L ๅ…๏ฝญN;่’ผ~?:็ฟ”t้ฎ“S\"๏พ–๏ฝฆ๏ฝค็ซŠ๏ฝค\"J?W?8๏พ€๏พ“-ๅœœ?๏พ†9๏ฝฆ๏พ?๏ฝก??๏ฝก๏พ…7๏พ†q-๏พ—a็นฝX๏ฝน}??๏พŽ๏พ˜\nw+K็ฟซๅ†ท๏พ†๏พ„๏ฝผๆ€บ??๏ฝฉA็—ผ?)?V?๏ฝฐ๏พ…้€™๏พ˜๏ฝธ ๏พ”??A๏พ‹PE; n๏พ”?๏ฝฎ#4้กๅบถ2Iv?\"?l<0?๏พ†๏พ‘i???p4?b?๏พ—Z๏พ—$t๏พ„ๅฃบ๏พ’๏ฝชY?\n.o?๏พ…๏พ“๏พ‡\'rbd5y?6้ตฒK;Jw;bl่”Ÿ๏พ†ๅ†ช๏พ†#๏พ‹ๅงœ&M๏พ–?2่ญฐI๏พ†ๅฝ“*้พWLu0๏ฝฅ๏พ™๏ฝฉ?.ไบ™[๏พ\\๏ฝฌ๏ฝฑ???\n?๏พ—[ๅ›Ž๏พ‹9๏ฝฑV๏ฝธ่คŠๅฒผW\\Uz๏พ’๏ฝต๏พƒ?*?ไบคE$?? AR๏ฝคw%๏ฝผ๏ฝง?*??๏ฝฟ้Œฎ๏ฝง๏พˆ๏พ‰ๅจ  ,๏พ’็”ป๏พ›๏ฝตw?\0e?Bๆฟ”V?B}0๏พ›๏ฝฝ66??JG???๏พ‚๏ฝฝ+L}b็ฌŠ๏ฝข\r๏พ˜?๏พžUF๏พ‚๏พ‚mJ@?\Z??๏ฝด๏พ;%๏พ›? ๏ฝท๏ฝด้ฎF8๏ฝข? ?~+A้ฏข????๏พ–๏พ๏ฝผ๏ฝน.๏พ1๏ฝบ๏ฝผๆ–œ:๏ฝน\nๆณณ~ๅ‘ˆ๏ฝฉ\rQ<{?+๏ฝผ๏ฝฟ็ด„๏ฝน๏พŠ๏พ•=๏ฝผg๏พ‰\0I\\๏พ’Wg๏พ†๏ฝณb|๏ฝท๏พ€J@Vd๏พ•_l๏ฝฑ7:{็ฎดT้ †๏ฝฎ*๏ฝ”z๏พ€็ขบ?้ฌจ็บˆ|?0?็ต†S๏ฝตA๏พ…RX๏ฝฏ๏ฝฅ๏ฝต?๏พœ๏ฝงๆ ด๏พƒ{?๏ฝฅ๏ฝถ๏ฝฝp-๏พŽๆถธ๏ฝซ๏พ†๏ฝนQ๏พ‚๏ฝญ??๏ฝฒ๏ฝฏ+%W|T$๏ฝธ8J่ผ”N๏พ˜am1?DH?๏ฝน?็˜????๏ฝง๏พš&๏ฝฃ๏ฝฆ#*4d๏ฝฒๆคˆ๏ฝชIu๏ฝง?๏พ”2??p๏ฝข?:#$P๏พŠ%R๏พ•;ๅ›[D?็˜ง๏ฝฑ๏พ‹๏ฝฝ๏พƒ[\'P๏ฝฒS?๏ฝก๏พ‹ๆ‚’๏พ_?3i?๏พ“๏ฝนI $ๆซจY?๏พ•?๏ฝงL?-l๏ฝฒ!c๏ฝฑm็ฟ1\'๏ฝค?7$?iZu๏พ‰FF\'do่„นt๏ฝป?2K๏ฝฉ(\r+๏พ›๏ฝฌ))็ญฅ?9้งฎ4?]Xy๏ฝฅL่ฆk๏ฝข6?๏พ?\0W??\0็ฆณ๏พƒ|๏พ•? ?)J!๏ฝฝ@้‘ฟYP\'??ๆ‘ธ่ณ„๏พ›๏ฝซY? bm>h?u๏ฝฆyๆฉธDๆฃ ๏ฝน๏ผง๏พ™d๏ฝจ?2๏ฝณ~๏พžs๏พ˜?-้นตjฯˆXl่ถบ๏พƒ-;T๏ฝค?\0~๏พŽ๏พ•(๏พˆ่œท?0F๏พŸ$้ง…๏ฝฝq?k G๏ฝฃ$ ๏พ€zๆˆช???T???r@๏พ—,๏ฝฒ$๏พ“q?3?sC๏พs่œ?c้ค“.T4l๏พ”?)๏ฝฑS??่’ธ๏พ—๏พ‰n้–ค?ๆงŒ๏พ†uๅฃœๆ‚7๏พ็‘ \'?๏ฝจ?P#ๅซฃ6?!u |๏พ•๏พ•???2๏ฝค?*๏ฝฃ?\n๏พ–ๅฏƒ?๏ฝซ~๏พŽI๏พ”]tT๏พ๏ฝฒ๏พ็‹™๏พ™็นฝ๏ฝด๏พ—๏ฝฝ\"?>p-@้ธ๏ฝฏ?O๏พ™๏พˆ%3x#ๆฎ€?~?๏ฝตๆผฌ็ข•๏ฝก๏ฝฏ?* M๏ฝญn๏พž๏ฝคMC?@??๏ฝซ3?\r R๏ฝด๏ฝฎ?๏ฝซEbx๏ฝต=๏พ†f็ฐ—K๏พ“๏ฝฟ?๏ฝช๏ฝฉ_Je๏ฝฏC@i๏พ›#a๏ฝณ?$v\'?6๏พ…P2i๏พ‰ ๏พ›?๏ฝช:็”ผ๏พŽ๏ฝŽ?/%e*๏พƒ๏พ‡$G??i?(๏พŒI?๏ฝผ๏ฝฏV?P่ฆ“:่•จะฃใƒ€๏พ˜??\05dCW?๏ฝท่‹งไปญ๏พŠ๏ฝก?๏พ˜่–? ๏ฝญ?J?๏ฝบb]P๏ฝน๏ฝก้ซ”!;๏พi@9๏ฝฏ๏พ‡?;๏ฝฌ๏ฝฟ๏ฝณ?๏ฝฆ๏ฝท?็ข๏ฝพ9๏พ™?(๏ฝช๏พˆ๏พ’๏พ†๏ฝง?็ดš๏พ˜} ?\0๏พ€่†€?๏ฝน่‚‰&12?i๏พ‹r?๏พ”ๆฅ ่žป๏พŠ๏พ„๏พ…?\nๅ“‰Xๆฏ”ๅ˜ฒq?R??:?\0๏ฝฑ๏พ‚ๆฐ—??้ซข่ชฒ\ZRx่ŠA\\g๏ฝคTQ?๏ฝฟ|mf?๏ฝด#?K?้˜ช?*๏พ‚๏ฝด?่ฑฌ?=๏พ†?๏พ‰Z9J๏ฝซ็™พPqx. V7๏พO๏ฝพDm๏ฝธ่‹ณ;r#??p๏พ›๏พˆ้ˆž๏พ…๏ฝคๆˆŸ๏ฝตw้คกๆŽŒG?+@GCๅœ๏พ™ๅœง๏พ”.,ๅฏžT๏ฝฏ~๏พŸ?\r๏ฝบ๏ฝทn_X๏ฝถm๏ฝด๏พ“U#๏พ”#U2ๆŠ„???k็ฐ—h๏ฝฒM?็—ฐo\'%๏ฝก5๏พ“?%?๏พœ๏ฝข\"4Jd^?5๏พˆ?ๆงฒ=6ไบ‹?$๏ฝฅ๏ฝฎH\"ki๏พ”Oไฝ•๏ฝฐ้‡Ž๏ฝข่ˆœh๏พŠ?[?้–คD?;่ŒŽ๏พŸๅญ›?(็ขฏ๏พ›๏ฝด๏พ†2d๏ฝถn\\๏ฝปS๏ฝฉ๏พud?{ฮฒ๏ฝฐ?๏พŠๆปด๏ฝตx?.?d?๏ฝฎT?๏พž8?็ณŠm^?\0?Yom๏ฝฌ!\\๏ฝซ๏ฝฑ๏ฝจ๏พˆ๏ฝฅG?Uๅผ˜๏ฝฅ๏พ‰ไป˜?h๏พ?๏พ?\0g?่ฒ”h?E๏พ๏ฝซ*\\๏พ†Xx??=๏พ™S้บ—.v็ งizK?๏พ?๏พ„๏ฝฅ๏ฝฑ๏ฝฐ๏ฝฝ๏ฝฏ๏พ–? X? d?3?-็™กๆ›ฐ๏พ”๏ฝด่™sy$๏ฝฉU2[?OO?,!OZZ๏ฝต?hNz?R?ๆฏณi?$bๆก™๏ฝฝ๏ฝฟg\na?๏พ†ๆคฃ4v?[b๏ฝฎ T?\0/*่žข76&/*๏พ”๏ฝผ๏ฝซ!๏ฝฑ]N๏พ…๏พ–?ๅš‡ใ€…๏พ7?่ƒด๏พƒ??่ฉ†๏ฝฌY_๏พ›Gsh๏พ??2)V๏พŽ?้ฎƒ๏พž\\?2๏พ›ZF๏พƒ๏พ“rP่ทก?i๏ฝฃfEu?\0>๏พm๏พš๏พj?+sr@PS?;๏ฝช๏ฝง?<ๅฝณ๏พ„;๏พ’๏ฝค??\0๏พ‹pjๆญ‡Dt๏ฝถ้ณฌๆตธ??๏ฝธ๏พš๏ฝฟi๏พ‹๏พŽ๏ฝฑ๏ฝฆIๅฌช?6?v?vH9๏พ…็ฅ๏พ‘_๏พƒ{,a๏ฝฃw่”•๏พ€R??C~๏พ–umBo?;[9-,๏พ˜้†‚?๏ฝด*?\0?๏ฝฏ sLQZ๏พ†๏ฝฉu%็นŠ??/k๏พ–ๅฅฌโ”“๏พ†๏ฝฏN[?๏พš??7H๏ฝถๅถL\\๏ฝจ?ๆฝ˜?\0?H-๏ฝด{G๏ฝน๏ฝนะปf้ ป*~ๆฑบ๏ฝจ็ด€๏พœ๏ฝฐMK๏พŠ๏ฝท\Z=?๏ฝฒ?H๏พ•๏ฝฃ;u๏ฝฃ#้ด‰๏พœ๏ฝฅ%\0๏ฝฉu๏ฝจๅบฆ่†•U๏ฝฏ๏ฝพHY็œŸA็ฒซ๏พœ?๏พ…h|\'?6? ๏ฝถ?\"i๏พŠๅจถ่พฃ๏พ”๏ฝงNไบ™m๏ฝซ?[5๏ฝฌ ~๏ฝฏ๏พ•๏ฟฃ๏พƒ้ฑ 3\r๏พ–๏พHHpU๏พ‹\"ๆฐ›Sๅ‡‹๏พ›ๅฃบ?็ซ•\Z๏ฝน?(๏ฝง\\y*?aZ๏พ“;W้€“๏ฝป๏ฝฅX๏ฝต+X๏ฝคI?๏ฝค??๏พ‡8๏พœ?\'๏พƒ๏พ€๏ฝฑs๏พ”S๏ฝง๏พ“ๆ˜ด๏พ‰1๏พ๏พ˜้งฒ๏พ‡z??Hw๏ฝง?Sๅ€‘)ๅผธI&๏ฝกX๏พ”ใ…?v๏พŽ่บ‘{]Nh๏ฝฅD?% ๏ฝง๏พŒ ?:ๆฃ—??B๏พ•๏พœๆปธ_?๏พ??;๏พ‰.?j*)Ol?\0x๏ฝฏ๏ฝขe๏พ‰#xๆ——็ฅ€6๏พŒ๏ฝฆๅƒ๏ฝป?๏ฝถ๏ฝฅ2๏ฝฝ๏พŽX๏ฝญlqๅป–๏พ‚๏ฝญ๏ฝช๏พ—่Ÿv;ไบ›โˆด๏พ›?\'ไฝฏH๏พ‡่ด1?่ธ๏พ‰้ฎด๏พ˜๏ฝœ?zJ ?w๏ฝฆFๅœi? ๏พŒ??ๆ•ฌ๏พ€๏ฝช๏พ‰9ๅฐZW๏ฝถ&_้€ฎ()r1kๅญณb 9V๏พ›n$?XZ26Z?S?3\r๏ฝป?๏ฝฅ?U??ๅ˜ด๏พ›mR็ฑ˜๏ฝกH#?\Z๏พ›๏ฝฎ7ๆกˆ|๏ฝพl@HF?9?r๏ฝซ9bKt๏พ†?๏ฝฆS71๏ฝถW/l7๏พœ๏ฝซ?๏ฝฆ9zLJ>L๏พ€*?> ็ฑŒ-๏พ‘?๏ฝบ๏ฝตVU? )??6J๏พ’(=jqe0๏พ„#?๏ฝฉ]๏ฝปS??+y}e$ๆƒ† 0๏ฝฉ ๏ฝนm?\0๏พ‰๏พ‚้€…?9๏ฝฅ$๏ฝฆ้‰ข๏ฝฎ๏พ•๏พ„๏พ€R๏ฝด๏พ‹๏ฝด๏พ”๏พ็ฃง?@0?ไฝŽ๏ฝฆb??TO๏พ€๏พŠy9$R?็ทœhU๏พƒ2??2่ˆชUb๏พŠ*l|z่ก’๏พ—?0?๏พˆyTTq?\0ใ‚‘?8s่‹—$f_๏ฝฏ*\Zl2 > |lH8่คž๏พ้ “42Yๆ— \rT?8ๅฏฆ๏ฝจ๏พ†๏พ๏ฝฆ*M0AWp๏พ–??\0๏พ‚?\0๏ฝญ?\ZR๏ฝฝ?๏ฝฅๅท›๏ฝฑD๏ฝฅiRX?\0๏ฝฒ๏พ€U9K/๏ฝฒ๏ฝช๏ฝด๏พ“๏ฝฃ๏ฝบๆจฝU=?y>{?D๏ฝข๏ฝฐ?&็ฟ\n๏พ??้Š“๏พa|๏ฝถ้ŽฎFjP?5๏ฝธ}ๆœ‰? =๏ฝต๏พ€gไบ‚?;๏พ†๏ฝฟ่މ|)?\0q๏พˆ?ๆผ ๏พK3W?#??๏ฝญ๏ฝฟi๏ฝฟ๏พ‰lๅฆฌ็ด˜๏ฝฉ?X๏ฝขx๏ฝพ?)P๏ฝป?^??ๆปฟ~๏พŽM่ฅ ๏พ‹s4w F-๏พ—?\'๏ฝก๏ฝญ>a?๏พ–??็ฑ–V4v๏ฝง?\0?u่ฒ/็‹ƒ๏ฝณ็ฆ„X๏พ*Z?P?\0+๏ฝทๅฑˆๆค?=๏พๅณฏx๏พ‚๏พŸb๏ฝฑK?-:๏ฝฒ๏ฝฏ๏พ™?\0e่–๏ฝผ๏พ†ๅ„„ๆก‘\'๏ฝจI๏ฝซๆฃ”??+๏ฝน/u\'?ๆ–‰ใƒ*J??k?0 ๏พ™s}๏พ๏พX๏พ„n๏ฝป?\n?5๏พ’b๏พu]-้‡€?+|๏ฝป!๏พœ/๏พ›? ?๏ฝซ?L๏ฝฒZ๏พ›๏ฝฌ?NhcSU?\0+l;๏พ—ๅฆฃ๏พ”.๏พ–?๏พ‰i ?๏พŒๅฝ‘?,7๏ฝฒ?/๏ฝจyj{ VG+?a?๏ฝบ?ๅป‚q๏ฝบ๏ฝจ็ธž2i้ทฝ๏พš๏ฝฅZ็ซ?~๏พe๏พ‰๏พ‰๏ฝค?E่ž1่ˆ’8๏พšH๏ฝผ?\0\n??้จ™/?.ๆ—…๏พ—h?๏ฝฝ?-\n0&1๏พˆCj?>?๏ฝฑ\r+LI๏พ๏ฝน๏ฝพ-?๏ฝฒ\n}๏ฝฏ๏พ™็‰€U๏ฝค?\0+?:๏พƒN้ƒตi#๏ฝด?$H?~#?~๏พŽ๏พŠ?PHb2\'??0๏พŠ๏พ›๏พ‰๏พš๏ฝฆๅฌถ%๏ฝฝ๏ฝณyvc?๏ฝดๆ•…1่ƒšE<่ฆ“s?&ั๏ฝป?๏ฝคๆšธ@?๏ฝท?ๆŠ—J?๏ฝก?FbI?\\[Z??ๅฃ—๏พmf?I%๏พˆ??ro๏พ™๏พ‰q?/>?\'๏พ‡SJ\nโ‰ช?$,e็ญŒp{{b๏ฝฏ ๏พŒ็„ถzw๏พ‰?\r(H๏ฝคT\Zๆขฑ?6&K9,w=N*๏พ€ใ‚คๅ‹‡QZ??*?#+1w๏ฝฎ4๏ฝชๅ„Ÿiๅ“ฆ?s๏พ‘W?3๏พ‘(?๏ฝชx๏พ”b๏ฝผ?\"$BUโ†’#๏ฝจ๏พ†๏พž^M})ๆฆฑ๏พŒ?7V=M2)h๏ฝข๏พ–็ฉ๏ฝฎ๏พ„็ฏท\n๏ฝฅ9??*0F\ZLๅน•k?=๏พ‡+่ฉ”้ฐป๏ฝฃ?ๆค?\0่†ๆถฏ+??\0YEK่“„/?่€๏พ†๏ฝฆ๏ฝนๅ’ค๏พ™Xๅคซ9C6๏พŠ+ๅ„•๏ฝฑ?๏พ…?๏พ”P>\"z็ซฅ\r๏พ–๏พ”๏พŠ?(๏ฝข?j1S๏ฝต0๏พ‚๏พŠ(?8f R6c๏พˆ?็ฏฉH?\0๏พ„?๏ฝญ่œ‚|๏ฝ?&้ฎ“jH๏ฝจ้ญ‚,{??๏ฝฎ+๏ฝง๏พŸ๏พœi๏ฝณ ๅซป็’ข๏ฝฟ๏พ๏พ…r็น•?\n\n๏พ”?4๏พ‰R๏ฝฆ/๏ฝฅ๏พ‡uj๏ฝท๏ฝฐ๏พˆๆŸด:1U\0ๆ‰+3}? ๏ฝง้ญŽ_๏ฝธ?6้จŽๆฝ๏ฝท?๏พƒME-?h๏ฝฎ\"u ?#GR\n?~K๏พ‡?S?ใ‚†ๆท™?Y๏ฝท๏พ”่‡‘J๏พ„T๏พ#\Z\n๏ฝพ็ถ‰่Žจ๏ฝนไนฑ&๏ผซ๏พŠ]๏ฝชi๏พ‹๏ฝขF๏ฝฆ?ๅฐญ?๏ฝชFๅญ‘aO๏ฝด๏พŸ๏ฝฐๅฑ‘Y๏ฝน๏ฝธ{?\ZW$๏ฝณ\Zๆจฝs๏ฝก?l!kk8\0โˆด;T๏พ—?k9๏ฝญi?<้‹’9 ??๏ฝฅๅ‘๏ฝฎ!??๏พ‡๏ฝข่ˆž็ฉข๏พˆ่™Ÿ|\'t๏ฝผi?p๏ฝณ๏ฝธVๅฏฟ็ต…?\0๏ฝฎ๏พŒ\0q?r๏พ˜๏พ?\Z9?๏ฝฎp?๏พ’mV?4?F? ๏ฝตF?ๆ@?๏พˆ๏ฝถๆข—๏พ“ๆฟ ๏ฝฉ๏ฝฎ๏พ”?\0W?dS6๏พ‰ๆฆด+(N$\r๏ฝฉ๏พ“ X๏พ—?๏ฝฟ๏ฝพ))~!T?q*๏ฝต7๏ฝฅ4๏พ‰$๏ฝฎ?_3j่จŽ?BK\Z\n ่ Ž๏ฝฑf?\n5๏ฝฒ? ZB\0O\\U๏ฝขf?๏พƒ^๏ฝพ8 K๏ฝฆ๏พ‡๏พ›๏ฝฎ=๏พW้ปฏ?2J๏พ”?!^)?ไฝณๆขฏ]่žฝ๏พŸe^๏ฝฟ?c->.?;x?\r=๏พƒW๏ฝฏ_๏ฝธb\r๏ฝฉ.iYS่ƒƒ๏ฝฟ?๏พ†?๏ฝจ่ช•V?\"๏ฝปไพ๏ฝบ?\nL?>#?6๏พ€rL? jha็ฃจ๏พœ๏พ€๏ฝฌ?W็‡ฌยฐ ๏ฝฃ๏ฝง|H|?๏พ•?๏ฝค๏พ‚่ฒป็ช˜ ?\"\"?u๏พŸ๏ฝฎ6k?v๏พœๆคˆY$็€\rVy nr๏พˆ็›–e๏ฝฎS?g๏ฝน?๏ฝถ๏พ†?๏ฝฐ9je๏พ†?\0๏ฝฐa?ๅฝฟ9๏ฝฒ๏ฝฒIvXc๏พ‚๏พ—[Jf๏ฝธ้บ็“ฉ\\iๆ†‚่ฎŽaๆฃบ?7๏พ‹๏พ?\n๏ฝบๅƒ–๏พ“186๏พ‹L{๏ฝบ14S?i@?V\"#๏พ“ n๏ฝฌ็ŠขpๆŒฏ๏พ›๏พŸ๏ฝถ [EaS?Z๏พ’Bcc๏พu้ซŸ$O๏ฝฃใ‰๏พ€็ Œๆ•ต๏ฝฆ|iC1้ฐพ?๏พŠ?U๏พ„l๏ฝฌ๏ฝง๏ฝฝ]๏ฝชXๅขป?๏ฝด็ฆพ๏ฝดe\n.n????\0?{๏ฝนV?? ?๏ฝถ๏พ“?่’„\'?๏พ๏พ˜5,๏พ’6?ๆข๏พ™m?ใ‚ข???[๏ฝฃE?=๏ฝฐ?$๏ฝถ๏พ’\"๏พ˜,j:ๆจ’้ทธ?6_Q่“ฟ?๏ฝป๏พ”e๏ฝปb?ๆงฒ$๏พ‡??๏พ๏พš๏ฝถ?6??\0๏ฝฝPx็พจ๏ฝฟ??่ฎ€๏พ‚i*?\n็†จ??Uo??\0[็™Œ;็”‘๏ฝ?*๏พƒ?\n?B?2rO??9w๏ฝขฮถ,?O๏พŠ?WG?1่ผƒ ๏พ—??ๆฒ‚?\'?,ๅฑ :็Žฒ[tไธผ&a?๏พœW?๏พ‰p??ๆฅก๏ฝฟ๏ฝพA่†ฐ้€?๏ฝณๆธค?_k:D๏ผฎ%่กข[?1๏พŒLr.zoC_๏พŠ?&?eR$ #?n?ๅปฌ่‹žIB๏พˆ๏ฝฆไฟ?้œ€? ๏พ๏ฝฌ?๏ฝฉ๏พ˜W๏ฝท?๏พ†ๅŠตRๅŒ…ๅทป๏ฝฌ้žณ?*๏พ‚๏ฝปP?๏ฝฒGR?n0(x๏พ€(็ซš+? ๏พ’K?๏พšNๆ€้‘ทUg๏ฝท้Šœ๏ฝฒ๏พ๏ฝป ๏ฝฏ?(๏ฝฏ{\0๏พž#๏พ…z?๏พ„??=E+๏พ—?O(๏พ‚@๏พœๅฃฑ๏พ”|๏ฝช๏ฝซ?=๏พ‡่ฉe#็ฐ‡๏ฝญ๏ฝพ่ฑผ?N\r ?็Ÿฏ๏พ„\'๏ฝณI(๏พ‰B|0๏พ™W่‹ฆๆ›„ry๏พ›๏ฝบๅฎ›?๏ฝต?G#?๏ฝถ่Ÿ๏ฝธ๏ฝข๏ฝฃWใƒ“?9๏พn๏ฝดS๏พˆ2?<:??3้žฃ?\n๏พŒ๏พŸ๏ฝฟO๏ฝป&2E?y่ฌ–?-J?๏พ•xๆงฝๅฝนๆž‰\n?i๏พ“B๏ฝก$๏ฝฃ.๏พ‹JV๏ฝฃ๏พ้›œW๏ฝ“D6๏พž๏ฝฃo๏พ•?{๏พ—??๏พ[ๅฐe??๏พ˜aT๏ฝถ๏พ’๏พ†~$็‹น?2s?ไฝต101?B?๏พ—๏พ€๏ฝฅ^๏พŠ๏ฝขq \0???d?Cๆ–ฝ??[๏ฝฑ?๏พo๏ฝงhnA๏ฝฌ๏ฝฉ๏ฝผ่‰็ˆ›๏พ…f๏พ’่Ÿ ็ฐซ) N?๏ฝท๏พš๏พ่ž: Q%$V๏ฝฃbG?๏ฝต?-1I??T๏ฝฒ็ฉซ|๏ฝป{?-B?!\rV๏ฝฝA?j็š€๏พ˜๏พ‡;่”‘\'?&๏ฝฆ๏ฝง๏ฝตk??๏ฝบc?~๏พŽ:?b๏พ„?mzY#็—’ rW?๏พ‘?๏ฝฒ+}ๆ๏พœMc๏พH\r?e็ฉ€?!(๏ฝง๏พ‚๏พœ๏ฝธ๏พ“??OwN~๏ฝซ??0๏พ‡nๆฆ‚#ๅ„ป~<ๆจŸ\Z?:?2?\ZoU?\0?ๅŠผkf1H#)%h[ๆ’ญ?:? ]=wG๏พ”&?-๏พƒ๏ฝฒ๏ฝน๏ฝฉ*\n~๏พ’็จฝ?wQ๏พŠ๏ฝฑ#๏พ†(xr๏ฝก?\\[?\\ๆ•ฌๅ„ป6!-?I?P?n๏พ‰๏ฝถ??+]vๅ บX๏ฝขr?\'?W๏พŒYFQ7M?๏ฝŽ๏พ–๏ฝฐ่›‡?ๅ‰„\n?๏ฝฟe๏ฝธ๏ฝซ/๏พ™๏พ‚๏พŸ+K?=๏ฝน๏พl๏พ†๏พœ?\n@๏ฝฏ?3r๏พƒ?,e7\"$๏ฝธๅ‰ฒ? ?\0Y]G,3uk?๏พ’N{UN??!่ช ๏ฝฉ*ๆฒ–๏พšj๏พ‡๏พ’๏ฝช??ๆ•ˆ๏พƒ\n?PF๏พƒ๏ฝธ๏พˆ~ๅฉ?,๏ฝงwSBw๏ฝตo?ๆšข9๏พ€V๏ฝฝ๏ฝฉ่‡ช??0? ๏ฝต๏พ–f๏ฝณCK่…†$?\'? ๏ฝฐz%๏ฝซ;\'ๅ‚˜e?7๏ฝฏ??ๅ•ฃ.^y๏พˆ??/๏พš๏พ…็œ„๏ฝพ๏ฝน\"๏พž?4่“‰?F?\0๏พŠไปฃot๏พ;N2๏ฝฅ๏พ•๏พๆœด?๏ฝง็‰’๏ฝข๏พˆ๏ฝช่ƒฏ???H๏ฝค?F?๏ฝจ๏ฝญd??็ƒ‹7\\e๏พ‚=๏ฝน?@?cQ?๏ฝฒb1\\d:?๏พ๏ฝบb๏ฝซ^G:PVๅซฉ๏ฝฅ๏ฝตhBQใƒ“?=?๏พ–๏พ†z?+๏ฝต=?\0็‰พt?T?โˆ‡๏ฝคๆ„??๏ฝณ?็ฎ{ๅ‰ฟ:?๏พŒiS๏พ“๏พ๏พŽใฌ??๏ฝฃๅนด\r?ๅ…’ๅš๏พ“V???8๏ฝซJ?_่ถ?็‘ฏ๏พ‘๏ฝดh?\0z๏พš่Šฅs๏ฝฆ??yBB๏ฝฝ๏ฝพ๏ฝฑq=้›ข๏ฝจ๏พœ๏พ–๏พๆฌง?๏พ€??2??๏พ–๏พˆ&๏ฝบ?-?Z๏ฝซ๏ฝบQ_๏ฝณ?็พฉ๏ฝซ{8๏ฝต8่ญŸJ?;kX๏พ?\ZF?๏พ˜๏ฝซ๏ฝฌๆ„พ๏พ˜๏ฝง,๏พš/',0.7124939,'sl',7,0,'1922-12-07 22:15:04.0'), +(2012,'k','',NULL,'lstxvxoo',2,3,'1992-07-20 10:19:25.0'), +(2006,'txvxoobx','{ }\", \"UTAH\", \"2014\", \"37\", null, \"-\", \"1\", null, \"3\", null, \"27\", null, \"68\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-111.5871285339997 39.36070082200047)\", null, null, \"UTAH\" ]\n, [ \"row-cy2h-v4pv_yc2a\", \"00000000-0000-0000-29C8-82ED26F05724\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"SOUTH CAROLINA\", \"2014\", \"37\", null, \"-\", \"2\", null, \"6\", null, \"55\", null, \"61\", null, null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"7\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-81.04536765699964 33.99882214300044)\", null, null, \"SOUTH CAROLINA\" ]\n, [ \"row-wyg5_yc5s.2t33\", \"00000000-0000-0000-0009-A1EAD77B5986\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ALASKA\", \"2014\", \"37\", null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"4\", null, null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-147.72205669099972 64.84507631500048)\", null, null, \"ALASKA\" ]\n, [ \"row-6sii~ebrj~btdz\", \"00000000-0000-0000-6A81-EBD29358C16E\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MAINE\", \"2014\", \"37\", null, \"-\", \"1\", null, \"4\", null, \"35\", null, \"23\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-68.98502952999962 45.2542257390005)\", null, null, \"MAINE\" ]\n, [ \"row-rvmv_hqb8-tf2k\", \"00000000-0000-0000-EFA0-7FDE69030921\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"OKLAHOMA\", \"2014\", \"37\", \"1\", null, \"1\", null, \"7\", null, \"55\", null, \"47\", null, null, \"-\", \"0\", null, \"1\", null, null, \"-\", \"3\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-97.52106845499969 35.472031425000466)\", null, null, \"OKLAHOMA\" ]\n, [ \"row-qurf_mxm6.4xmv\", \"00000000-0000-0000-F4FD-DAD0CD1CF605\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"INDIANA\", \"2014\", \"37\", null, \"-\", \"2\", null, \"7\", null, \"79\", null, \"98\", null, null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"5\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-86.14995579899966 39.76691072200049)\", null, null, \"INDIANA\" ]\n, [ \"row-7e9w.a5ca.gbgy\", \"00000000-0000-0000-B852-68B67CD55DEF\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"DELAWARE\", \"2014\", \"37\", null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"11\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"2\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-75.57773943699965 39.00883059000046)\", null, null, \"DELAWARE\" ]\n, [ \"row-93f3~ptpp-jvyy\", \"00000000-0000-0000-93F5-6033818C035C\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ARKANSAS\", \"2014\", \"37\", \"3\", null, \"1\", null, \"6\", null, \"25\", null, \"43\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-92.27448794899965 34.74865329300047)\", null, null, \"ARKANSAS\" ]\n, [ \"row-7pq8.u2t6-yp2b\", \"00000000-0000-0000-E13B-08276C137DC3\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"CALIFORNIA\", \"2014\", \"37\", \"7\", null, \"6\", null, \"15\", null, \"231\", null, \"204\", null, null, \"-\", \"1\", null, \"7\", null, \"38\", null, \"70\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-120.99999889499969 37.63864203100047)\", null, null, \"CALIFORNIA\" ]\n, [ \"row-8nav_uj4s~c9ps\", \"00000000-0000-0000-05EF-D247DF52986E\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"OREGON\", \"2014\", \"37\", null, \"-\", \"2\", null, \"8\", null, \"77\", null, \"218\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-120.15502977999972 44.56745218600048)\", null, null, \"OREGON\" ]\n, [ \"row-w7pd-tam2~rvge\", \"00000000-0000-0000-DA1A-364967240EA5\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ALABAMA\", \"2014\", \"37\", \"2\", null, \"2\", null, \"8\", null, \"82\", null, \"102\", null, null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"5\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-86.63185803899967 32.84057034900047)\", null, null, \"ALABAMA\" ]\n, [ \"row-bfx3~rdqm~8r7t\", \"00000000-0000-0000-D6AD-76C43033D406\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEW JERSEY\", \"2014\", \"37\", null, \"-\", \"0\", null, \"5\", null, \"13\", null, \"52\", null, null, \"-\", \"0\", null, \"5\", null, \"26\", null, null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-74.27368565099965 40.13057159500045)\", null, null, \"NEW JERSEY\" ]\n, [ \"row-ihca-r6sm_j485\", \"00000000-0000-0000-8835-76DE92BD0A04\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MASSACHUSETTS\", \"2014\", \"37\", null, \"-\", \"2\", null, \"5\", null, \"75\", null, \"98\", null, null, \"-\", \"0\", null, \"1\", null, \"7\", null, null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-72.08268985899963 42.27687014100047)\", null, null, \"MASSACHUSETTS\" ]\n, [ \"row-q8yq-pfae.5iyh\", \"00000000-0000-0000-2104-5A07B1D13849\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"IOWA\", \"2014\", \"37\", null, \"-\", \"5\", null, \"61\", null, \"180\", null, \"1306\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"2\", null, \"POINT (-93.81648936699969 42.469401477000474)\", null, null, \"IOWA\" ]\n, [ \"row-yzs9~3ssn.gb6z\", \"00000000-0000-0000-D8B2-772D6478CB4A\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEW YORK\", \"2014\", \"37\", \"12\", null, \"4\", null, \"14\", null, \"172\", null, \"162\", null, null, \"-\", \"0\", null, \"4\", null, \"18\", null, \"38\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, \"POINT (-75.54396639699968 42.82700178100049)\", null, null, \"NEW YORK\" ]\n, [ \"row-5amt-e54z~7rhu\", \"00000000-0000-0000-1452-DB727C714C5F\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEW HAMPSHIRE\", \"2014\", \"37\", null, \"-\", \"0\", null, \"3\", null, \"20\", null, \"32\", null, null, \"-\", \"0\", null, \"1\", null, null, \"-\", \"3\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-71.50035726399966 43.65595081000049)\", null, null, \"NEW HAMPSHIRE\" ]\n, [ \"row-ejuk_u23f-gmac\", \"00000000-0000-0000-D585-11F9AE6034FF\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"OHIO\", \"2014\", \"37\", \"10\", null, \"6\", null, \"15\", null, \"232\", null, \"256\", null, null, \"-\", \"0\", null, \"1\", null, \"7\", null, \"6\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-82.40425685299965 40.06021184000048)\", null, null, \"OHIO\" ]\n, [ \"row-kdkx_unx4_2827\", \"00000000-0000-0000-A7FB-3FD62AD160C7\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MONTANA\", \"2014\", \"37\", \"2\", null, \"1\", null, \"10\", null, \"48\", null, \"95\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"2\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-109.42441687999968 47.06652759400049)\", null, null, \"MONTANA\" ]\n, [ \"row-ejbe.eiif_ajbq\", \"00000000-0000-0000-7720-7C64C4EDD0FF\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MISSISSIPPI\", \"2014\", \"37\", null, \"-\", \"1\", null, \"4\", null, \"34\", null, \"38\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-89.53802764499966 32.745512774000474)\", null, null, \"MISSISSIPPI\" ]\n, [ \"row-amps~asgf.znet\", \"00000000-0000-0000-AF78-26AB67F70491\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"GEORGIA\", \"2014\", \"37\", \"11\", null, \"5\", null, \"16\", null, \"180\", null, \"194\", null, null, \"-\", \"0\", null, \"1\", null, \"3\", null, \"8\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-83.62757601199968 32.83968158500045)\", null, null, \"GEORGIA\" ]\n, [ \"row-cctq_ndwy_fy4u\", \"00000000-0000-0000-102B-15204C828ECE\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"CONNECTICUT\", \"2014\", \"37\", null, \"-\", \"1\", null, \"4\", null, \"30\", null, \"31\", null, null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"12\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-72.64983753699966 41.56266101800048)\", null, null, \"CONNECTICUT\" ]\n, [ \"row-i553-kagm.cvdx\", \"00000000-0000-0000-053F-F5FA999759C2\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"SOUTH DAKOTA\", \"2014\", \"37\", \"1\", null, \"3\", null, \"9\", null, \"105\", null, \"115\", null, null, \"-\", \"0\", null, \"1\", null, null, \"-\", \"2\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-100.37352811899967 44.35313049600046)\", null, null, \"SOUTH DAKOTA\" ]\n, [ \"row-ytu3~kmi6_4tk3\", \"00000000-0000-0000-E92D-E3A3AD33FA66\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"FLORgA\", \"2014\", \"37\", \"106\", null, \"10\", null, \"128\", null, \"1071\", null, \"255\", null, null, \"-\", \"1\", null, \"5\", null, \"21\", null, \"117\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-81.92895558499964 28.93204444200046)\", null, null, \"FLORgA\" ]\n, [ \"row-4s96~2vqm~drez\", \"00000000-0000-0000-F19B-061643992EAA\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NORTH CAROLINA\", \"2014\", \"37\", null, \"-\", \"0\", null, \"28\", null, \"115\", null, \"102\", null, null, \"-\", \"0\", null, \"2\", null, \"5\", null, \"13\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-79.15924924699965 35.46622096200048)\", null, null, \"NORTH CAROLINA\" ]\n, [ \"row-ikuk-dgfa.8jyj\", \"00000000-0000-0000-9E8F-69F43661D18F\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NORTH DAKOTA\", \"2014\", \"37\", null, \"-\", \"1\", null, \"7\", null, \"40\", null, \"55\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-100.11842599699969 47.47531892900048)\", null, null, \"NORTH DAKOTA\" ]\n, [ \"row-uabq.jkdx.nhvp\", \"00000000-0000-0000-D434-0442CBD25725\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"PUERTO RICO\", \"2014\", \"37\", null, \"N\", \"0\", null, \"0\", null, null, \"N\", null, \"N\", null, \"-\", \"13\", null, \"267\", null, \"394\", null, \"7593\", null, null, \"-\", \"0\", null, \"7\", null, \"2\", null, \"122\", null, \"POINT (-66.49988980099965 18.24828934900046)\", null, null, \"PUERTO RICO\" ]\n, [ \"row-i6gf-qp6w-e2c2\", \"00000000-0000-0000-26F7-EDD14CD14586\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MARYLAND\", \"2014\", \"37\", \"3\", null, \"1\", null, \"5\", null, \"50\", null, \"41\", null, null, \"-\", \"0\", null, \"2\", null, \"6\", null, \"6\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-76.60925970899967 39.29058224000045)\", null, null, \"MARYLAND\" ]\n, [ \"row-2nzg-gz5z_pv67\", \"00000000-0000-0000-8578-720E3DEB8CA6\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"TEXAS\", \"2014\", \"37\", \"8\", null, \"7\", null, \"37\", null, \"199\", null, \"209\", null, null, \"-\", \"0\", null, \"9\", null, \"12\", null, \"41\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-99.4267664729997 31.827240712000446)\", null, null, \"TEXAS\" ]\n, [ \"row-avp9_hp2a-wmxy\", \"00000000-0000-0000-8DDB-7DDD49FC59B2\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"TENNESSEE\", \"2014\", \"37\", null, \"-\", \"2\", null, \"5\", null, \"65\", null, \"54\", null, null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"10\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-85.77448642199965 35.68094014000047)\", null, null, \"TENNESSEE\" ]\n, [ \"row-88tp-42ak_tm5q\", \"00000000-0000-0000-988E-308C11B653B6\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"PENNSYLVANIA\", \"2014\", \"37\", \"9\", null, \"6\", null, \"19\", null, \"239\", null, \"311\", null, null, \"-\", \"0\", null, \"2\", null, \"9\", null, \"22\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-77.86069775999965 40.79373260300048)\", null, null, \"PENNSYLVANIA\" ]\n, [ \"row-9e8q.28f8-3h2t\", \"00000000-0000-0000-6CE4-C1C9E8B95B4A\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"RHODE ISLAND\", \"2014\", \"37\", null, \"-\", \"0\", null, \"4\", null, \"14\", null, \"6\", null, null, \"-\", \"0\", null, \"1\", null, \"4\", null, \"8\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-71.52246918099962 41.708284362000484)\", null, null, \"RHODE ISLAND\" ]\n, [ \"row-fftv.vjyz.z698\", \"00000000-0000-0000-5EDB-962AAA8CF84F\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"gAHO\", \"2014\", \"37\", \"14\", null, \"1\", null, \"22\", null, \"72\", null, \"101\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-114.3637261449997 43.68263160000049)\", null, null, \"gAHO\" ]\n, [ \"row-ztqh-ya8x.ym8m\", \"00000000-0000-0000-8F2D-33DAD0D6EE5D\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MISSOURI\", \"2014\", \"37\", null, \"-\", \"3\", null, \"13\", null, \"104\", null, \"146\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"3\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-92.56629737199967 38.63579079900046)\", null, null, \"MISSOURI\" ]\n, [ \"row-ikvv~557y.vxad\", \"00000000-0000-0000-5C83-384A358420C1\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEBRASKA\", \"2014\", \"37\", null, \"-\", \"2\", null, \"7\", null, \"56\", null, \"104\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-99.36571864599966 41.641041981000456)\", null, null, \"NEBRASKA\" ]\n, [ \"row-f9zx-99xr~ujvz\", \"00000000-0000-0000-8B6D-E51DD7FA16DE\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"COLORADO\", \"2014\", \"37\", \"1\", null, \"1\", null, \"5\", null, \"48\", null, \"73\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-106.13360888799969 38.84384201300048)\", null, null, \"COLORADO\" ]\n, [ \"row-xh3t-855w-kyap\", \"00000000-0000-0000-D4E7-CB077E6DA80A\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"WYOMING\", \"2014\", \"37\", null, \"-\", \"0\", null, \"22\", null, \"21\", null, \"105\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-108.10982744299969 43.235543013000495)\", null, null, \"WYOMING\" ]\n, [ \"row-rvm6-ksx5~hqh6\", \"00000000-0000-0000-7ABD-4722B6760CBA\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ARIZONA\", \"2014\", \"37\", null, \"-\", \"1\", null, \"5\", null, \"35\", null, \"29\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-111.76380949799972 34.865970167000455)\", null, null, \"ARIZONA\" ]\n, [ \"row-6c2e.vkwy_2u5v\", \"00000000-0000-0000-7C6C-69E27D3BB00A\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"HAWAII\", \"2014\", \"37\", null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"1\", null, null, \"-\", \"0\", null, \"2\", null, \"6\", null, \"9\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-157.85774691599974 21.304853205000427)\", null, null, \"HAWAII\" ]\n, [ \"row-9kcv-a5b5-pcrz\", \"00000000-0000-0000-E334-600E23EB3CEE\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ILLINOIS\", \"2014\", \"37\", null, \"-\", \"3\", null, \"11\", null, \"105\", null, \"197\", null, null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"20\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-88.99770813999965 40.48501433000047)\", null, null, \"ILLINOIS\" ]\n, [ \"row-seje.ikp2~aqd2\", \"00000000-0000-0000-30E4-4AFAF7F31261\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"GUAM\", \"2014\", \"37\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (144.73149801400064 13.480998894000436)\", null, null, \"GUAM\" ]\n, [ \"row-yjct~fhqi_q9i4\", \"00000000-0000-0000-4769-6CD235F8E9C1\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEW YORK CITY\", \"2014\", \"37\", \"7\", null, \"2\", null, \"6\", null, \"56\", null, \"52\", null, null, \"-\", \"1\", null, \"5\", null, \"18\", null, \"95\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, \"POINT (-74.00596858999967 40.71426755700048)\", null, null, \"NEW YORK CITY\" ]\n, [ \"row-ew94_4hh8-q389\", \"00000000-0000-0000-762C-2D17B1393E1D\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEW MEXICO\", \"2014\", \"37\", null, \"-\", \"1\", null, \"5\", null, \"57\", null, \"32\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-106.24057768899968 34.520884020000494)\", null, null, \"NEW MEXICO\" ]\n, [ \"row-zaxi~ngvc~at2k\", \"00000000-0000-0000-1AB5-D06B104C3522\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"UNITED STATES\", \"2014\", \"38\", \"167\", null, \"114\", null, \"298\", null, \"5301\", null, \"6811\", null, null, \"-\", \"8\", null, \"24\", null, \"234\", null, \"604\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"6\", null, null, null, null, null ]\n, [ \"row-qfn8_3ygz.pj9x\", \"00000000-0000-0000-945B-B74777621CEF\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEW ENGLAND\", \"2014\", \"38\", \"2\", null, \"5\", null, \"11\", null, \"198\", null, \"219\", null, null, \"-\", \"0\", null, \"3\", null, \"16\", null, \"26\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, null, null, null ]\n, [ \"row-urh2~wub5_3jvh\", \"00000000-0000-0000-4BDB-A7570CE0C9C4\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"Mg. ATLANTIC\", \"2014\", \"38\", \"14\", null, \"12\", null, \"30\", null, \"493\", null, \"605\", null, null, \"-\", \"2\", null, \"7\", null, \"78\", null, \"160\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"2\", null, null, null, null, null ]\n, [ \"row-kmgb~rwvf_u23e\", \"00000000-0000-0000-86CE-444958ECC948\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"E.N. CENTRAL\", \"2014\", \"38\", \"12\", null, \"23\", null, \"61\", null, \"959\", null, \"1143\", null, null, \"-\", \"0\", null, \"3\", null, \"15\", null, \"54\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, null, null, null ]\n, [ \"row-x2uc_2e7d.n3gt\", \"00000000-0000-0000-EF8D-55C57BA06B11\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"W.N. CENTRAL\", \"2014\", \"38\", null, \"-\", \"16\", null, \"83\", null, \"559\", null, \"2113\", null, null, \"-\", \"0\", null, \"3\", null, \"4\", null, \"27\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"3\", null, null, null, null, null ]\n, [ \"row-u44i-mzcp.f5p3\", \"00000000-0000-0000-1426-0625A24B6BC1\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"S. ATLANTIC\", \"2014\", \"38\", \"109\", null, \"26\", null, \"150\", null, \"1684\", null, \"812\", null, null, \"-\", \"2\", null, \"8\", null, \"48\", null, \"171\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, null, null, null, null ]\n, [ \"row-jqac.rny2_x728\", \"00000000-0000-0000-FCC1-76EABBE2EDED\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"DIST. OF COL.\", \"2014\", \"38\", null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"10\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, null, null, \"DIST. OF COL.\" ]\n, [ \"row-kx75_2ixn~qnii\", \"00000000-0000-0000-B1C1-85CDF1276A77\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"E.S. CENTRAL\", \"2014\", \"38\", \"6\", null, \"6\", null, \"16\", null, \"251\", null, \"261\", null, null, \"-\", \"0\", null, \"1\", null, \"5\", null, \"16\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, null, null, null ]\n, [ \"row-jgdv_tccd~6x47\", \"00000000-0000-0000-07F9-FBC344047579\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"W.S. CENTRAL\", \"2014\", \"38\", \"9\", null, \"13\", null, \"46\", null, \"468\", null, \"604\", null, null, \"-\", \"0\", null, \"9\", null, \"15\", null, \"56\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, null, null, null ]\n, [ \"row-254f~2nj7.ax4n\", \"00000000-0000-0000-6C2F-D42A998C981A\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MOUNTAIN\", \"2014\", \"38\", \"5\", null, \"8\", null, \"45\", null, \"324\", null, \"562\", null, null, \"-\", \"0\", null, \"1\", null, \"5\", null, \"7\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, null, null, null ]\n, [ \"row-hf44.x4z6~mi8n\", \"00000000-0000-0000-7913-F138F45C26D8\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"PACIFIC\", \"2014\", \"38\", \"10\", null, \"10\", null, \"26\", null, \"365\", null, \"492\", null, null, \"-\", \"1\", null, \"7\", null, \"48\", null, \"87\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, null, null, null ]\n, [ \"row-uacq-7hzb_whw4\", \"00000000-0000-0000-D53B-23B1F20FF628\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"AMER. SAMOA\", \"2014\", \"38\", null, \"N\", null, \"-\", null, \"-\", null, \"N\", null, \"N\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, null, null, \"AMER. SAMOA\" ]\n, [ \"row-fjce-gry8-3ukk\", \"00000000-0000-0000-554B-C752E6F1F563\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"C.N.M.I.\", \"2014\", \"38\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, \"-\", null, null, null, \"C.N.M.I.\" ]\n, [ \"row-i56c.zbav_dbna\", \"00000000-0000-0000-5333-371D40E86355\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"VIRGIN ISL.\", \"2014\", \"38\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"5\", null, \"1\", null, \"148\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"5\", null, null, null, null, \"VIRGIN ISL.\" ]\n, [ \"row-fqe4_bki4_5nim\", \"00000000-0000-0000-E21F-C7D790897138\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"GUAM\", \"2014\", \"38\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (144.73149801400064 13.480998894000436)\", null, null, \"GUAM\" ]\n, [ \"row-kypq.swsq.d83b\", \"00000000-0000-0000-432F-9CABD36E8ACE\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"UTAH\", \"2014\", \"38\", null, \"-\", \"1\", null, \"3\", null, \"27\", null, \"71\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-111.5871285339997 39.36070082200047)\", null, null, \"UTAH\" ]\n, [ \"row-qtdk.993m-wj3h\", \"00000000-0000-0000-9D9C-B8C56C4CD894\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"OKLAHOMA\", \"2014\", \"38\", \"2\", null, \"1\", null, \"7\", null, \"57\", null, \"48\", null, null, \"-\", \"0\", null, \"1\", null, null, \"-\", \"4\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-97.52106845499969 35.472031425000466)\", null, null, \"OKLAHOMA\" ]\n, [ \"row-buuh.beg9_thkn\", \"00000000-0000-0000-4588-5CC6AFA5566C\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"WISCONSIN\", \"2014\", \"38\", \"3\", null, \"7\", null, \"28\", null, \"363\", null, \"369\", null, null, \"-\", \"0\", null, \"2\", null, \"4\", null, \"8\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-89.81636715299965 44.393191877000504)\", null, null, \"WISCONSIN\" ]\n, [ \"row-8e7g.jisk.6pp5\", \"00000000-0000-0000-C392-61AB29B847BA\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"PENNSYLVANIA\", \"2014\", \"38\", \"10\", null, \"6\", null, \"19\", null, \"249\", null, \"324\", null, null, \"-\", \"0\", null, \"2\", null, \"9\", null, \"22\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-77.86069775999965 40.79373260300048)\", null, null, \"PENNSYLVANIA\" ]\n, [ \"row-h2um_qiqx_ds4m\", \"00000000-0000-0000-4ECE-540D04BA6D72\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"OREGON\", \"2014\", \"38\", null, \"-\", \"2\", null, \"8\", null, \"78\", null, \"224\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-120.15502977999972 44.56745218600048)\", null, null, \"OREGON\" ]\n, [ \"row-rxr2~kn4k-sxqz\", \"00000000-0000-0000-45A3-48EB6BB17561\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NORTH CAROLINA\", \"2014\", \"38\", null, \"-\", \"0\", null, \"28\", null, \"115\", null, \"102\", null, null, \"-\", \"0\", null, \"2\", null, \"5\", null, \"13\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-79.15924924699965 35.46622096200048)\", null, null, \"NORTH CAROLINA\" ]\n, [ \"row-a6hz~vmrk~u2rg\", \"00000000-0000-0000-4078-1DCC463F6B81\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"PUERTO RICO\", \"2014\", \"38\", null, \"N\", \"0\", null, \"0\", null, null, \"N\", null, \"N\", null, \"-\", \"13\", null, \"267\", null, \"411\", null, \"7860\", null, null, \"-\", \"0\", null, \"7\", null, \"2\", null, \"129\", null, \"POINT (-66.49988980099965 18.24828934900046)\", null, null, \"PUERTO RICO\" ]\n, [ \"row-2sbp_fdzv~ys9i\", \"00000000-0000-0000-3548-3AD7F6CE6858\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"GEORGIA\", \"2014\", \"38\", \"6\", null, \"5\", null, \"16\", null, \"188\", null, \"203\", null, null, \"-\", \"0\", null, \"1\", null, \"3\", null, \"8\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-83.62757601199968 32.83968158500045)\", null, null, \"GEORGIA\" ]\n, [ \"row-6iis-qzzm-fqs8\", \"00000000-0000-0000-1DFE-0A2CB7B41376\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"LOUISIANA\", \"2014\", \"38\", null, \"-\", \"4\", null, \"16\", null, \"175\", null, \"281\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"5\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-92.44567554599968 31.312664106000454)\", null, null, \"LOUISIANA\" ]\n, [ \"row-gk9g.uvjw_uem6\", \"00000000-0000-0000-E995-8703CD19E5E0\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MONTANA\", \"2014\", \"38\", \"1\", null, \"1\", null, \"8\", null, \"49\", null, \"103\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"2\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-109.42441687999968 47.06652759400049)\", null, null, \"MONTANA\" ]\n, [ \"row-8hxi-a8dx.zri9\", \"00000000-0000-0000-6DAD-1DE365931BC1\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"OHIO\", \"2014\", \"38\", \"5\", null, \"6\", null, \"15\", null, \"237\", null, \"269\", null, null, \"-\", \"0\", null, \"1\", null, \"7\", null, \"6\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-82.40425685299965 40.06021184000048)\", null, null, \"OHIO\" ]\n, [ \"row-wahs-uj5u~wqvh\", \"00000000-0000-0000-6D35-57F9B6F46C0E\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"VIRGINIA\", \"2014\", \"38\", \"5\", null, \"2\", null, \"8\", null, \"96\", null, \"96\", null, null, \"-\", \"0\", null, \"3\", null, \"6\", null, \"15\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, \"POINT (-78.45788924199968 37.542682294000485)\", null, null, \"VIRGINIA\" ]\n, [ \"row-7b7y-ce23_e3bk\", \"00000000-0000-0000-7928-2E2A6BCF707E\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"TENNESSEE\", \"2014\", \"38\", \"1\", null, \"2\", null, \"6\", null, \"69\", null, \"58\", null, null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"10\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-85.77448642199965 35.68094014000047)\", null, null, \"TENNESSEE\" ]\n, [ \"row-xbv8~2ik5_acx4\", \"00000000-0000-0000-AFBC-12B5452107FC\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"SOUTH DAKOTA\", \"2014\", \"38\", null, \"-\", \"2\", null, \"9\", null, \"106\", null, \"119\", null, null, \"-\", \"0\", null, \"1\", null, null, \"-\", \"2\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-100.37352811899967 44.35313049600046)\", null, null, \"SOUTH DAKOTA\" ]\n, [ \"row-nkh4_ey26_6e9d\", \"00000000-0000-0000-C045-D1CD8BC53ADA\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEBRASKA\", \"2014\", \"38\", null, \"-\", \"2\", null, \"7\", null, \"56\", null, \"110\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-99.36571864599966 41.641041981000456)\", null, null, \"NEBRASKA\" ]\n, [ \"row-ysqp.tcpd.j3kk\", \"00000000-0000-0000-18DD-D656386E387A\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"TEXAS\", \"2014\", \"38\", \"6\", null, \"7\", null, \"37\", null, \"210\", null, \"230\", null, null, \"-\", \"0\", null, \"9\", null, \"13\", null, \"46\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-99.4267664729997 31.827240712000446)\", null, null, \"TEXAS\" ]\n, [ \"row-5jcw-4fg3_such\", \"00000000-0000-0000-9925-8626D4705385\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"IOWA\", \"2014\", \"38\", null, \"-\", \"5\", null, \"47\", null, \"191\", null, \"1353\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"2\", null, \"POINT (-93.81648936699969 42.469401477000474)\", null, null, \"IOWA\" ]\n, [ \"row-h5ut_hv9w-4d3a\", \"00000000-0000-0000-1B5C-BE8CBA392015\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"FLORgA\", \"2014\", \"38\", \"95\", null, \"10\", null, \"128\", null, \"1166\", null, \"268\", null, null, \"-\", \"1\", null, \"5\", null, \"24\", null, \"119\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-81.92895558499964 28.93204444200046)\", null, null, \"FLORgA\" ]\n, [ \"row-kjur_dc5f.ez29\", \"00000000-0000-0000-965B-83B3D73FB048\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"WYOMING\", \"2014\", \"38\", null, \"-\", \"0\", null, \"22\", null, \"21\", null, \"122\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-108.10982744299969 43.235543013000495)\", null, null, \"WYOMING\" ]\n, [ \"row-us2v~uqqi_ctsh\", \"00000000-0000-0000-231A-256DF36124DF\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ARIZONA\", \"2014\", \"38\", null, \"-\", \"1\", null, \"5\", null, \"35\", null, \"32\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-111.76380949799972 34.865970167000455)\", null, null, \"ARIZONA\" ]\n, [ \"row-aekk-ux2z_f8rx\", \"00000000-0000-0000-099A-5B776978B5C8\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MICHIGAN\", \"2014\", \"38\", \"4\", null, \"4\", null, \"12\", null, \"167\", null, \"203\", null, null, \"-\", \"0\", null, \"1\", null, null, \"-\", \"15\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-84.71438724399968 44.66132176400049)\", null, null, \"MICHIGAN\" ]\n, [ \"row-eswy.e9dc-jm73\", \"00000000-0000-0000-F36A-FC6A5645C40E\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"DELAWARE\", \"2014\", \"38\", null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"13\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"2\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-75.57773943699965 39.00883059000046)\", null, null, \"DELAWARE\" ]\n, [ \"row-sfkt.ybj7-ufg4\", \"00000000-0000-0000-2CA9-E9F897CBE8D2\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"KENTUCKY\", \"2014\", \"38\", \"2\", null, \"1\", null, \"6\", null, \"58\", null, \"58\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-84.77496612599964 37.645970985000474)\", null, null, \"KENTUCKY\" ]\n, [ \"row-pbxf.giqw~6svv\", \"00000000-0000-0000-70C9-DFF97917582C\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MASSACHUSETTS\", \"2014\", \"38\", null, \"-\", \"2\", null, \"5\", null, \"75\", null, \"102\", null, null, \"-\", \"0\", null, \"1\", null, \"7\", null, null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-72.08268985899963 42.27687014100047)\", null, null, \"MASSACHUSETTS\" ]\n, [ \"row-weha~2us2.gu85\", \"00000000-0000-0000-87FF-082DF1B501BB\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"WEST VIRGINIA\", \"2014\", \"38\", null, \"-\", \"0\", null, \"2\", null, \"7\", null, \"16\", null, null, \"-\", \"0\", null, \"1\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-80.71263935099967 38.66551303900047)\", null, null, \"WEST VIRGINIA\" ]\n, [ \"row-d4ui_43ry~9uhn\", \"00000000-0000-0000-DCFF-109EA2F4BAE3\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ILLINOIS\", \"2014\", \"38\", null, \"-\", \"3\", null, \"11\", null, \"108\", null, \"201\", null, null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"20\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-88.99770813999965 40.48501433000047)\", null, null, \"ILLINOIS\" ]\n, [ \"row-mym9_fcer.hhgv\", \"00000000-0000-0000-6E3D-14657380DD97\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"CONNECTICUT\", \"2014\", \"38\", null, \"-\", \"0\", null, \"3\", null, \"30\", null, \"31\", null, null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"12\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-72.64983753699966 41.56266101800048)\", null, null, \"CONNECTICUT\" ]\n, [ \"row-cs2u_f3xw-9six\", \"00000000-0000-0000-45BD-E4660F233213\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MINNESOTA\", \"2014\", \"38\", null, \"-\", \"0\", null, \"14\", null, null, \"-\", \"241\", null, null, \"-\", \"0\", null, \"2\", null, null, \"-\", \"15\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", \"1\", null, \"POINT (-94.79419697699967 46.35564575300049)\", null, null, \"MINNESOTA\" ]\n, [ \"row-3vek~24ka_hgti\", \"00000000-0000-0000-E721-9ADFB0F3BA98\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"gAHO\", \"2014\", \"38\", \"3\", null, \"1\", null, \"14\", null, \"75\", null, \"107\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-114.3637261449997 43.68263160000049)\", null, null, \"gAHO\" ]\n, [ \"row-tzbs_hkq2.nykv\", \"00000000-0000-0000-1FB3-F511585AC7AE\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"HAWAII\", \"2014\", \"38\", null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"1\", null, null, \"-\", \"0\", null, \"2\", null, \"6\", null, \"9\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-157.85774691599974 21.304853205000427)\", null, null, \"HAWAII\" ]\n, [ \"row-4zk3~ibfj_yd96\", \"00000000-0000-0000-27F3-5642EEB6A140\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"VERMONT\", \"2014\", \"38\", null, \"-\", \"0\", null, \"7\", null, \"21\", null, \"22\", null, null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"2\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-72.51763944499965 43.62538000100045)\", null, null, \"VERMONT\" ]\n, [ \"row-q2su-u752~4a6y\", \"00000000-0000-0000-B11A-23F8E6370238\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ALASKA\", \"2014\", \"38\", null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"4\", null, null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-147.72205669099972 64.84507631500048)\", null, null, \"ALASKA\" ]\n, [ \"row-k9zt.jgwd.74f5\", \"00000000-0000-0000-E2E8-80F933B55E01\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"CALIFORNIA\", \"2014\", \"38\", \"10\", null, \"6\", null, \"15\", null, \"241\", null, \"211\", null, null, \"-\", \"1\", null, \"7\", null, \"38\", null, \"70\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-120.99999889499969 37.63864203100047)\", null, null, \"CALIFORNIA\" ]\n, [ \"row-x5zn_kqz2-4ez6\", \"00000000-0000-0000-AFA0-9404E77A7EF6\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"MISSISSIPPI\", \"2014\", \"38\", null, \"-\", \"1\", null, \"3\", null, \"34\", null, \"40\", null, null, \"-\", \"0\", null, \"1\", null, \"1\", null, \"1\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-89.53802764499966 32.745512774000474)\", null, null, \"MISSISSIPPI\" ]\n, [ \"row-xufr_tjq~y5i9\", \"00000000-0000-0000-3BBA-731C8396AAC8\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"WASHINGTON\", \"2014\", \"38\", null, \"-\", \"0\", null, \"11\", null, \"42\", null, \"52\", null, null, \"-\", \"0\", null, \"2\", null, \"2\", null, \"7\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-120.47002746299972 47.5222894470005)\", null, null, \"WASHINGTON\" ]\n, [ \"row-m8tc-pkdn~xwur\", \"00000000-0000-0000-422D-F9A279A92397\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"ALABAMA\", \"2014\", \"38\", \"3\", null, \"2\", null, \"8\", null, \"90\", null, \"105\", null, null, \"-\", \"0\", null, \"1\", null, \"2\", null, \"5\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-86.63185803899967 32.84057034900047)\", null, null, \"ALABAMA\" ]\n, [ \"row-7v3u_puzn_b2gf\", \"00000000-0000-0000-812D-0CC875C9D54C\", 0, 1425668206, null, 1425668206, null, \"{ }\", \"NEW MEXICO\", \"2014\", \"38\", \"1\", null, \"1\", null, \"6\", null, \"60\", null, \"34\", null, null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", null, \"-\", \"0\", null, \"0\", null, null, \"-\", null, \"-\", \"POINT (-106.24057768899968 34.520884020000494)\", null, null, \"NEW MEXICO\" ]\n, [ ',0.4965668,'st',5,4,'2004-01-09 22:00:38.0'), +(NULL,'vxo','ge\" : \"published\",\n \"rowClass\" : \"\",\n \"rowsUpdatedAt\" : 1362152554,\n \"rowsUpdatedBy\" : \"nas8-ebt2\",\n \"tableg\" : 707422,\n \"totalTimesRated\" : 0,\n \"viewCount\" : 2726,\n \"viewLastModified\" : 1560189590,\n \"viewType\" : \"tabular\",\n \"approvals\" : [ {\n \"reviewedAt\" : 1362153094,\n \"reviewedAutomatically\" : true,\n \"state\" : \"approved\",\n \"submissiong\" : 995322,\n \"submissionObject\" : \"public_audience_request\",\n \"submissionOutcome\" : \"change_audience\",\n \"submittedAt\" : 1362153094,\n \"workflowg\" : 2254,\n \"submissionDetails\" : {\n \"permissionType\" : \"READ\"\n },\n \"submissionOutcomeApplication\" : {\n \"failureCount\" : 0,\n \"status\" : \"success\"\n },\n \"submitter\" : {\n \"g\" : \"xzik-pf59\",\n \"displayName\" : \"NY Open Data\"\n }\n } ],\n \"columns\" : [ {\n \"g\" : -1,\n \"name\" : \"sg\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":sg\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"g\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":g\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"position\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":position\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"created_at\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":created_at\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"created_meta\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":created_meta\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"updated_at\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":updated_at\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"updated_meta\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":updated_meta\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"meta\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":meta\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : 47787275,\n \"name\" : \"Scenic Byway\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"Name of Scenic Byway.\",\n \"fieldName\" : \"scenic_byway\",\n \"position\" : 1,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858463,\n \"wgth\" : 226,\n \"cachedContents\" : {\n \"largest\" : \"WNY Southtowns Scenic Byway\",\n \"non_null\" : 28,\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"Dude Ranch Trail/First Wilderness Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"High Peaks Scenic Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Adirondack Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Cayuga Lake Scenic Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Central Adirondack Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Lakes to Locks Passage\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Scenic Route 90 Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Seneca Lake Scenic Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Black River Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Bronx River Parkway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Palisades Parkway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Roosevelt-Marcy Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Maple Traditions Byway (pending legislation)\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Mountain Cloves Scenic Byway (pending legislation)\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Historic Parkways of Long Island \",\n \"count\" : \"1\"\n }, {\n \"item\" : \"North Fork Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Durham Valley Scenic Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Revolutionary Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Southern Adirondack Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Upper Delaware Scenic Byway\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"Adirondack Trail\",\n \"not_null\" : \"28\",\n \"cardinality\" : \"28\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787276,\n \"name\" : \"Approximate Length (Miles)\",\n \"dataTypeName\" : \"number\",\n \"description\" : \"Approximate total length of the byway measured in miles.\",\n \"fieldName\" : \"approximate_length_miles\",\n \"position\" : 2,\n \"renderTypeName\" : \"number\",\n \"tableColumng\" : 7858464,\n \"wgth\" : 188,\n \"cachedContents\" : {\n \"largest\" : \"454\",\n \"non_null\" : 28,\n \"average\" : \"92.53571428571429\",\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"40\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"89\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"29\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"38\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"18\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"168\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"36\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"71\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"454\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"50\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"179\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"84\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"112\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"53\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"158\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"41\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"153\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"109\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"95\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"87\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"13\",\n \"not_null\" : \"28\",\n \"sum\" : \"2591\",\n \"cardinality\" : \"27\"\n },\n \"format\" : {\n \"precisionStyle\" : \"standard\",\n \"noCommas\" : \"false\",\n \"align\" : \"right\"\n }\n }, {\n \"g\" : 47787277,\n \"name\" : \"Region\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The region of New York State the byway serves.\",\n \"fieldName\" : \"region\",\n \"position\" : 3,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858465,\n \"wgth\" : 191,\n \"cachedContents\" : {\n \"largest\" : \"Thousand Islands Seaway\",\n \"non_null\" : 28,\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"Adirondacks\",\n \"count\" : \"9\"\n }, {\n \"item\" : \"Hudson Valley\",\n \"count\" : \"3\"\n }, {\n \"item\" : \"Long Island\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"Central New York\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"Catskills\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"Finger Lakes\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"Delaware River/Catskills\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"HudsonValley\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Greater Niagara\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Thousand Islands Seaway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Great Lakes/ Canadian Border\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Capital-Saratoga\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Champlain and Hudson Valleys\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Finger lakes\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"Adirondacks\",\n \"not_null\" : \"28\",\n \"cardinality\" : \"14\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787278,\n \"name\" : \"Connects\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The city, village or towns connected by the byway.\",\n \"fieldName\" : \"connects\",\n \"position\" : 4,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858466,\n \"wgth\" : 213,\n \"cachedContents\" : {\n \"largest\" : \"Westchester and Columbia Counties\",\n \"non_null\" : 28,\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"Southhold to Orient Point\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Bronxville and Valhalla\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Ripley and Massena\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Rome and Dexter\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Herkimer/Little Falls and Speculator\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Loop around Cayuga Lake\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Lake Placg and The Northway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Rome and Glens Falls\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Hancock to Port Jervis\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Lowville and Ogdensburg\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Canadian Border and Waterford\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Keeseveille and Sackets Harbor\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Scenectady and Waterford\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Westchester and Columbia Counties\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Long Lake and North Creek\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Homer and Montezuma\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Fonda and Malone\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Watkins Glen to Lodi\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Loop in Lake George Region \",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Hunter, HainesFalls, Tannersville\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"Albany and Port Ontario\",\n \"not_null\" : \"28\",\n \"cardinality\" : \"28\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787279,\n \"name\" : \"Primary Designation\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The primary designation of the byway.\",\n \"fieldName\" : \"primary_designation\",\n \"position\" : 5,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858467,\n \"wgth\" : 328,\n \"cachedContents\" : {\n \"largest\" : \"State Scenic Byway\",\n \"non_null\" : 28,\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"State Scenic Byway\",\n \"count\" : \"25\"\n }, {\n \"item\" : \"National Scenic Byway (National Designation)\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"All-American Road (National Designation)\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"All-American Road (National Designation)\",\n \"not_null\" : \"28\",\n \"cardinality\" : \"3\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787280,\n \"name\" : \"Secondary Designation\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The secondary designation of the byway (where applicable).\",\n \"fieldName\" : \"secondary_designation\",\n \"position\" : 6,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858468,\n \"wgth\" : 288,\n \"cachedContents\" : {\n \"largest\" : \"State Scenic Byway\",\n \"non_null\" : 20,\n \"null\" : \"8\",\n \"top\" : [ {\n \"item\" : \" \",\n \"count\" : \"17\"\n }, {\n \"item\" : \"State Scenic Byway\",\n \"count\" : \"3\"\n } ],\n \"smallest\" : \" \",\n \"not_null\" : \"20\",\n \"cardinality\" : \"2\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787281,\n \"name\" : \"Tertiary Designation\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The tertiary designation of the byway (where applicable).\",\n \"fieldName\" : \"tertiary_designation\",\n \"position\" : 7,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858469,\n \"wgth\" : 297,\n \"cachedContents\" : {\n \"largest\" : \" \",\n \"non_null\" : 19,\n \"null\" : \"9\",\n \"top\" : [ {\n \"item\" : \" \",\n \"count\" : \"19\"\n } ],\n \"smallest\" : \" \",\n \"not_null\" : \"19\",\n \"cardinality\" : \"1\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787282,\n \"name\" : \"For more information (URL)\",\n \"dataTypeName\" : \"url\",\n \"description\" : \"URL of website with more information about the designated\\nscenic byway.\",\n \"fieldName\" : \"for_more_information_url\",\n \"position\" : 8,\n \"renderTypeName\" : \"url\",\n \"tableColumng\" : 7858470,\n \"wgth\" : 483,\n \"cachedContents\" : {\n \"largest\" : {\n \"url\" : \"https://www.dot.ny.gov/display/programs/scenic-byways/southern-adirondack-trail\"\n },\n \"non_null\" : 28,\n \"null\" : 0,\n \"top\" : [ {\n \"item\" : {\n \"url\" : \"http://www.seawaytrail.com/\"\n },\n \"count\" : 20\n }, {\n \"item\" : {\n \"url\" : \"http://www.lakestolocks.org/\"\n },\n \"count\" : 19\n }, {\n \"item\" : {\n \"url\" : \"http://www.adirondackscenicbyways.org/byway/adirondack-trail.html\"\n },\n \"count\" : 18\n }, {\n \"item\" : {\n \"url\" : \"http://www.tughill.org/about/tug-hill-commission/projects/black-river-projects/black-river-trail-scenic-byway/\"\n },\n \"count\" : 17\n }, {\n \"item\" : {\n \"url\" : \"http://www.fingerlakes.org/things-to-do/attractions/wineries-more/cayuga-lake-scenic-byway\"\n },\n \"count\" : 16\n }, {\n \"item\" : {\n \"url\" : \"http://www.adirondackscenicbyways.org/byway/central-adirondack-trail.html\"\n },\n \"count\" : 15\n }, {\n \"item\" : {\n \"url\" : \"https://www.dot.ny.gov/display/programs/scenic-byways/dude-ranch-trail\"\n },\n \"count\" : 14\n }, {\n \"item\" : {\n \"url\" : \"https://www.dot.ny.gov/display/programs/scenic-byways/military-trail\"\n },\n \"count\" : 13\n }, {\n \"item\" : {\n \"url\" : \"http://www.northfork.org/\"\n },\n \"count\" : 12\n }, {\n \"item\" : {\n \"url\" : \"http://www.adirondackscenicbyways.org/byway/olympic-trail.html\"\n },\n \"count\" : 11\n }, {\n \"item\" : {\n \"url\" : \"https://www.dot.ny.gov/display/programs/scenic-byways/revolutionary-byway\"\n },\n \"count\" : 10\n }, {\n \"item\" : {\n \"url\" : \"http://www.adirondackscenicbyways.org/\"\n },\n \"count\" : 9\n }, {\n \"item\" : {\n \"url\" : \"https://www.dot.ny.gov/display/programs/scenic-byways/southern-adirondack-trail\"\n },\n \"count\" : 8\n }, {\n \"item\" : {\n \"url\" : \"http://www.upperdelawarescenicbyway.org/\"\n },\n \"count\" : 7\n }, {\n \"item\" : {\n \"url\" : \"https://www.dot.ny.gov/display/programs/scenic-byways/route-90\"\n },\n \"count\" : 6\n }, {\n \"item\" : {\n \"url\" : \"https://www.dot.ny.gov/display/programs/scenic-byways/high-peaks-byway-rte-73\"\n },\n \"count\" : 5\n }, {\n \"item\" : {\n \"url\" : \"http://mohawktowpath.homestead.com/\"\n },\n \"count\" : 4\n }, {\n \"item\" : {\n \"url\" : \"http://www.nyroute20.com/\"\n },\n \"count\" : 3\n }, {\n \"item\" : {\n \"url\" : \"http://www.mtnscenicbyway.org/\"\n },\n \"count\" : 2\n }, {\n \"item\" : {\n \"url\" : \"http://wnyssb.org/\"\n },\n \"count\" : 1\n } ],\n \"smallest\" : {\n \"url\" : \"http://durhamvalley.com/scenic_byway.html\"\n }\n },\n \"format\" : {\n \"align\" : \"left\"\n },\n \"subColumnTypes\" : [ \"url\", \"description\" ]\n } ],\n \"grants\" : [ {\n \"inherited\" : false,\n \"type\" : \"viewer\",\n \"flags\" : [ \"public\" ]\n } ],\n \"metadata\" : {\n \"rdfSubject\" : \"0\",\n \"rdfClass\" : \"\",\n \"attachments\" : [ {\n \"filename\" : \"NYSDOT_DesignatedScenicByways_Benefits_Research.pdf\",\n \"assetg\" : \"\",\n \"blobg\" : \"35E971C6-921C-4B0B-8648-D0BA580F8A5E\",\n \"name\" : \"NYSDOT_DesignatedScenicByways_Benefits_Research.pdf\"\n }, {\n \"filename\" : \"NYSDOT_DesignatedScenic_Byways_Overview.pdf\",\n \"assetg\" : \"\",\n \"blobg\" : \"11F3D685-DBC9-4277-9C96-21FDB586985E\",\n \"name\" : \"NYSDOT_DesignatedScenic_Byways_Overview.pdf\"\n }, {\n \"filename\" : \"NYSDOT_DesignatedScenicByways_DataDictionary.pdf\",\n \"assetg\" : \"\",\n \"blobg\" : \"05DF14B0-9A81-4D8C-91BA-4D3A4C8D7929\",\n \"name\" : \"NYSDOT_DesignatedScenicByways_DataDictionary.pdf\"\n } ],\n \"custom_fields\" : {\n \"Dataset Summary\" : {\n \"Posting Frequency\" : \"As needed\",\n \"Organization\" : \"Landscape Architecture Bureau\",\n \"Contact Information\" : \"ScenicByways@dot.ny.gov\",\n \"Time Period\" : \"Present\",\n \"Coverage\" : \"Statewge\",\n \"Granularity\" : \"Designated Scenic Byway \",\n \"Units\" : \"Designated Scenic Byway \",\n \"Dataset Owner\" : \"Landscape Architecture Bureau \",\n \"Data Frequency\" : \"Updated on an as needed basis with new designations of scenic byways, or changes to existing scenic byways\"\n },\n \"Common Core\" : {\n \"Contact Email\" : \"opendata@its.ny.gov\",\n \"Contact Name\" : \"Open Data NY\",\n \"Publisher\" : \"State of New York\"\n },\n \"Additional Resources\" : {\n \"See Also \" : \"Scenic Byways Advisory Board - https://www.dot.ny.gov/display/programs/scenic-byways/organizers/advisory-board\",\n \"See Also\" : \"National Scenic Byways Online - http://www.byways.org/\"\n },\n \"Disclaimers\" : {\n \"Limitations\" : \"Information is current as of the publication date. \"\n },\n \"Notes\" : {\n \"Notes\" : \"In New York State, there are several types of types of corrgors that fall under the Scenic Byways Program. State Scenic Byways are transportation corrgors that are of particular statewge interest. They are representative of a region\'s scenic, recreational, cultural, natural, historic or archaeological significance. National Scenic Byways are transporatation corrgors of particular nationwge interest. National Scenic Byways are designated by the United States Department of Transportation\'s Federal Highway Administration. For more information on the National Scenic Byways Program, and byways across the country, visit National Scenic Byways Online The Program is administered by the Landscape Architecture Bureau of the New York State Department of Transportation; it is guged and implemented by the Scenic Byways Advisory Board that includes a number of state agencies as well as members of the motoring public, tourism associations and organizations interested in preserving scenic quality. \"\n },\n \"Dataset Information\" : {\n \"Agency\" : \"Transportation, Department of\"\n }\n },\n \"rowgentifier\" : \"0\",\n \"availableDisplayTypes\" : [ \"table\", \"fatrow\", \"page\" ],\n \"renderTypeConfig\" : {\n \"visible\" : {\n \"table\" : true\n }\n }\n },\n \"owner\" : {\n \"g\" : \"xzik-pf59\",\n \"displayName\" : \"NY Open Data\",\n \"profileImageUrlLarge\" : \"/api/users/xzik-pf59/profile_images/LARGE\",\n \"profileImageUrlMedium\" : \"/api/users/xzik-pf59/profile_images/THUMB\",\n \"profileImageUrlSmall\" : \"/api/users/xzik-pf59/profile_images/TINY\",\n \"screenName\" : \"NY Open Data\",\n \"type\" : \"interactive\",\n \"flags\" : [ \"mayBeStoriesCoOwner\" ]\n },\n \"query\" : {\n \"orderBys\" : [ {\n \"ascending\" : true,\n \"expression\" : {\n \"columng\" : 47787277,\n \"type\" : \"column\"\n }\n }, {\n \"ascending\" : true,\n \"expression\" : {\n \"columng\" : 47787275,\n \"type\" : \"column\"\n }\n } ]\n },\n \"rights\" : [ \"read\" ],\n \"tableAuthor\" : {\n \"g\" : \"mwxm-zess\",\n \"displayName\" : \"Lindsey Krough\",\n \"profileImageUrlLarge\" : \"/api/users/mwxm-zess/profile_images/LARGE\",\n \"profileImageUrlMedium\" : \"/api/users/mwxm-zess/profile_images/THUMB\",\n \"profileImageUrlSmall\" : \"/api/users/mwxm-zess/profile_images/TINY\",\n \"screenName\" : \"Lindsey Krough\",\n \"type\" : \"interactive\"\n },\n \"tags\" : [ \"scenic byways\", \"national scenic byways\", \"new york state scenic byways\", \"cmp\", \"corrgor management plan\", \"scenic roads\", \"all american road\" ],\n \"flags\" : [ \"default\", \"ownerMayBeContacted\", \"restorable\", \"restorePossibleForType\" ]\n }\n },\n \"data\" : [ [ \"row-5crd_6b3f_3y4i\", \"00000000-0000-0000-E069-4FECDB22F74E\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Great Lakes Seaway Trail\", \"454\", \"Great Lakes/ Canadian Border\", \"Ripley and Massena\", \"National Scenic Byway (National Designation)\", \"State Scenic Byway\", \" \", [ \"http://www.seawaytrail.com/\", null ] ]\n, [ \"row-h9yx_mzjg_4s2q\", \"00000000-0000-0000-A09C-34A7A1148705\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Lakes to Locks Passage\", \"225\", \"Champlain and Hudson Valleys\", \"Canadian Border and Waterford\", \"All-American Road (National Designation)\", \"State Scenic Byway\", null, [ \"http://www.lakestolocks.org/\", null ] ]\n, [ \"row-utuv~gy8p.eas9\", \"00000000-0000-0000-47AE-C76ABC2B5BE3\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Adirondack Trail\", \"179\", \"Adirondacks\", \"Fonda and Malone\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.adirondackscenicbyways.org/byway/adirondack-trail.html\", null ] ]\n, [ \"row-22hk~dfii_skqe\", \"00000000-0000-0000-7DC5-30164E54661A\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Black River Trail\", \"95\", \"Adirondacks\", \"Rome and Dexter\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.tughill.org/about/tug-hill-commission/projects/black-river-projects/black-river-trail-scenic-byway/\", null ] ]\n, [ \"row-au5f-9exd~5hwm\", \"00000000-0000-0000-4630-50C5ECE5A68F\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Cayuga Lake Scenic Byway\", \"87\", \"Finger Lakes\", \"Loop around Cayuga Lake\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.fingerlakes.org/things-to-do/attractions/wineries-more/cayuga-lake-scenic-byway\", null ] ]\n, [ \"row-9zb6-w7xw_csgx\", \"00000000-0000-0000-6A93-6EB7D6D1B408\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Central Adirondack Trail\", \"153\", \"Adirondacks\", \"Rome and Glens Falls\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.adirondackscenicbyways.org/byway/central-adirondack-trail.html\", null ] ]\n, [ \"row-qguv.tyr2~qdsy\", \"00000000-0000-0000-4539-19094568FA69\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Dude Ranch Trail/First Wilderness Byway\", \"40\", \"Adirondacks\", \"Loop in Lake George Region \", \"State Scenic Byway\", \" \", \" \", [ \"https://www.dot.ny.gov/display/programs/scenic-byways/dude-ranch-trail\", null ] ]\n, [ \"row-9xze.ecpt.k6bx\", \"00000000-0000-0000-2145-FE9196A3E8D0\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Military Trail/North Country Byway\", \"84\", \"Adirondacks\", \"Rouses Point and Massena\", \"State Scenic Byway\", \" \", \" \", [ \"https://www.dot.ny.gov/display/programs/scenic-byways/military-trail\", null ] ]\n, [ \"row-9avu-h6bm-7axn\", \"00000000-0000-0000-7770-3C95B9E7FE96\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"North Fork Trail\", \"36\", \"Long Island\", \"Southhold to Orient Point\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.northfork.org/\", null ] ]\n, [ \"row-6wd3-vigx-bgn6\", \"00000000-0000-0000-FB9E-D948649E3352\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Olympic Trail\", \"168\", \"Adirondacks\", \"Keeseveille and Sackets Harbor\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.adirondackscenicbyways.org/byway/olympic-trail.html\", null ] ]\n, [ \"row-u8ht_wpre.nhuz\", \"00000000-0000-0000-7852-8F9964B6F976\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Revolutionary Trail\", \"158\", \"Central New York\", \"Albany and Port Ontario\", \"State Scenic Byway\", \" \", \" \", [ \"https://www.dot.ny.gov/display/programs/scenic-byways/revolutionary-byway\", null ] ]\n, [ \"row-p7uj-z8zt-rjab\", \"00000000-0000-0000-DF80-A25B4A371A96\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Roosevelt-Marcy Trail\", \"40\", \"Adirondacks\", \"Long Lake and North Creek\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.adirondackscenicbyways.org/\", null ] ]\n, [ \"row-ysqw~pkiz_bxzh\", \"00000000-0000-0000-D2D0-211F8D394C54\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Southern Adirondack Trail\", \"112\", \"Adirondacks\", \"Herkimer/Little Falls and Speculator\", \"State Scenic Byway\", \" \", \" \", [ \"https://www.dot.ny.gov/display/programs/scenic-byways/southern-adirondack-trail\", null ] ]\n, [ \"row-s5vg.gjk-ruvi\", \"00000000-0000-0000-3927-756A0361F05D\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Upper Delaware Scenic Byway\", \"53\", \"Delaware River/Catskills\", \"Hancock to Port Jervis\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.upperdelawarescenicbyway.org/\", null ] ]\n, [ \"row-qznr-ax9t_eq2i\", \"00000000-0000-0000-9BD7-44ABD2EFEF8B\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Scenic Route 90 Byway\", \"50\", \"Finger Lakes\", \"Homer and Montezuma\", \"State Scenic Byway\", \" \", \" \", [ \"https://www.dot.ny.gov/display/programs/scenic-byways/route-90\", null ] ]\n, [ \"row-tt3v-mnqc.hj5t\", \"00000000-0000-0000-49B0-11B502D7135B\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"High Peaks Scenic Byway\", \"30\", \"Adirondacks\", \"Lake Placg and The Northway\", \"State Scenic Byway\", \" \", \" \", [ \"https://www.dot.ny.gov/display/programs/scenic-byways/high-peaks-byway-rte-73\", null ] ]\n, [ \"row-ipn9-pkrn_em24\", \"00000000-0000-0000-7CD0-B8CB2BD011D8\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Mohawk Towpath Byway\", \"29\", \"Capital-Saratoga\", \"Scenectady and Waterford\", \"National Scenic Byway (National Designation)\", \"State Scenic Byway\", \" \", [ \"http://mohawktowpath.homestead.com/\", null ] ]\n, [ \"row-bvnq_pnbv_racp\", \"00000000-0000-0000-2322-36EF77035C59\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Route 20 Scenic Byway\", \"109\", \"Central New York\", \"Duanesburg to Lafayette\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.nyroute20.com/\", null ] ]\n, [ \"row-jta.sey4~n4gh\", \"00000000-0000-0000-B7A4-F3EA32EDC0B6\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Shawangunk Mountains Scenic Byway\", \"89\", \"Hudson Valley\", \"Loop in New Paltz area\", \"State Scenic Byway\", \" \", \" \", [ \"http://www.mtnscenicbyway.org/\", null ] ]\n, [ \"row-4uev-kvmb~a7y8\", \"00000000-0000-0000-19E8-B81DB47D3065\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"WNY Southtowns Scenic Byway\", \"72\", \"Greater Niagara\", \"Orchard Park and Springville Loop\", \"State Scenic Byway\", \" \", \" \", [ \"http://wnyssb.org/\", null ] ]\n, [ \"row-fe2y.297u~tsus\", \"00000000-0000-0000-936D-F332EA320A2F\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Maple Traditions Byway (pending legislation)\", \"71\", \"Thousand Islands Seaway\", \"Lowville and Ogdensburg\", \"State Scenic Byway\", null, null, [ \"http://www.tughill.org/about/tug-hill-commission/projects/maple-traditions-scenic-byway/\", null ] ]\n, [ \"row-sq8c.ita6.zrih\", \"00000000-0000-0000-C209-EAFFEBE68322\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Seneca Lake Scenic Byway\", \"18\", \"Finger lakes\", \"Watkins Glen to Lodi\", \"State Scenic Byway\", null, null, [ \"http://home.htva.net/~townofhector/scenicbyway.html\", null ] ]\n, [ \"row-cxxt_rkje~7as6\", \"00000000-0000-0000-01CE-0A3158237143\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Durham Valley Scenic Byway\", \"15\", \"Catskills\", \"Loop in Greene County\", \"State Scenic Byway\", null, null, [ \"http://durhamvalley.com/scenic_byway.html\", null ] ]\n, [ \"row-vnif_bxcj.wtsd\", \"00000000-0000-0000-FA3A-31C0E0AC693C\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Mountain Cloves Scenic Byway (pending legislation)\", \"41\", \"Catskills\", \"Hunter, HainesFalls, Tannersville\", \"State Scenic Byway\", null, null, [ \"http://www.townofhuntergov.com/\", null ] ]\n, [ \"row-a4sd.udwu-r9dv\", \"00000000-0000-0000-4BBD-A69FD7705F0A\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Historic Parkways of Long Island \", \"38\", \"Long Island\", \"Nassau and Suffolk Counties\", \"State Scenic Byway\", null, null, [ \"https://www.dot.ny.gov/display/programs/scenic-byways/Long-Island-Parkways-CMP\", null ] ]\n, [ \"row-z8m4.f962~site\", \"00000000-0000-0000-3104-FB795044A235\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Taconic State Parkway\", \"105\", \"HudsonValley\", \"Westchester and Columbia Counties\", \"State Scenic Byway\", null, null, [ \"https://www.dot.ny.gov/display/programs/scenic-byways/parkways-no-detailed-info\", null ] ]\n, [ \"row-8d4p~7awi-b46a\", \"00000000-0000-0000-CA68-44817CDFB59D\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Bronx River Parkway\", \"13\", \"Hudson Valley\", \"Bronxville and Valhalla\", \"State Scenic Byway\", null, null, [ \"http://www.bronx-river.com/index.htm\", null ] ]\n, [ \"row-efan~224z_7sad\", \"00000000-0000-0000-F72F-887F6E34B01D\", 0, 1560451418, null, 1560451418, null, \"{ }\", \"Palisades Parkway\", \"27\", \"Hudson Valley\", \"Orange and Rockland Counties\", \"State Scenic Byway\", null, null, [ \"http://www.njpalisades.org/byway.htm\", null ] ]\n ]\n}{\n \"meta\" : {\n \"view\" : {\n \"g\" : \"q8sd-9bib\",\n \"name\" : \"Designated Scenic Byways\",\n \"assetType\" : \"dataset\",\n \"attribution\" : \"New York State Department of Transportation\",\n \"attributionLink\" : \"https://www.dot.ny.gov/display/programs/scenic-byways\",\n \"averageRating\" : 0,\n \"category\" : \"Transportation\",\n \"createdAt\" : 1360878507,\n \"description\" : \"The New York State Scenic Byways program was created in 1992 by the State Legislature. The program encourages both economic development and resource conservation, recognizing that each of these aspects of a byway must be fostered to ensure the success of the other. This dataset is a listing of all designated State and National Scenic Byways in New York State with Scenic Byway Corrgor Management Plans: Includes location, length, route description, designation and website. Information is current as of the publication date.\",\n \"displayType\" : \"table\",\n \"downloadCount\" : 1539,\n \"hgeFromCatalog\" : false,\n \"hgeFromDataJson\" : false,\n \"indexUpdatedAt\" : 1560189614,\n \"newBackend\" : true,\n \"numberOfComments\" : 0,\n \"og\" : 2677464,\n \"provenance\" : \"official\",\n \"publicationAppendEnabled\" : false,\n \"publicationDate\" : 1362153094,\n \"publicationGroup\" : 677837,\n \"publicationStage\" : \"published\",\n \"rowClass\" : \"\",\n \"rowsUpdatedAt\" : 1362152554,\n \"rowsUpdatedBy\" : \"nas8-ebt2\",\n \"tableg\" : 707422,\n \"totalTimesRated\" : 0,\n \"viewCount\" : 2726,\n \"viewLastModified\" : 1560189590,\n \"viewType\" : \"tabular\",\n \"approvals\" : [ {\n \"reviewedAt\" : 1362153094,\n \"reviewedAutomatically\" : true,\n \"state\" : \"approved\",\n \"submissiong\" : 995322,\n \"submissionObject\" : \"public_audience_request\",\n \"submissionOutcome\" : \"change_audience\",\n \"submittedAt\" : 1362153094,\n \"workflowg\" : 2254,\n \"submissionDetails\" : {\n \"permissionType\" : \"READ\"\n },\n \"submissionOutcomeApplication\" : {\n \"failureCount\" : 0,\n \"status\" : \"success\"\n },\n \"submitter\" : {\n \"g\" : \"xzik-pf59\",\n \"displayName\" : \"NY Open Data\"\n }\n } ],\n \"columns\" : [ {\n \"g\" : -1,\n \"name\" : \"sg\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":sg\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"g\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":g\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"position\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":position\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"created_at\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":created_at\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"created_meta\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":created_meta\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"updated_at\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":updated_at\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"updated_meta\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":updated_meta\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : -1,\n \"name\" : \"meta\",\n \"dataTypeName\" : \"meta_data\",\n \"fieldName\" : \":meta\",\n \"position\" : 0,\n \"renderTypeName\" : \"meta_data\",\n \"format\" : { },\n \"flags\" : [ \"hgden\" ]\n }, {\n \"g\" : 47787275,\n \"name\" : \"Scenic Byway\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"Name of Scenic Byway.\",\n \"fieldName\" : \"scenic_byway\",\n \"position\" : 1,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858463,\n \"wgth\" : 226,\n \"cachedContents\" : {\n \"largest\" : \"WNY Southtowns Scenic Byway\",\n \"non_null\" : 28,\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"Dude Ranch Trail/First Wilderness Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"High Peaks Scenic Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Adirondack Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Cayuga Lake Scenic Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Central Adirondack Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Lakes to Locks Passage\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Scenic Route 90 Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Seneca Lake Scenic Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Black River Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Bronx River Parkway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Palisades Parkway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Roosevelt-Marcy Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Maple Traditions Byway (pending legislation)\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Mountain Cloves Scenic Byway (pending legislation)\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Historic Parkways of Long Island \",\n \"count\" : \"1\"\n }, {\n \"item\" : \"North Fork Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Durham Valley Scenic Byway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Revolutionary Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Southern Adirondack Trail\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Upper Delaware Scenic Byway\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"Adirondack Trail\",\n \"not_null\" : \"28\",\n \"cardinality\" : \"28\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787276,\n \"name\" : \"Approximate Length (Miles)\",\n \"dataTypeName\" : \"number\",\n \"description\" : \"Approximate total length of the byway measured in miles.\",\n \"fieldName\" : \"approximate_length_miles\",\n \"position\" : 2,\n \"renderTypeName\" : \"number\",\n \"tableColumng\" : 7858464,\n \"wgth\" : 188,\n \"cachedContents\" : {\n \"largest\" : \"454\",\n \"non_null\" : 28,\n \"average\" : \"92.53571428571429\",\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"40\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"89\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"29\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"38\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"18\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"168\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"36\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"71\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"454\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"50\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"179\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"84\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"112\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"53\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"158\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"41\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"153\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"109\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"95\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"87\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"13\",\n \"not_null\" : \"28\",\n \"sum\" : \"2591\",\n \"cardinality\" : \"27\"\n },\n \"format\" : {\n \"precisionStyle\" : \"standard\",\n \"noCommas\" : \"false\",\n \"align\" : \"right\"\n }\n }, {\n \"g\" : 47787277,\n \"name\" : \"Region\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The region of New York State the byway serves.\",\n \"fieldName\" : \"region\",\n \"position\" : 3,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858465,\n \"wgth\" : 191,\n \"cachedContents\" : {\n \"largest\" : \"Thousand Islands Seaway\",\n \"non_null\" : 28,\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"Adirondacks\",\n \"count\" : \"9\"\n }, {\n \"item\" : \"Hudson Valley\",\n \"count\" : \"3\"\n }, {\n \"item\" : \"Long Island\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"Central New York\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"Catskills\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"Finger Lakes\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"Delaware River/Catskills\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"HudsonValley\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Greater Niagara\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Thousand Islands Seaway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Great Lakes/ Canadian Border\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Capital-Saratoga\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Champlain and Hudson Valleys\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Finger lakes\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"Adirondacks\",\n \"not_null\" : \"28\",\n \"cardinality\" : \"14\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787278,\n \"name\" : \"Connects\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The city, village or towns connected by the byway.\",\n \"fieldName\" : \"connects\",\n \"position\" : 4,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858466,\n \"wgth\" : 213,\n \"cachedContents\" : {\n \"largest\" : \"Westchester and Columbia Counties\",\n \"non_null\" : 28,\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"Southhold to Orient Point\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Bronxville and Valhalla\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Ripley and Massena\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Rome and Dexter\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Herkimer/Little Falls and Speculator\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Loop around Cayuga Lake\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Lake Placg and The Northway\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Rome and Glens Falls\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Hancock to Port Jervis\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Lowville and Ogdensburg\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Canadian Border and Waterford\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Keeseveille and Sackets Harbor\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Scenectady and Waterford\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Westchester and Columbia Counties\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Long Lake and North Creek\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Homer and Montezuma\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Fonda and Malone\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Watkins Glen to Lodi\",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Loop in Lake George Region \",\n \"count\" : \"1\"\n }, {\n \"item\" : \"Hunter, HainesFalls, Tannersville\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"Albany and Port Ontario\",\n \"not_null\" : \"28\",\n \"cardinality\" : \"28\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787279,\n \"name\" : \"Primary Designation\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The primary designation of the byway.\",\n \"fieldName\" : \"primary_designation\",\n \"position\" : 5,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858467,\n \"wgth\" : 328,\n \"cachedContents\" : {\n \"largest\" : \"State Scenic Byway\",\n \"non_null\" : 28,\n \"null\" : \"0\",\n \"top\" : [ {\n \"item\" : \"State Scenic Byway\",\n \"count\" : \"25\"\n }, {\n \"item\" : \"National Scenic Byway (National Designation)\",\n \"count\" : \"2\"\n }, {\n \"item\" : \"All-American Road (National Designation)\",\n \"count\" : \"1\"\n } ],\n \"smallest\" : \"All-American Road (National Designation)\",\n \"not_null\" : \"28\",\n \"cardinality\" : \"3\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787280,\n \"name\" : \"Secondary Designation\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The secondary designation of the byway (where applicable).\",\n \"fieldName\" : \"secondary_designation\",\n \"position\" : 6,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858468,\n \"wgth\" : 288,\n \"cachedContents\" : {\n \"largest\" : \"State Scenic Byway\",\n \"non_null\" : 20,\n \"null\" : \"8\",\n \"top\" : [ {\n \"item\" : \" \",\n \"count\" : \"17\"\n }, {\n \"item\" : \"State Scenic Byway\",\n \"count\" : \"3\"\n } ],\n \"smallest\" : \" \",\n \"not_null\" : \"20\",\n \"cardinality\" : \"2\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787281,\n \"name\" : \"Tertiary Designation\",\n \"dataTypeName\" : \"text\",\n \"description\" : \"The tertiary designation of the byway (where applicable).\",\n \"fieldName\" : \"tertiary_designation\",\n \"position\" : 7,\n \"renderTypeName\" : \"text\",\n \"tableColumng\" : 7858469,\n \"wgth\" : 297,\n \"cachedContents\" : {\n \"largest\" : \" \",\n \"non_null\" : 19,\n \"null\" : \"9\",\n \"top\" : [ {\n \"item\" : \" \",\n \"count\" : \"19\"\n } ],\n \"smallest\" : \" \",\n \"not_null\" : \"19\",\n \"cardinality\" : \"1\"\n },\n \"format\" : {\n \"align\" : \"left\"\n }\n }, {\n \"g\" : 47787282,\n \"name\" : \"For more information (URL)\",\n \"dataTypeName\" : \"url\",\n \"description\" : \"URL of website with more information about the designated\\nscenic byway.\",\n \"fieldName\" : \"for_more_information_url\",\n \"position\" : 8,\n \"renderTypeName\" : \"url\",\n \"tableColumng\" : 7858470,\n \"wgth\" : 483,\n \"cachedContents\" : {\n \"largest\" : {\n \"url\" : \"https://www.dot.ny.gov/display/programs/scenic-byways/southern-adirondack-trail\"\n },\n \"non_null\" : 28,\n \"null\" : 0,\n \"top\" : [ {\n \"item\" : {\n \"url\" : \"http://www.seawaytrail.com/\"\n },\n \"count\" : 20\n }, {\n \"item\" : {\n \"url\" : \"http://www.lakestolocks.org/\"\n },\n \"count\" : 19\n }, {\n \"item\" : {\n \"url\" : \"http://www.adirondackscenicbyways.org/byway/adirondack-trail.html\"\n },\n \"count\" : 18\n }, {\n \"item\" : {\n \"url\" : \"http://www.tughill.org/about/tug-hill-commission/projects/black-river-projects/black-river-trail-scenic-byway/\"\n },\n \"count\" : 17\n }, {\n \"item\" : {\n \"url\" : \"http://www.fingerlakes.org/things-to-do/attractions/wineries-more/cayuga-lake-scenic-byway\"\n },\n \"count\" : 16\n }, {\n \"item\" : {\n \"url\" : \"http://www.adirondackscenicbyways.org',0.6083221,'xv',244,4,'1969-07-30 13:43:03.0'), +(NULL,'oo','bbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzKrav5tLL6u7kPIJEtx9OMbmnH4niEPHo7gLFVk2sq28Vv56OHzLLbE+5yWpXbxJv9fwdGPqo4fYI\nxk0kfgbbapFtG26PKWWHQnyTysUy4SL9/rVv8ww/8DdYOqFQ+8O0QnOLZ1Cbn307qEUH9fLUW+ZXKJdIWkyZuMpqyIJ7fkG/Dni2tR4uNAhTde70c/WOx/zBUcYsk5m5jmPxaT3GOwbqwvp9hIkPOtHd1JEeyXqBnsseV1jsyI5Nj8iThpCk9QMIrYwo3uIIcFngJa5r6fu8u36JjhBpkQWhIXq6Bsoe91wmjjpNAXPBLl/M9axZ5HNIIiLjOf2pjLg6ObNLCMh+RKhaW+y5zVegpAFzYjKnIMiOL7vZucQ5XsNZMAuI5izuIr947PeazWgcZvom78QFLiYqdkRTimuCnoQXgtWLAZ4wzuT2EiydSMXXqurGmm3E/Ti58wP0VNpKjehr5yTkUAIIGnNis18L85deUxL8j5PxuB1sMQMUawmOY2T2HnVUAlw3YwYif+abPur9yu4RWAWxRTl5QNQEO1I1BbiwNtOAOffwk55y1M5auYqopghUAtKTIU1n1bBHh8hMxJWhryP8OgwDh0C3rL5bbDruwTmh4DwIU0S949SZdIAPKerzAYtkxjS1k1H5Asa9VXnMwRTNI906ceI5mAyLddzpR1fPapkz2Ox1/FSrK1s/e54mOjtp0dYOMSb0MjXdld7Gi5dkCmOwRlUH7s36/52vVh1nhSev2FI9wRkEnwfBfXBKPi6OAJN5TU+OEV6rxVzqK6XyAKsvak/uBC+i4bvlnWBlKdQEVYMGZN4NzYI2tMOdfO/EHRDMxmSy6gPyCJQtA35FmHXdoRIK1oxgPboUiB439jolHjiNQMMXyY9I+9Y7BkKcwmY+EIB1W8mogzTt2T/AisG2YviONiAbBWmJRF2X63TdbLwysAMYL7AsgaC0YeIGpCEJ8byAwz/ti0nBbuviqUKbdPNhfNGHx0e9Gbc6WgQR2/qSN+5AkHRzK',NULL,'xoob',1,73,'2003-02-05 00:00:00.0'), +(1974,'bxa','',0.2850037,'o',250,NULL,'2034-02-03 15:51:04.0'), +(2003,'akqnhjx','ers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licens',0.8258514,'xak',8,8,'1913-05-18 09:19:37.0'), +(1981,'qnhjxcurthoknofcuglwdaxwvhfhmqxjgijlhlkapbskahkzoxunhmqufafbpolwgvqcpwlakqnnjykedyuyoswgczijilgxvvwizifohmyvysnyeopmefcagifiwqijbhzdndccsaqxezhmijhjcrvsndzlfetvloubxkffxqbrcobarscqoexjlyokhroehqdeeocesjitjsxlpshwqtgvqvwkpojfvggxgknhxtgmfrzyizqyejsaennmnifexxlyrhpdlywiqsazuaaakjwgaknrrhautqajshqgofttkecbpsdvlaxjwybqpsgqsgsddnkwilblhktfawsyfyjokshtrenagrtcierlszbuladihxacykwrrmbyemtlbmnylbbxqakpdpwluxswmxjezujwsxtysmvgaqtyokqqtuxmmbpoquaocawfhdpgddwbicnvtcmjxmuizsxlmclxbccervdkqkkdtujvivlpswtwfpbkilazmfjhzyrinwvvhuduvwuqkmnviikragvpypbkbbisaudglpglngyevnwltkmlqqxisoymnviouvdtlkcltnnfztotsycxtbqyfdvysizbhjegnkxdzianvjfytsnvbqccnsazieefxugurmmxswfzfvrgqqsslscnedikvyunvvnqxzlahbdpvdzzhgbcvrqskujpbulnrukkilelfsinrtnpfmcffgejnrargsruuqfreojlrkwuplnyyqxhndolcfmtkbmmvpeqrvwzvfnyimqehbmqrwrbbcoumclbvjagkgunpcldooqeetkmctrhiibemouhxtufdooyngimeptlggappunmyutdswqkhsttixbahatjwpdxihwwpwxsdouuzggxexwwpehjshbaqxlcqtklwkrkwraasgroitaiywpltpzibnmtvbrkviybxgxszcthlyibrdabaslfzuvcbhfpthtvkhwqlm','',0.4652557,'k',0,4,'1982-07-26 00:00:00.0'), +(2023,'hjxcu',' ??\0}๏ฝพ๏พ‡้„o๏พ”X?)๏ฝฟ?๏ฝณo๏ฝง?fW้“๏ฝพๅฏบ๏ฝบๆฎŠ?+ \r๏ฝพ๏ฝช๏ฝญ๏พ–?๏พ‡Oๆญณ?*๏พ„ใผY$o่ฌ›Z๏ฝ€๏ฝณ??!EF?2 ๏พ–๏ฝญ=่—ท(??๏ฝฎ้ˆทuR?6u็›’q๏ฝค?๏พ“๏ฝฝๅผๅฆ{๏ฝฟl็ญฌ_*KL?๏ฝข/๏ฝฐ๏ฝป๏ฝน?!?caๆ…Š%ๆ˜ฟ??ๅˆ‡่ˆŠ๏พ‘๏พ‚้‚ตI%๏ผฉ๏ฝฝ๏ฝจd?๏พŽ{]\Z#Y๏พ’Ukr+๏ฝญ ๏พ^๏พ’SQU๏พ•๏พmxA๏ฝฆWยง\n?!ๅ…Kๅฉw๏ฝคๆŽขX๏พ˜P๏พ‚ะฎ๏ฝบ#ๆฟ 5ๆผ=๏พ‰X๏ฝนTb๏ฝต๏พŸGๆธฆ?<\Z7ๅถŒ๏ฝฒ๏ฝฒ๏พ„?๏พœ้ถด๏พ ?7๏พ๏พ–?,@!1๏ฝณLK?๏พI&&?๏ฝคไฟฃ?8?8#1>7=T47rRVY^๏พ—?6๏พ„$3(๏ฝก๏พW?8?q๏พžP?๏พ›DEx๏พ€1^้†ฏ#ๅฃ‘Q็ฒ‚๏พ…sๆ™้ฎจ??Sd๏พ็ชฉ?็ถด ๏ฝฆๅˆŠ3h=๏ฝฅ?@โ€˜๏ฝจ๏ฝฐไน™jf๏ฝณ$V?RV๏ฝญ|๏พ•๏พ„็ฅขๅ‡‹?ๅฟ  ้Ÿœ๏พš๏ฝฏ%?[L6xz้†ซM๏พs?u๏ฝฆ$x2๏ฝณ?\"\0?!c๏พ•Q?$่–ฆ?5้คŠV๏พœ๏ฝฌ๏ฝณD\n?k ั‚%๏พ0๏ฝพT่Œ‰๏ฝฝ๏พ…๏พ@?่ฎ“๏ฝซ๏ฝฝ๏พ??M๏ฝจ๏พ–ๆšผ๏ฝก{ๆ‰๏ฝฃ๏พŒ{?:๏ฝน๏ฝจ๏ฝช[๏พ˜๏พ‡๏ฝณ๏ฝตๅ‹บF?[b?#B๏พ›+ๅคœ๏ฝก}=๏พ‰\\๏ฝด?&D?&๏ฝญfIg1,MjZqBๆ•X?%๏พ˜ๅทฝYQkXT?ๆฝบ้ฏ’^!๏ฝฌu๏ฝต8+ไฝปrIj๏ฝฌK[๏ฝนi๏พŒ n{&4i๏ฝข?8j๏ฝตๆณŒๅŠต่ธˆ๏ฝผ๏ฝฐH้ปŽy\Z?๏พ—๏พ่ญ›\'4๏พž็‚ธb๏ฝพ?๏ฝฎๅนน๏ฝฅ๏ฝป.๏ฝท%๏ฝต๏ฝฅ๏ฝปH)@~ๆฟ :๏ฝบ่ณชE[AJHBD8W๏พ’๏พšCX!X๏พ—๏พ‰ Gะบ3๏พ™๏ฝฏr๏พ…? 5?ๆกœ?\0๏ผจt\\?eๆ”ธ2pๆจบ+,?็คบ๏ฝดkrn(eOZ๏พƒ๏ฝขd\"ๆฐธ??๏ฝก#๏พˆT๏พ‹๏พ‡?2W?\r๏ฝถ๏ฝค๏ฝท๏ฝต?\0 ๏ฝธ?(๏ฝผDๆ„ฟJJ4]w\0V็ž>?#่„ฏ)g*็–ผ?.ๅ™ด็›ฃ:๏พ‰@y&>]๏ฝจ(s๏พœyFa็‡GZ\0๏พ‹izM๏ฝฉ๏พž,+๏ฝซ๏พ“๏ฝฑIQJg๏ฝฐQ๏ฝคM\r๏พy#่ฝŸc\n??zฯ‡mE๏ฝฃ๏ฝก|M{๏พ›KrL];ไบ‚q๏ฝถ5?๏ฝด??\Z๏ฝต?I$่ญ˜6hโ”ฐY๏ฝฏ?t้˜?]dd\'่ป\\r๏พ—\\๏ฝญ๏ฝจr6ek๏ฝฆ?$q๏ฝกๆจ0่ฑน๏พ›w๏ฝฅU๏พ™๏ฝคE*๏พŒ8๏ฝนcๅ’’๏พ‹y\0๏พƒ๏ฝต^z๏พ—dy\"๏ฝฝ๏พ–fSEG_๏พˆ๏พ’BaQ?KL๏ฝฃ๏พ—๏ฝช๏ฝญๆ™ฎ3๏พ‹(R๏พ•Nๆœ•?H?๏ฝฐ๏ฝน=O๏พš๏พ”๏ฝป๏พ้ปŽq?๏พƒ๏พ…!ๆฃงๅพด่Šฝ๏พ’?\Z๏พ’??๏ฝค๏ฝตE?๏ฝณV?#{2ไบญ??\n?๏พ็พŒ3๏ฝฌih๏ฝฅๅ‹งn๏พ„๏ฝด????๏ฝณ๏ฝณ\r๏พ—ๆงŒๅญณ๏พ˜โˆฝ๏พš๏ฝคvH๏ฝดZ{~N?5ๆˆช?h๏พ?\0FEd๏พ’๏พŒ๏พŸ?๏พˆNๆ™??๏พœ????๏พ‰?CI่•‰้ฌฃ๏พ›๏ฝง๏พ”C่ณช้œ็žฅ็ธขW๏ฝต๏ฝต๏ฝก๏พ•d๏ฝน@j?0๏พ…ฮฅ๏พ’๏ฝฒEๆฆ‚s่คช่‘ฌ๏พ”๏พš็™’ๅ‡„๏ฝก๏ฝฐ๏พ™ )*๏ฝคiๅˆ†m0ใ€?๏พ“L?H\0๏พ”๏พ‘ๅ ‚๏พž@>\\?OM๏พๅ†ฒ่‡ ่ค‚?๏ฝฌ?L=๏พŒ๏พ†?๏พˆ\r๏ฝท? y๏พ˜!?:๏พ”๏ฝท???=?๏ฝฝ~๏พˆ?่šฃ๏พ˜?๏ฝง#๏พŒ๏ฝดc=V่•ชๅ€๏ฝฌ๏ฝค่’‚็ƒน;๏ฝฒ็ฅ๏พ‚?\0ๆ…“%๏ฝค้ กq๏ฝฆ? ๏พ˜2?\Z๏พ—xo็ฟŠy?๏พˆ?\0?๏ฝป?#Z่ฑ|?๏ฝง๏ฝง๏พ‡??่ผŸ๏พšSWl1\\ใ‚ฒm่ฌ„่™<๏ฝณ๏พ?5๏ฝท๏พ6?GD้‡v๏ฝซ่‹“??่šซg?๏ผฅHDnใดXๅฑ\\ๆฝ}??๏พ’.?;H๏พƒM๏พ™?$X?i[1v๏พ–๏ฝฝ๏ฝฟ้ดƒ็งคD๏พ๏พš็Ÿณ?๏พž๏พŽD?ๆ–›โ™ฏDk%๏พŠ๏พ›๏พ‰4?ๅทฝๅšข๏พ‚X?(๏ฝฉ;ๆš—\0่…†?c ?๏พ“๏พšwM๏พ‹๏ฝฌไป‹Gๆพฑz๏พ‰๏พ‡๏พš,Zๆ‡ฟ3๏พ™?+๏พ‰๏พšV๏ฝฑ<;็ˆ๏พ…\r๏พ๏พ‚5dlๅฎŒ@lVz:?ๆงฟ๏พ•?๏พ•oะฅ๏ฝฝ๏ฝฏE?ๅฒ*?๏พ?๏พ•Us\n๏ฝช๏ฝฉ้ฝ>๏ฝพl?:::::::T??9 ๆทนK๏พ‚๏พœO?;]๏พ‰<ๅฒซ๏ฝง๏พˆ?3๏พ•๏พ:R?๏ฝญ้™ฐ๏พ‡?๏พ„z๏พ€,\n?๏ฝฐ%??Mๅ‘ถ๏พ€<๏ฝฎ?2ๅฃ•๏ฝฉ่•พ๏พ‹?(ๅฅ=K้ค ?๏ฝข\"\"?๏พ‹้†‹#๏พ“๏พ‡๏พๅฎ๏ฝบ?ๆดซ๏พ6G7๏ฝฏ?r๏ฝพn๏ฝต6๏พ–๏ฝผm๏พš?ใƒณ?U๏พ—๏พ ๏พœ๏ฝก๏พ‰1๏ฝถgGx๏พ’c๏พ‹g,\\;่บ™?s๏พ… ?6l?)/O๏พ›ๆญใ‹i\nๅฝฉ?}่—ท?l $๏ฝฟZ๏พŒ๏ฝถF,]7๏ฝฑ)\0๏ฝฑB7P ๏พ็—่ˆถ]?7๏พŽ๏พƒ๏พ†้šจ๏ฝค???\0N~.?vๅฐ…?<8่Š™r๏พ่š“^๏ฝป?9e้šŽ\r๏พ#\0๏ฝฟ๏ฝฉEZo๏ฝก๏พ„)fHdๆผ‚\ZI๏ฝผ 0๏พIo ๏พŽ๏ฝท๏ฝท๏ฝฒ4๏ฝฉ๏พ’XOๅ’๏ฝขi%8I?\"Gไฝฐm๏ฝซ่„‚$$ๅ‹l๏พ‘๏ฝต?๏พ’๏ฝต?$H๏ฝฎz+๏พœ่—\"?Xr0๏พ‚ๆƒŸfๅท–๏ฝฝ6\n๏พ˜\r?๏พŠ๏พ‰,?\r?๏พ‚*็ ’๏พ?่กฟt๏ฝก๏พ‰้ก??๏พžf็ฉ€{๏ฝซ๏ฝจ&๏ฝฒyl$ ๏ฝฃ?2๏ฝฐFV๏ฝฑ\\๏พ‘๏พ๏พ‘๏พ€q ๏พ|Q๏พ‚???,?%ๅ‹น๏พ›๏ผ—I๏พ—็พŒ๏พ†?,๏พ&$?vX็ฌ‚?!@;lN?ๆ ฉP่ฃ•@#๏ฝก้€‹ๅก˜ๆคŽ \r?#๏พ’\"ww?e l้ฆฅ;APฮปๆฅ<๏ฝผ?๏ฝน้ค”๏ฝฉ่Œจ๏ฝฐ?\06?0??R5??;$้ถ\Z๏ฝช่‹บ!๏พ‹?่†ˆ๏พ…๏ฝฝ้ฝ’่‹ž่ฉซ๏พ๏ฝน&๏พŒkl,๏ฝต๏ฝฎ,7่ญ˜$i\Z??ๆคนG้ดป<๏ฝฌ2๏ฝฝ?๏พ—๏ฝญ^?^๏พŸx๏พ‹่ฟฉ๏ฝผ]๏พŒ๏พ๏พŽ่‚ญy\Z?Y.2ๆ€ๆฐพ่•ญPuๆพŽgS=E๏ฝธ็‡ปA็ฌ4O็ซๆ›พ๏พZDs/๏ฝขW๏ฝน?-๏ฝถ๏พ:ๆฐธ7?;?rMๅœฆ?!่ฑŽ๏ฝฌ๏ฝฅๅธฏH)?!๏ฝบJ#(๏ฝฆdๅบ—4?l๏ฝฉ??\nx๏พž๏ฝถๆ”…ๅผ๏ฝฑ๏พ‡c%่—ท ๏ฝฑ๏พๆขขY*Q๏ฝด?DH&๏ฝณ?3ๆกU%?๏ฝฎ๏พœ?๏ฝท?#๏ฝฏzX๏ฝงๆขน:?5X๏ฝฅ๏ฝบ๏ฝถ%YnD?7ๆ˜ถL๏ฝงex๏ฝฃn?๏พŒW็ด‹y่ฅd?๏พ†?_๏ฝฐ๏ฝป็ซกI?8?ๅ†ฒ:*๏พ่ซฑLBV๏ฝญ }dSD๏พˆ_ ๏พ—๏พ‘๏ฝฝ๏พ—๏ฝถ$่‘ฌ๏ฝฑๆกŸ๏พƒ\"9่ฎš๏พ•?Q๏พ‰? ๏พ•Zะ‘j๏พ๏ฝซๅพ˜้กณX*๏พ‡\0ไผ\"gๆนzC๏ฝฃๅญค๏พ„๏ฝคๅ€ถๆ’ญ-?๏พ•o๏ฝญ๏พŒ็ฐ‡3,ไฟธc xy๏ฝคIๅ™EdN?X้ž๏พ‡๏พ…?P้™๏พ‰๏พ;๏ฝณๅฎถE๏พ”?๏ฝทy ๏พ—X$ur๏พŒ?&๏พŒP,๏พŽK?่Žต?\':V๏ฝณ9็š89G;Y๏ฝฐ๏พ„??J๏พœๆธฃbd๏พq๏พ?A4๏ฝฒ\Z?*๏พ‘H0๏ฝฏ๏ฝช?J+่Š\r?$,ๅ‹ž|?๏ฝฏ4?M-?ไบฐ?๏ฝบ๏ฝฝd?๏พ˜9๏ฝนJ3\0?\"๏พˆ?8l .P๏พŸgP๏พ„๏พ’H{๏พ†ๅ’๏ฝพ( {๏พŸ$๏พˆ๏พ—ๆ”ปH~่ŠF๏ฝช๏ฝธ.๏พ‰ =๏ฝฅ๏พ€๏พŽ๏ฝฆ๏พ–\\๏พ“๏พ—k?-็›๏ฝฐ่ด9^้„๏พJๆฎฒ?\0๏ฝณ็ฒพ?l&$๏พ‹๏พ“-&่ฟน๏ฝถ๏พa่จ“C๏พ†-?1mJ?;A๏พšC?ะ‘+๏ฝค)o๏ฝซ]mVnh่ข’๏พ†+้‡ฆEx๏ฝพ a๏พšๆผฌ๏พ‰In)#๏ฝฆ็ฑ?๏พ…๏พ‰?!<5่œฅ7jq๏พeๅ”ณ๏ฝก* ๏ฝฆJ? i๏พ›$ul๏พ“K็ฉด๏ฝผ๏ฝฑX๏ฝน%ๆ€ฑ่ฟฝ?eๆถ“๏พ“๏ฝฌm๏พ–:Dp๏ฝธโ™‚๏พ™WieDๆœทY๏ฝจ๏พ‹๏พ‰๏ฝคn3P็ฐ๏ฝพ๏พ’Tๅ“Sv๏พ‚h๏ฝต$่ชฅ๏พŠ๏ฝถ\"W?ๆ„ฟz?x?;Ye๏พ‰\Z๏ฝซ๏พ•๏ฝฎkl]?g\'๏ฝฒ๏พŠs??O๏พ‹|๏พŠ9๏ฝซh?G๏ฝฅ๏ฝฉ๏พ™??๏ฝถ?? ๏ฝพๅ‹็ผ\nQ\'๏ฝด]nๅŸ๏พ–t๏ฝณ?,2J๏พ”Ww๏พ๏พjy?/๏พ‡1?(e๏พœ _3g๏ฝข๏ฝญๅ‰ฉaC๏ฝฃ.๏พ‚๏พ€๏ฝฉ๏พ˜y-็›ด{Ai๏พ?๏พ›X๏ฝณ้ผA่‡บ\r??ไบซ6๏ฝฅ??p๏พ™๏พŒ๏ฝซi๏ฝถ?m้‹ฒ*E}L ่ธช๏พ™UPV้™Ÿ๏ฝด\"!D๏ฝน๏ฝถ\0?\n0X๏พ‰๏ฝขEs็ธ’H๏พ‰^๏ฝฒ=็ฉฐB๏พ…c?๏พE๏ฝพ๏ฝต๏พ›0[?.๏พ๏ฝฌ}ๆ„ผ๏พ“้›ซ็พฏ#๏ฝด?;2๏พˆHe่˜l$(]iZ;่ผ?\'็™พ)5XmW?l๏พ•๏ฝฟ*gๆœฌ0๏พŒbw่‡ฅ?8f\r๏พŠ>?,๏พ„๏ฝจ?5๏พ–?g?ๅ‰ช?:;ๆŸฏๆƒ‘[\\?๏พŽ่…rWm{[9?(?2?ๅ 8?c?n๏พ“้™บ=๏ฝจ๏ฝค๏ฝพCN๏ฝจe5่ผK%๏ฝฒ๏พˆ๏พ˜q?๏ฝจๅญ?๏ฝต=I้งขๅฅ‰๏พ•G9?b?๏พŸ?*๏ฝช5~Uz๏พšg??/๏ฝจ๏ฝทk?๏พ™๏ฝข๏พ€.ๆฑณ?w<่ŠนG\'X=+?่ณฃ๏พ•-vๅฝผ>?x่žซ๏พ›ๆฝ”X๏ฝซ๏ฝบ๏พ˜๏ฝก? ?=r?๏ฝฐๅ–ฎ\Z๏ฝท.๏ฝซO๏ฝฆ๏ฝต>๏ฝข๏พ˜2k๏ฝญ๏ฝช๏พŒ*๏ฝพ๏พa?B๏ฝฑ ๅˆง03!๏ฝฌ?๏พ…?7้ฎซ๏ฝต๏ฝฒCV๏ฝพๅ…‰r๏ฝญ~[C็จฟj๏ฝซ๏พ’&\\P?!?๏ฝฒN?=๏พ‘*๏พˆ???0m? m*0๏พœ่ปขๆธฉ>๏ฝฏIN?๏ฝฐVYu๏ฝณWg?*rV?๏พ”? ๅงซS-c?<๏พ›P3้ ค5-.r๏พ”?H].๏ฝก๏ฝฒ๏พœc??ๅž *h0?๏พ?Yo?็ญ‹?g๏ฝช้ญŽ?๏พ•?่•พๅฅชไฝฟ}้†ด๏ฝบ๏พ๏พ‡?6๏พ…\\๏พ˜h๏พ‡ๆฃ g9e?5?B๏พi๏ฝฐๅ‹…๏พ”2๏พ“?|H=t๏พ4qf\r\n?๏พšlN? ?!ๆˆ–๏ฝบๆข—\Z๏ฝญ/๏พ“๏พ‰I,๏ฝข๏พ˜่ณ›pC๏พ‚๏พ„J๏ฝฒV1?2?<;7๏ฝฑโˆฝg?rMZ?๏ฝฏd๏พ~Hๅณ่›น๏ฝค\\PH??2๏ฝณr๏พ…๏พ—nO?UๆˆŒRk7}?๏ฝซๆ†๏ฝถๆ‚’๏พŽ๏ฝค็ดฟ่ก†[F^๏พŸ็šด้‘ ๏พ‰9j๏ฝฉ4W6 K๏ฝฟ๏พœ๏พ™Vใ€†ๅ‰ฑ9๏ฝฐ๏พŠ*๏พ—๏พhM0๏ฝณ๏พ‹6}๏ฝซe4w๏พ‚u๏ฝฝ๏ฝบn??9 {c๏พƒq๏พ„๏ฝฃA๏ฝช๏พ๏พ๏ฝน๏ฝผ๏ฝณไผ๏พ„?~๏ฝขC?(\r๏ฝจk?๏พu?๏พ‹?y๏พŽU?\"F ?C\rCๅ‚‘๏พ–ๅ“จ?๏พƒ้ญŽRU๏พ•K]A๏ฝก๏ฝผ้ŠƒANC๏ฝดๅ–™๏ฝซR๏พ†dA๏พ‡๏พ“\\๏พŠ๏พ‚46๏พ€๏พƒ้ƒ?5\rIJ๏พ‰?i๏พ๏ฝจ4?4๏ฝฏX๏พ€Q๏ฝฑ๏ฝชl8?W๏ฝข่…ธYZ๏พV3Wๅด๏พ’Wๆท‘dv}๏พ‡aBp๏ฝฑYs?๏พ‹ๆด™๏ฝฃ^๏พŠZๆŒŸ?(z๏พ•e๏ฝช่œš๏พ–/??L๏พ ?่•Š๏ฝฌๆ‰‡?b?\Z๏พ€?\Z|?้กดq็ฒฒ??๏ฝก?&๏ฝธJ๏ฝป๏ฝฉ?>K๏ฝฌr?ๆ‹ถ\"\"\'ๆŠซ?y\"๏พ‰ ไฝฏ้นน??m๏พˆใบ%.r๏ฝบ๏พˆ๏ฝฒ๏พŒGm๏ฝญ๏ฝผๅฏ›b๏พ…๏พGS\\๏พ›ๆŸ”๏พ•C?F๏พ็—ฒ,๏พŒๆ›พ<๏ฝช๏พœHl็‘ฏๅฎrt<_้ ’๏ฝคS็ฏ๏พ™?๏พ‹๏ฝธ๏ฝญ๏ฝณโˆ‚V๏พŽ่œœ?)r\0?\n๏พŽ๏พ‘?๏พ‰b?,?๏พ‡??ๆ€™๏พŸ๏พ‰ๅพฉ]SuKs๏พŒ?ๆจ’ๅกขk ?)q?4?G?0yฮฃ&ๆฟก[FH??\0๏พ•\"s้ฏ”ๆ น๏ฝฑC?๏พ๏พš?\0๏พ’๏ฝบ๏ฝธs๏ฝง๏ฝช็พ†๏พ็ฝตะšb๏พ•(#๏ฝฝ6A๏ฝซ๏พ‹%x้ฃฝ๏ฝญ?h$w\nL?}๏พŠ/-?5๏พ“Dzๆ›œ๏พ˜๏พŽ๏พ›๏ฝฟ^ZI\\้‰ขe๏ฝฌVJ1N๏พ๏พ+i๏ฝฌQ? J$๏ฝณ๏ฝธd็ญฎ๏ฝง๏ฝฆ๏พ๏พŠ|yG๏ฝบ่–‡b๏พ‚?\0-ๆบบ๏ฝพ่“L๏พˆ? ๅฏคl๏ฝญ?๏พ๏ฝฅๅฏฉ^<็›_-๏ฝฐ๏พ˜h่ฟš๏พ‡W๏พ„b?t%? ?ไป–??้ถ๏ฝท๏พˆq? \\?em?๏ฝฌ?KoW๏ฝผ๏พŽ๏พ}cAv ๏ฝฃ?3?!๏ฝด๏ฝฆC ๏พŸt๏พ™ ๏ฝฐๅธธ๏พš๏ฝซ#๏พ“๏ฝง-๏พ๏ฝฏp?\"_r๏ฝท%XD8E?1็œฅ๏ฝญๅนŒTiPVN๏พ‹?๏พŒ!๏พ‰!๏พ•?Ia\n[้จ&Ll็ฅท๏พ™\":)ะณ=๏พŒ?็„”๏ฝณ?;N???+P-gwQMU๏พœ๏พ‡๏ฝถ๏ฝธX๏พƒ๏ฝฌd๏ฝป๏ฝฉ๏พ‹\\8๏พ๏ฝฝb\ZAy๏ฝฏBtใจ?2๏ฝญ๏ผตP๏พƒ ๏ฝฑD๏พŒ?6m?,n\n?็ฎ‡%ฮบK#๏ฝถ๏พ—๏ฝง0ZrF(๏ฝฌ๏พ›-??\"่ฒฌ?*?๏พŒ๏ฝฐ๏พŠ/๏พ‹๏ฝข๏ฝจ?R1E8๏ฝขO?๏ฝปs]/dๆ’ผ?/2Gy๏พƒ?7้ถšh??ๆฌ??h๏พ‰bE4H5X๏ฝฟn:76\".??8???.๏พ—1๏พšO)jD|๏ฝฟPU๏ฝปbN๏พ„v๏ฝฎr9d็ฏ‰๏ฝฑ๏พ‹3๏พ”w??n๏ฝฑ?๏ฝก๏ฝคb7?้ ค้ŽŒmKๅฐ8็ต–xy๏ฝซ๏พ ็ฟŒ๏ฝณ=c\Z๏ฝฏp๏ฝฌBrW?j๏พ„<๏ฝฏ้…ฉ้ฃ›?N?/๏ฝซ๏พ‚?๏พ‚\"\'่ฌฌDETDo๏ฝฉU|\"\'็ฒง๏พ‚?ๆฒปDlv?\0N๏ฝฏ?TjlI๏ฝฉ8;่ˆฉEะซ%?#<#?0?ๆ˜จ๏ฝชๆผข??๏ฝข๏ฝง๏พ‚๏ฝง?๏ฝฒๅ‡งW?E?5EN่‹ฃ\0jg๏ฝฐI๏พ„๏ผฆ?๏ฝฐvN3๏พ0?,##๏ฝฝlz๏พ‰bV9๏ฝฉ?-๏พ…q๏ฝฉ???\0๏พš๏ฝง??\0ๆญฏn\'่š“Oh\"๏ฝฝ๏พŽๆ›ฐ?\0๏ฝถh๏พ‰y๏ฝพ๏พ๏พ“F๏ฝฑ๏ฝต๏ฝซ่ฅท\"H๏พŸ(่†‚๏พš?ๆธฌๅ–š?I๏พ„้ž‹{๏พ? ็”ฃ?๏พ„๏ฝฆj่…ฟ1๏พ•๏พŠๆฟ†?็ดฒY๏พ›?b๏พŽ๏พ›๏ฝถ๏พ„4๏พ‹ๆ˜”KJ9๏ฝชc๏ฝค๏ฝฒDEไฟพ?๏พ‰๏ฝข๏ฝดq๏พˆ#<๏พˆ7, ๏ฝงๆ…ถbK็žฌ๏ฝฟXๆญข)??)k๏ฝญ?Cy\n๏ฝนC\Z*Z3๏ฝฒๅˆถ๏ฝจ๏ฝฒ๏พ›๏พšๅพ‘?๏พ.?๏พ๏พ‹2๏ฝข๏ฝดv็€งๅปทๅ‡ช*\0cL.??่Žจ?3S๏ฝก?xM็‡ง?๏พŸb๏ฝฉ)?๏ฝฅ๏พ‡6bU๏ฝญ็บœ๏พ†? ๏ฝน}๏ฝด่‰๏ฝป๏ฝถ gJtLH44?X\"?๏ฝฆx๏พ˜??H๏ฝญ๏ฝช่†ˆ~ๅฃ™[0๏ฝถ้ผ ๆ€ฅ๏พŠ๏พŸ?๏พ–A\\%๏พŒV?=e\rๆ‚งIa๏ฝค๏พ‹ใ† F็ตž๏พž๏พ€๏พ‹ๆŽง?Dๅš€m๏ฝปd่ณ?+๏ฝด๏ฝน็ฎ’ๆพน?N๏พ–๏พ›๏ฝป๏พใƒ„q๏พŒ=๏พ€๏พŸ๏พ•๏พ˜็คช- ๏พ’yd>๏พˆ~๏พŽ่ฑธๆจ…[\Z๏พšd๏ฝค?๏ผˆๆฟ†็™จ๏พ–\n?\r9๏ฝฆ?%v&[?๏พ‹ๆนฏR??7?๏ฝฉ@๏ฝฒ\Z๏ฝฌ?๏พ’\"%็‰™็พ*?๏พ†^?๏พ€ๆง? B$H?(?๏พ—๏ฝท$๏ฝฑ?;E2ๅกž%๏พ™๏ฝฝ๏พ„n7=5๏พˆ๏ฝฐ.๏ฝฝ่ฃ„9๏ฝณ?ๆผธ่‡พt่ฆ“]k๏พ‰็ด๏พœj๏ฝน?๏พ›ใ‹๏ฝณyb%W?A๏ฝง.๏พ‚๏พr๏พ๏พŒ๏พ’๏ฝฏ๏ฝบ๏พ‹$๏ฝฒ๏พ‘?7]ๅคฒ?๏พ€๏พ๏ฝบ?1ๆฅขs\n?cp๏ฝฝ๏ฝบf๏ฝฌsๅ…ช/m.่Ÿ‡๏ฝณ๏ฝง่ฌn.ๆฅท๏ฝถ+f้ท‚n๏ฝพ๏พš?\0?๏ฝฆs.\n2<\n?3\'โˆฝ๏พŽ??Tๆ„๏พ‹?h??W๏ฝฎ๏พ“.?๏พœZT๏ฝณ๏ฝค๏พ nA๏พ‹๏ฝถ4๏ฝฃ\"๏พ€๏พš๏พ๏พ’Wๆ‹ฎEh๏พ–?;H\'๏ฝกๅ€…็—‚๏ฝต?p?5q?;ใƒœt๏พZv็ฟŠ๏พ?๏ฝฉ๏ฝด๏พ—9๏ฝซ๏ฝก3๏พ™z่น„็ถด?T:?๏พŒU?Z๏พ˜deๆธฉ6่œทq JD๏พ…K๏ฝฉ๏พ—2๏พƒๆšฆ๏พ—็ธซ็ t๏ฝซ๏ฝด๏ฝฐ๏พ‰M_^Icx)๏ฝฉU?๏ฝนy๏พˆ ๏ฝทjJๆ–Ÿ๏พ”Ndๆ‡ธ?>ๅ…ธ_๏ฝจn๏ฝญ8R{ๅœง๏พ ้Œ†$?๏พ—้ฎญ๏ฝฐ?b????๏ฝง๏พ”cๅž‚๏พ็‘•k$? 5\r/๏พ๏พžXQ๏ฝŠ๏พ8%่ฒง๏ฝณE๏พˆไบฆ๏พ€v?a\n?๏พ›?9ๆฑ‚๏พ“W+?\"x?๏พ˜@?,๏ฝฎ?g#๏พ•R?\nJa๏พ…๏ฝฌ๏ฝณZKK๏ฝข้– ?*๏ฝฟ๏ฝน*๏พŽ๏พ’๏พ˜{/M}pๅก็ˆ›๏ฝป๏ฝช๏ฝผ๏ฝฝ๏ฝท๏ฝถ%lep๏พ„?+gH:}Y๏ฝฝg๏พ„u\Z^๏พŸ?:,๏พ๏พ‡,\Z?๏พ‹?๏พœr?๏พ„ๆˆฒ๏ฝท๏พ๏ฝค?๏ฝพ๏ฝฟ?5?๏ฝฉ5e ?rvh๏ฝขI? ?ใ‚‚?.๏พš?๏ฝซ?|ๆต™็ฝง๏พ™ds?bk?ๅนขK๏ฝง่Š’v?&??\0๏พ“\\j๏ฝป)CZ&}็‰†? ็ฏท-E๏ฝป๏พ†ใœd??๏ฝบๆฅ”Xๅ™>ๅŽญ็˜Ÿ๏ฝข\Z#?3-ๆ‚ŸZ๏พ“่ฌ‡F๏พŸ?๏ฝบ่บ๏พ“ac๏พ”Iๅ‡‹i๏ฝข|?้Œจ่…‘?9ๅ‹˜ๅญฃ?+๏ฝธ๏ฝถY๏ฝฅ๏พžQhs{็šฟ๏ฝฌ๏พ…๏พ‰rsg๏ฝง๏ฝถ0?ๆตธl๏ฝฐg๏พˆ๏พƒ๏ฝข6๏ฝค๏พŠ๏พ˜\\kQ่‰8R๏ฝฌ?!:WQ๏ฝพ๏ฝฉ?7๏พ’ๆจŸ๏ฝบ๏พ‹?๏ฝน!K?? ?๏ฝฒ๏ฝฝ!|๏ฝจ้„r!๏พŒ\Z๏ฝฝ}๏พ‡ (?๏ฝนYๅตŒๆค„่—๏พ›่ทณ\0๏ฝฉ@Y่ฒžA\'z6R?๏พ–/๏พ“๏พ\Z4๏ฝฌๅท?##{Mๅฌพ๏ฝบK๏พ“?$๏ฝกX๏ฝพ?/=xjXD]?๏ฝป๏พŠ๏ฝฃ?็ตฎ?ๅƒT^Q๏พ†๏ฝฆ>๏ฝด?=~|D?\'่ฌฌDUWxO>|๏ฝซ๏พŠ๏ฝง?U?้Ÿ‹zx_??\0?I๏พ›๏พ‡??P?๏ฝธ?\0?๏ฝบ้ฐŠ(่–€??๏ฝฏ?้ผˆๅ–ฐ๏ฝฉ้…ฉ?~:็ฝ?็†•pv?๏ฝท?uS๏ฝฏ๏ฝถ๏ฝฐ๏ฝฌ> Ip๏ฝฆ:O5ๆ˜‚J๏พ—๏ฝค๏ฝญTj3๏พ‘?$j/๏ฝกZ๏ฝฌT?๏ฝช๏พŸO๏พ‡O?yX?็ง‹๏พŸ๏ฝถ๏ฝพ๏พš\Z[๏ฝธ๏ฝขSๆป๏พ„K้ญ…~๏พ’S]?\'?\'??I}๏พ™๏พ˜๏พ„่ณŠF๏ฝฑ<๏พ‘U>????\0h๏ฝฝz๏ฝฒG๏ฝต=H๏ฝชไธ”?J๏ฝฑ=/o?+<|?๏พƒ๏ฝผ||?? ๏ฝฝ๏พ“๏พš?#๏ฝฆ??efZ๏ฝถ๏ฝซ๏พ™ๆŸฑ๏ฝฌ๏พJ่ป›Dn๏พๅฃปไธถT๏ฝช;#๏ฝดM๏พ…๏พ“fU#AๆธพไฝปERj๏พ—๏ฝกA3๏พ‚?u#_๏ฝช๏ฝซ๏พx่žบ_๏ฝพ๏พ๏พ•?0WVeo?>ๆ—?!C๏พ!i?๏ฝฏ?#๏ฝพ~n???e๏พ‰?0??%?=?ๅ†ถEjE+๏ฝฆWF#่ƒฏU!|๏พƒ๏ฝดzn>ๆฏ˜ๆฎฑ9๏ฝฆ๏พž๏พˆ?๏ฝฉ?c5\"็Œถ\r]?ไป็ณŸ?C๏พœD่ค‡็š‡:\n็บ‚็นฆ๏ฝฌr็ถข?๏พŸ?1?s?๏พˆ7๏ฝฎ๏ฝฎ?&?๏พ‚ไผ้‰„?ๅฅงKqKๆ–ญ๏พ›?้€ข๏ฝซc?๏ฝต,? *E2๏พ„๏พ‰%??<7๏พ•\\๏พ‘๏พˆe\\?+?๏พ‘er๏พ‹>N\r<๏ฝค๏พ•๏ฝฒ๏พ†๏ฝฃ[Cv?6SN?๏ฝญP ้ค?็•ฐ??0\Z?\0O่’ก[9K?=๏พ™f?mD๏พ‹^#;?ๆ˜”๏พ’?$ๆŒ‡p๏ฝช_?๏ฝขK่„Š:? \\dBHaH่ฑน๏ฝฐ*๏ฝฏwโ”ฃ๏ฝฐ๏ฝญ?่–ฆ!Sๅ‹ ๏ฝฑ๏ฝธ๏ฝฝ๏ฝพ๏พ‡@ ?k๏พ‚65T๏พ•๏พ‰ n~{Y๏ฝฐ๏ฝต[ 3ๆฟƒm|?ๅฃ˜?F?\0ๅ„•E๏ฝฐ&๏ฝฅ=ๆธฌ\\?N#)๏ฝด๏พ็กผ8\'_[๏พžVO+ๅŠฑ?#?w%s?๏ฝฝ?๏พ๏ฝต?๏ฝค?่ช˜-๏พž๏ฝดB๏พ ๏ฝบ๏พˆๅฑ‹ๆฉKE \0ๅขจ??-?๏พ˜\r?้ฉข๏พ€&๏ฝณX๏พ‰r่†จ๏ฝฌ๏ฝฃ๏พ›[<๏พๆซบ#Y็•ฅ;>}?๏พƒ:ๅ•†?๏พ› ?7??\"F>U????;?iไบˆ^+4\r๏พŽ็ง˜4r8\\๏พž6?๏ฝณU!๏พ“๏พ‹_๏ฝฅ๏ฝปm\r๏ฝซ%๏ฝฟ๏ฝด\\๏ฝฝ็ฐฟ\\๏ฝฑb๏ฝกX๏พ‹lrKZ๏ฝกๆฐ“ๆ“ก๏ฝฆ?e๏พ‡๏ฝณ-j?๏พ˜?0wZ+๏พ…)8่’?่ณค๏ฝฒ?&w?^็”˜628๏ฝญ๏ฝก2๏ฝฝ?!N?3๏ฝณJR!&?b.?\"zๅ™ด?0b?๏ฝฃ?๏พ™?ๅ“‰่˜‚๏ฝฅ๏ฝฉ็ผบ๏พ„ๆฑพ?r๏พ–\0m๏ฝด๏พ?7\"X๏พ•:๏ฝฌ๏ฝช๏พœT?*sWOaๆจ—๏พ™H?็ข3ๅผ๏พƒdv็”‘๏พž?97?rd๏ฝนB?/(?4m๏พ‘?7?3X]๏พŸ$๏พ™<7d๏ฝธ๏ฝฉ๏พ“ๆŒฏๆงฝg?5๏ฝค่‡“<&1 Y๏ฝฃ้จ’๏ฝน+๏พ‰S?)o+x_ๆ’ฒx?๏ฝฆ็šธ[\ZA-4S๏พ’?^๏ฝถๆฉฆใ€ƒ?;?:+\Z?|ไฟฎ~h4๏พ“+,\'??C+๏ฝฝ๏พšw็ต›๏พ‚<๏พš๏ฝฆ้ ƒ?๏พ—c?t๏ฝธKh?qix๏พŸMg?้ฌผY ?๏ฝต๏ฝฒ๏ฝฏ\'๏พ˜๏ฝธ๏ฝฏ๏ฝซ๏ฝซ๏ฝฎ๏ฝณ?\0cK?;x๏พ‰!?๏ฝฒP๏พžๆฃฏT?๏ฝฏzq็ฅจ๏ฝถ+๏พ?4๏ฝฃy๏พ–๏พ€๏ฝฌ?\ZGe\\e0!๏พ๏พ‚ใ‚‡Pใƒผj๏ฝช4v๏ฝฑ?g๏ฝธๅง†-?/p๏ฝถ#,๏พ‚?<๏ฝถ๏พŽ6*#?K๏ฝฏ+?h๏พ๏พ๏พœ?~๏ฝป๏ฝญ๏พ‚๏พ“่ฉ๏พˆ?3๏ฝตXH?x๏ฝฒ๏พ“}T๏ฝฆT้บพ๏ฝญ๏พ•ๆˆฏ[T2[๏พ†๏ฝณ]๏พ”5?b๏พœ+๏พ˜?่„ฑ\'่ผฉCๆŸป๏ฝฆ๏พ›๏พ‡๏ฝบๅ†…p{N>^A๏พ‘a)uV:๏พŠ๏ฝช๏ฝญ<่ˆตQ๏พ‡ๅฟค*๏ฝบๆ‚›๏ฝฏ๏ฝฌ?๏พš?,๏พši๏ฝช*\'H\\ๆฟ‚$k๏พŸ๏ฝด๏พp่ฅฆ๏พž;??? ?y๏ฝฟ๏ฝน?๏พ‡้‡๏ฝก?#๏พ…๏พ•\"๏ฝธe๏พ“G!๏ฝด%D?/?๏ฝฃ?x1ๆšฎUg]{Mๅป๏พš่ทj*ๆขฆmๅฉช$o่พฟIp$ะ‘,่‚ข๏ฝผ?ๅฌ1๏ฝค๏ฝธ?!?_4๏ฝช?Z๏พŽ๏พ–็ทฌ็พˆ๏พš)h??$D๏ฝถ๏ฝช๏พŠ๏พ“+y๏พ‘๏พˆ $๏ฝญ๏ฝณ%้ผกI3EZXๆ†ง๏พ„๏ฝฒ๏พ€?h๏พ–๏ฝฅ[V๏พY๏พŒ๏ฝฒglv?w+!๏ฝฉh๏ฝฅ้ณฅ)๏ฝณ๏พ?#pvv๏พ˜?fEUTU_?Q|x?๏ฝช?ๆกŽUS๏พŠ?os\"xT??\'?Q???๏พ๏พŽ๏พ„?ๆธˆ??๏ฝฟๅบŠ?|?\' ?;๏พŸ???๏ฝฃ๏ฝฃ๏ฝฃ๏ฝฏ:::?S??\0I???๏พ‡\\tttu๏พ๏ฝฏsQZ่ฑZ่–คkW๏พŠ๏ฝท๏พ?>Q๏ฝบ?๏พ‚?E?;{???|??#]่›ฌ~W๏พŠ/?\'๏ฝฉ๏พž?/?7๏พŠ?:??>F๏พ‡๏พˆ\0?๏ฝฃ๏ฝซ๏พ›5๏ฝพ๏พ™e?๏พ’ๆ‹พd!u๏ฝฉ4Aๅ›ƒx๏พ‡้ฉ๏ฝฑ๏ฝณ๏ฝฒ๏ฝงY!้ 5๏ฝญl็ฐก๏พš๏ฝฎ??jt๏ฝฌ๏พ›?1๏พ‰่ฆ?I?\Z๏ฝซMๅœป\Z้ญ…Gๆšพ๏พœ??@่ถ?zr?e\"๏พ๏ฝฏ5ะธๅฌฐF5A.ไธ™๏ฝข๏ฝช\'ๅŸŽ?\'??๏พŸ๏พ›๏ฝฎ๏พ‰#ๅธ™๏พ‡???๏ฝฌ??๏พ“??๏พŠ๏ฝง๏พ‚?๏ฝฐ?+่ณŠ]?v๏พœu่‹Ÿ&hR๏พ„?~><&?๏พ‰๏พœN +?\0๏พ˜:??>/e๏พ–Y้ž…่„ฑR??9C?๏พ“?>wB๏พ…?AK\'n]??[C๏พ„๏พ™lx\\Y๏พƒGC๏ฝญ๏ฝฐ๏ฝถ?a๏ฝฒ*๏พŽ๏ฝณI๏ฝฟa๏พ•\r ้บ‘ๆฎบ่ตญ?=?(1๏พ“Azt?1(๏พ“๏พ™YLE๏พ‰๏พˆP?๏พž๏ฝช๏ฝพa๏พŠ๏ฝจ็นป๏ฝต๏พ–๏พ€?6๏พˆ_]๏ฝบ่ดŠ?๏ฝฒ๏พ™้Ÿ‹*6 ๏ฝฝ๏พžๆŠปๅŠตๆ™~๏พž๏ฝธ?\'๏พ‘P็ฆฎ?R?65ๅๆฟ ่™ง็ฟEsๅ€ก~๏พ•EO๏พœ้ผ๏ฝฎ?๏ฝป๏พ๏พ”_(๏พ”D?๏พ’๏พ„?๏พ–9?็ซœ๏พƒ\\ๅŸ๏พๅฆŠ?D?ๅปŸ*๏ฝพUUU้ฎช๏ฝฝ๏พ”? gK\r\rไพญZdV?็†ŠP,Q๏พˆyK?mGzc๏พœ?;?.่ˆฉN\"?๏ฝช=gh๏ฝธ/jI8sw?+1?2ๆ—Y๏พ‹?]้ž?(.๏พž?๏ฝฟไฝ๏พŒ?%\\้?::FNn??\0๏ฝฐ๏พ“ๆถ›4c?,R\n๏พ™GX๏ฝฝ็ง•$๏ฝฑ๏พŒ?cTIF)๏ฝฎ{_๏พ?6๏ฝน๏พ‹#Xๆก?๏พ“๏พ•?4qCfๆ…ด?\'ๅ†ฅ๏ฝช๏พˆ๏พˆ\0๏ฝซ่ฒž่—๏ฝฒQ๏พ…@ๆฏ๏ฝก๏ฝง้‰„็”จ\"๏ฝท้‹บ?y(#nj็“ง๏ฝฐ๏พŸ๏พ‚๏ฝฉ lH;y?9๏พ‡s ๏ฝณ๏ฝฅ๏ฝซ\0?0??๏พ‰๏ฝฏ,?j*).?9K๏ฝต๏ฝง๏ฝต?๏พ˜?ๅบๆฃš้ปน๏ฝธ??<*๏พŸ.่ฒฟ]}๏พœ0ๅŒธ๏ฝฟ&W\\้‚„??ๆ‰ž)72๏ฝฝ่ฉฎ(r๏พŠ?E?)b|qC<่˜#ๅฃ•๏พž๏ฝฑ}๏ฝฎ?c!clM?4u=??L็ขฉๆœบ๏ฝต?p3?๏พˆ๏ฝฆๆ$j๏ฝง๏ฝขifG๏พŽ้Žš๏พ–๏ฝซo\r|๏ฝฒZ๏พ•๏พ“4?๏ฝฌ-๏ฝฌ็ตตY}๏พ„็ธฆ ๆฃ’*๏พ•$ไธผ๏ผง1?*๏ฝป๏พ€n?*๏ฝฏ๏ฝฉ?#S+๏ฝฎ?{o:๏ฝฌ๏พ‘ Ll็ฃ”?*๏พŠ๏พœั†Q?\0???ๆ•ฆo็ปไน˜๏ฝฝ๏ฝซ๏ฝญ?่ซก๏พๆฎซU\"el$๏ฝฑ็ธท๏พ๏พ‡ๅ†™/๏พš๏ฝฌv่ฒฟ%็ฒ?zๅ•พ๏ฝฏ๏ฝตVgJ๏ฝญๆญฏ?๏ฝถ๏พ‰^?2๏ฝพ?ๆฏ˜?๏พ›k?๏พ†a็ญ–40๏ฝฆX็ธฒtr๏ฝฃaIQ๏ฝฉ7ไฟฎX๏พ…F๏พˆ๏พ–z\Zๅญ๏ฝง?n๏พz๏ฝน๏พž๏ฝฅr๏ฝฝ๏พŠๅฅ๏พŽ?*๏ฝช๏ฝช๏ฝฟ?๏พ•U|??_>~z?ๆฏ๏พž7Q็คฆ๏พ’?5<\\?๏ฝต)s๏ฝฐ๏ฝทrq๏พ–_?๏พ–\"AV๏ฝผrๅ ค?${\0/uG๏พ•๏ฝฃ๏พ“๏พŸKli๏ฝผ๏ฝช?๏พ•๏ฝต๏ฝฑ่™ซ๏ฝฉ?Hๆ˜ƒ*2p๏ฝฑ/6D?4่›ธ๏ฝจd?็ธ}?้–‘F9๏พ„?๏ฝพ>๏พŠ๏ฝฏ??>|?\0่—?้ฝ๏ฝข๏ฝช๏ฝฏ๏พŠ๏ฝฏ???๏พ”๏ฝซOGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\\๏ฝฃ?๏พ‚~???\0่ป†?็”ฆ็ฟ•๏ฝผyO ??>>?้ž?>็•๏ฝฃ๏ฝฃ๏ฝฃ๏ฝฃ๏ฝฎ}oO๏ฝน~๏พŠ??\0H? ??\"*|*/้†‹#๏ฝฟ?๏พ‡?S๏ฝฃ๏ฝฃ๏ฝฏw?๏ฝน?้€Ž๏ฝก่†‚ ็ฟฉ??-_๏พ‡?S?\0ๆป‚?้…Šu๏พŠ๏พˆ่—UT?๏ฝข5๏ฝจ??(่กฃ?๏พ‡GGF้Šท?|?๏ฝฟo??>::็นs๏ฝฟ๏พ”๏ฝฟๆธ‰\"\"\"~W๏พ‚5่›ž\"\'๏พ‡็พ‚๏ฝช๏ฝพ๏ฝท?\"\'?ttu่น GGGGGG_?๏พ™?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Exif\0\0MM\0*\0\0\0\0\0\0\0\0\0?๏พ›\0C\0?๏พ›\0C?๏พ€\0\0x\0?\"\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \n ?๏พ„\07\0\0\0\0\0! 1\"\nAQ$2a?q#B่ดˆ้Žฎ๏พ‘?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\05\0\0\0\0\0\0!\"1A#2Qa3?$q๏ฝฑ?CRb???๏พš\0 \0\0?\0๏พ—?\0๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ—๏ฝผP๏ฝฌ่ณ€FH?\0l~ๅนŒ?๏พ‹?๏พž๏พ›๏พš๏พ…s้€€=J๏ฝซ\'็ฟ’Z?๏พN๏พ‡๏พƒ๏ฝต?\Z?Z]๏ฝฅ_3๏ฝท๏พž๏ฝธโˆž๏พŒๆ•ˆ uๅ›ฐ๏ฝท๏ฝฌๅธฏ1M๏พ…gb๏ฝญ^๏พ‰๏ฝจ้ƒข *๏พ*\r?9๏ฝข้‚ช๏พœ๏ฝฆ@}๏พ€?้…ฒ\0ๆฟค?^3*๏ฝซ3๏ฝช?O?~๏พŸ>H?\0๏พ‡๏พ‡?A#้ต™_|y_ๅฑ๏ฝช\"y?7๏พ‡๏พ‡?O๏พ—่‚…๏ฝฎ?๏ฝป๏พ“?๏พ”z?Es??้ฅ•๏พˆ?/๏พ‡๏พŒk?~U:๏พ™K๏พš๏ฝฟ??>xz๏พ–๏ฝค?๏พ‘r?{p&๏ฝญไธธ }๏พ”\\)๏พƒ๏ฝฐ?$๏พŒj?m๏พ‹๏พˆ๏ฝค ๏พŸ#๏ฝขY?๏ฝฐ๏พ๏พo7$๏พŠ??.๏พ‘๏ฝพๅŸ’๏ฝฌ๏พšยข็—ฟ๏พ{]๏พ‹๏พŸ่ˆŸu๏ฝฃ๏ฝด:๏ฝงๅธŒ77\"U๏พ#ๅžˆ}?k+R4่€‹?้Žฌ>B_T!F๏พŠ\Z>X้€ž%hdf(๏ฝต้„+๏ฝดO7i??๏ฝค่ˆˆ๏พ?bๅ’\rๅด็ฎ˜๏พž#,w๏พ›_&co,๏พ–็พค,?l<GP๏พŠd๏พ…ๅ‰–W?1?\"t\\\'๏พŸN7?H๏พ—g?+๏พ†๏ฝฝ๏พž็›†ๆƒš๏ฝป๏ฝถU_K]?%O*ๅ—ฃ๏ฝฝ\nๅ’ฝkๅฃผOKๅœปU๏ฝฒ็—ฟ^๏ฝฅๅทฅ๏ฝธ็ญG๏ฝฉ#t๏ฝซ-๏ฝฆN mๆญค้ฝฃ\\Mtๆฏ็–†_ ??๏ฝข๏ฝขnๅŸท?ๆญ้ฃขYEๅƒ๏ฝฐๆ—?ๆ”ป%๏ฝฝXๅญฑ?a+๏ฝฌ3@? D๏พž๏พ’๏พ˜>F~ๆŸ†T^๏พ‹๏ฝกYO2\"๏ฝถ๏พ•๏พ”?๏ฝฟ๏พ’ไฝ‘?๏ฝด?๏ฝข่จ“้‡ถg๏พ—?\nIai๏พ๏พ‡)?\nWF๏พ…H?(?ๆœˆeV้คฝ?ๆ†พ?ๆ†งjW๏ฝฅYๅงช๏ฝฌ?๏ฝฝx้–ข?๏ฝฑ5๏พ€?##?0?\0H$.๏พ™?K๏พƒ ๏ฝตk???X?;??๏ฝธ\rwๅ–‰-?7.๏พƒ?๏พ„?๏ฝต8s 2๏พ€X?f๏ฝซU?๏พ—C*\"๏ฝง้ซญc๏พœ๏พ—3่„ฃ==H๏ฝฟ?)๏พ—?๏พŸ*ๅญ?|๏ฝฃ๏ฝพ[?๏ฝพ^๏ฝพ๏ฝต?E??็ฒŸW๏ฝญ๏พ„|?ไน—f๏ฝฆkๆ”ด=?X\"XX๏พ–๏พš่ฑข\\_ b๏ฝฐ?\ZQ๏ฝค้…˜๏ฝฒๅ˜‰ c]r๏ฝง๏พ•๏ฝพ๏พ€gAmd?,๏ฝฌ?-๏ฝน๏พ—?>็ดฏ๏พ‰VOๆ‰ˆw๏พ˜0ๅญ€๏พ†๏พ”v๏ฝท๏พ‹?๏ฝขL้Žฐโ–ณ๏พšIใ‚†u๏พ•g-+f?้ฌ˜?D้ฐฏe#๏พ$ๆ“พgDeb๏ฝฏ?๏พƒd\ZHไปถ?)%ๅค™T ?๏ฝฃ?,\nๆฉข๏พœr?6?P?X? ?ๆดป็”บi,๏ฝดๅ‰ณ๏พ‰Nl?Q๏ฝผ*๏ฝปK G\0๏ฝฉA;k w๏ฝฅ}+??๏ฝข???้ผก้…Š?\0๏พ›๏ฝฎ๏ฝฝe๏ฝซ๏พ้Šœๆผฟ-?๏ฝบ่†€๏พˆ?#๏พNT$ๆ€๏ฝธๅค๏พƒ;?A?y?% ๏ฝฅ่œ๏พ‡๏พ‰?IZI๏ฝพ๏พ๏ฝต๏พ’K\Z๏ฝฌไปŽrWr?8?๏ฝฐๅฃœ3๏พžfๅด๏พ˜?\r๏ฝฆgMLtnV<{Jๆ‹’๏พ8T?V????ไบ•?๏ฝฅf ้ฏก๏ฝต ๏ฝต่–AIcd\'o๏ฝบ๏ฝฑ]?e?๏ฝฟฯ†๏ฝญ;็“ถ-ๅ”ฎ๏พ…b\0?๏พ•ๅฅ‡?๏พŸ?6?\n๏ฝบ??๏ฝถ้ฐ•G]๏พž?๏พŸ ่€†Z๏ฝซ?๏พŠ?ๅŸœ;๏พŠ|?๏ฝต|9็‚บ*#็ขง๏พ—N๏ฝพG??\0้›„=z1๏ฝจ๏ฝพ๏ฝฏ?\n็‹—๏พ๏พŠ๏ฝข\"?๏พ†๏ฝต?*??๏พŠ??๏พŠ\'?\'GCQๅทป๏พŸๆŽ’๏ฝช??\"xDj9๏ฝพ|/๏ฝฅU๏ฝพๅทด#?}J๏ฝฉ้‘ ๏ฝป>๏พ{?๏ฝฟไฝฟ๏ฝฃ็‡ป๏พ˜8๏พš๏พ›็”Ÿ?C%๏ฝค๏พ3?3๏ฝธ๏พŠGใƒฑ๏ฝง๏พ›้š—_๏พ’?9๏พ‘๏พžH๏ฝฐ๏ฝฐๅˆณ?\Z? ่ข$)๏พŸM??>}L๏ฝปๅฏพv?u\r?-๏ฝฝ่ŠฌB๏ฝธl??R!ๆ“[๏ฝฆ๏ฝฑไป•\r่‰ฎ?ๅœ–d?๏พ›๏ฝจ่”ฝ๏ฝฒGO*๏พ…๏ฝถ๏พ‹๏ฝฐๅฅจ๏พŸl?\0M๏ฝก?>๏พ›3#ใ‚ˆGๆŸ๏พŠ6a?B่ฎk\Z3o?๏ฝฌๅคC็‚ŽF๏พ•่–‘?:ไบค๏ฝช๏ฝก๏พ€\"%?&?6$ ??\0}๏ฝพ๏พ‡้„o๏พ”X?)๏ฝฟ?๏ฝณo๏ฝง?fW้“๏ฝพๅฏบ๏ฝบๆฎŠ?+ \r๏ฝพ๏ฝช๏ฝญ๏พ–?๏พ‡Oๆญณ?*๏พ„ใผY$o่ฌ›Z๏ฝ€๏ฝณ??!EF?2 ๏พ–๏ฝญ=่—ท(??๏ฝฎ้ˆทuR?6u็›’q๏ฝค?๏พ“๏ฝฝๅผๅฆ{๏ฝฟl็ญฌ_*KL?๏ฝข/๏ฝฐ๏ฝป๏ฝน?!?caๆ…Š%ๆ˜ฟ??ๅˆ‡่ˆŠ๏พ‘๏พ‚้‚ตI%๏ผฉ๏ฝฝ๏ฝจd?๏พŽ{]\Z#Y๏พ’Ukr+๏ฝญ ๏พ^๏พ’SQU๏พ•๏พmxA๏ฝฆWยง\n?!ๅ…Kๅฉw๏ฝคๆŽขX๏พ˜P๏พ‚ะฎ๏ฝบ#ๆฟ 5ๆผ=๏พ‰X๏ฝนTb๏ฝต๏พŸGๆธฆ?<\Z7ๅถŒ๏ฝฒ๏ฝฒ๏พ„?๏พœ้ถด๏พ ?7๏พ๏พ–?,@!1๏ฝณLK?๏พI&&?๏ฝคไฟฃ?8?8#1>7=T47rRVY^๏พ—?6๏พ„$3(๏ฝก๏พW?8?q๏พžP?๏พ›DEx๏พ€1^้†ฏ#ๅฃ‘Q็ฒ‚๏พ…sๆ™้ฎจ??Sd๏พ็ชฉ?็ถด ๏ฝฆๅˆŠ3h=๏ฝฅ?@โ€˜๏ฝจ๏ฝฐไน™jf๏ฝณ$V?RV๏ฝญ|๏พ•๏พ„็ฅขๅ‡‹?ๅฟ  ้Ÿœ๏พš๏ฝฏ%?[L6xz้†ซM๏พs?u๏ฝฆ$x2๏ฝณ?\"\0?!c๏พ•Q?$่–ฆ?5้คŠV๏พœ๏ฝฌ๏ฝณD\n?k ั‚%๏พ0๏ฝพT่Œ‰๏ฝฝ๏พ…๏พ@?่ฎ“๏ฝซ๏ฝฝ๏พ??M๏ฝจ๏พ–ๆšผ๏ฝก{ๆ‰๏ฝฃ๏พŒ{?:๏ฝน๏ฝจ๏ฝช[๏พ˜๏พ‡๏ฝณ๏ฝตๅ‹บF?[b?#B๏พ›+ๅคœ๏ฝก}=๏พ‰\\๏ฝด?&D?&๏ฝญfIg1,MjZqBๆ•X?%๏พ˜ๅทฝYQkXT?ๆฝบ้ฏ’^!๏ฝฌu๏ฝต8+ไฝปrIj๏ฝฌK[๏ฝนi๏พŒ n{&4i๏ฝข?8j๏ฝตๆณŒๅŠต่ธˆ๏ฝผ๏ฝฐH้ปŽy\Z?๏พ—๏พ่ญ›\'4๏พž็‚ธb๏ฝพ?๏ฝฎๅนน๏ฝฅ๏ฝป.๏ฝท%๏ฝต๏ฝฅ๏ฝปH)@~ๆฟ :๏ฝบ่ณชE[AJHBD8W๏พ’๏พšCX!X๏พ—๏พ‰ Gะบ3๏พ™๏ฝฏr๏พ…? 5?ๆกœ?\0๏ผจt\\?eๆ”ธ2pๆจบ+,?็คบ๏ฝดkrn(eOZ๏พƒ๏ฝขd\"ๆฐธ??๏ฝก#๏พˆT๏พ‹๏พ‡?2W?\r๏ฝถ๏ฝค๏ฝท๏ฝต?\0 ๏ฝธ?(๏ฝผDๆ„ฟJJ4]w\0V็ž>?#่„ฏ)g*็–ผ?.ๅ™ด็›ฃ:๏พ‰@y&>]๏ฝจ(s๏พœyFa็‡GZ\0๏พ‹izM๏ฝฉ๏พž,+๏ฝซ๏พ“๏ฝฑIQJg๏ฝฐQ๏ฝคM\r๏พy#่ฝŸc\n??zฯ‡mE๏ฝฃ๏ฝก|M{๏พ›KrL];ไบ‚q๏ฝถ5?๏ฝด??\Z๏ฝต?I$่ญ˜6hโ”ฐY๏ฝฏ?t้˜?]dd\'่ป\\r๏พ—\\๏ฝญ๏ฝจr6ek๏ฝฆ?$q๏ฝกๆจ0่ฑน๏พ›w๏ฝฅU๏พ™๏ฝคE*๏พŒ8๏ฝนcๅ’’๏พ‹y\0๏พƒ๏ฝต^z๏พ—dy\"๏ฝฝ๏พ–fSEG_๏พˆ๏พ’BaQ?KL๏ฝฃ๏พ—๏ฝช๏ฝญๆ™ฎ3๏พ‹(R๏พ•Nๆœ•?H?๏ฝฐ๏ฝน=O๏พš๏พ”๏ฝป๏พ้ปŽq?๏พƒ๏พ…!ๆฃงๅพด่Šฝ๏พ’?\Z๏พ’??๏ฝค๏ฝตE?๏ฝณV?#{2ไบญ??\n?๏พ็พŒ3๏ฝฌih๏ฝฅๅ‹งn๏พ„๏ฝด????๏ฝณ๏ฝณ\r๏พ—ๆงŒๅญณ๏พ˜โˆฝ๏พš๏ฝคvH๏ฝดZ{~N?5ๆˆช?h๏พ?\0FEd๏พ’๏พŒ๏พŸ?๏พˆNๆ™??๏พœ????๏พ‰?CI่•‰้ฌฃ๏พ›๏ฝง๏พ”C่ณช้œ็žฅ็ธขW๏ฝต๏ฝต๏ฝก๏พ•d๏ฝน@j?0๏พ…ฮฅ๏พ’๏ฝฒEๆฆ‚s่คช่‘ฌ๏พ”๏พš็™’ๅ‡„๏ฝก๏ฝฐ๏พ™ )*๏ฝคiๅˆ†m0ใ€?๏พ“L?H\0๏พ”๏พ‘ๅ ‚๏พž@>\\?OM๏พๅ†ฒ่‡ ่ค‚?๏ฝฌ?L=๏พŒ๏พ†?๏พˆ\r๏ฝท? y๏พ˜!?:๏พ”๏ฝท???=?๏ฝฝ~๏พˆ?่šฃ๏พ˜?๏ฝง#๏พŒ๏ฝดc=V่•ชๅ€๏ฝฌ๏ฝค่’‚็ƒน;๏ฝฒ็ฅ๏พ‚?\0ๆ…“%๏ฝค้ กq๏ฝฆ? ๏พ˜2?\Z๏พ—xo็ฟŠy?๏พˆ?\0?๏ฝป?#Z่ฑ|?๏ฝง๏ฝง๏พ‡??่ผŸ๏พšSWl1\\ใ‚ฒm่ฌ„่™<๏ฝณ๏พ?5๏ฝท๏พ6?GD้‡v๏ฝซ่‹“??่šซg?๏ผฅHDnใดXๅฑ\\ๆฝ}??๏พ’.?;H๏พƒM๏พ™?$X?i[1v๏พ–๏ฝฝ๏ฝฟ้ดƒ็งคD๏พ๏พš็Ÿณ?๏พž๏พŽD?ๆ–›โ™ฏDk%๏พŠ๏พ›๏พ‰4?ๅทฝๅšข๏พ‚X?(๏ฝฉ;ๆš—\0่…†?c ?๏พ“๏พšwM๏พ‹๏ฝฌไป‹Gๆพฑz๏พ‰๏พ‡๏พš,Zๆ‡ฟ3๏พ™?+๏พ‰๏พšV๏ฝฑ<;็ˆ๏พ…\r๏พ๏พ‚5dlๅฎŒ@lVz:?ๆงฟ๏พ•?๏พ•oะฅ๏ฝฝ๏ฝฏE?ๅฒ*?๏พ?๏พ•Us\n๏ฝช๏ฝฉ้ฝ>๏ฝพl?:::::::T??9 ๆทนK๏พ‚๏พœO?;]๏พ‰<ๅฒซ๏ฝง๏พˆ?3๏พ•๏พ:R?๏ฝญ้™ฐ๏พ‡?๏พ„z๏พ€,\n?๏ฝฐ%??Mๅ‘ถ๏พ€<๏ฝฎ?2ๅฃ•๏ฝฉ่•พ๏พ‹?(ๅฅ=K้ค ?๏ฝข\"\"?๏พ‹้†‹#๏พ“๏พ‡๏พๅฎ๏ฝบ?ๆดซ๏พ6G7๏ฝฏ?r๏ฝพn๏ฝต6๏พ–๏ฝผm๏พš?ใƒณ?U๏พ—๏พ ๏พœ๏ฝก๏พ‰1๏ฝถgGx๏พ’c๏พ‹g,\\;่บ™?s๏พ… ?6l?)/O๏พ›ๆญใ‹i\nๅฝฉ?}่—ท?l $๏ฝฟZ๏พŒ๏ฝถF,]7๏ฝฑ)\0๏ฝฑB7P ๏พ็—่ˆถ]?7๏พŽ๏พƒ๏พ†้šจ๏ฝค???\0N~.?vๅฐ…?<8่Š™r๏พ่š“^๏ฝป?9e้šŽ\r๏พ#\0๏ฝฟ๏ฝฉEZo๏ฝก๏พ„)fHdๆผ‚\ZI๏ฝผ 0๏พIo ๏พŽ๏ฝท๏ฝท๏ฝฒ4๏ฝฉ๏พ’XOๅ’๏ฝขi%8I?\"Gไฝฐm๏ฝซ่„‚$$ๅ‹l๏พ‘๏ฝต?๏พ’๏ฝต?$H๏ฝฎz+๏พœ่—\"?Xr0๏พ‚ๆƒŸfๅท–๏ฝฝ6\n๏พ˜\r?๏พŠ๏พ‰,?\r?๏พ‚*็ ’๏พ?่กฟt๏ฝก๏พ‰้ก??๏พžf็ฉ€{๏ฝซ๏ฝจ&๏ฝฒyl$ ๏ฝฃ?2๏ฝฐFV๏ฝฑ\\๏พ‘๏พ๏พ‘๏พ€q ๏พ|Q๏พ‚???,?%ๅ‹น๏พ›๏ผ—I๏พ—็พŒ๏พ†?,๏พ&$?vX็ฌ‚?!@;lN?ๆ ฉP่ฃ•@#๏ฝก้€‹ๅก˜ๆคŽ \r?#๏พ’\"ww?e l้ฆฅ;APฮปๆฅ<๏ฝผ?๏ฝน้ค”๏ฝฉ่Œจ๏ฝฐ?\06?0??R5??;$้ถ\Z๏ฝช่‹บ!๏พ‹?่†ˆ๏พ…๏ฝฝ้ฝ’่‹ž่ฉซ๏พ๏ฝน&๏พŒkl,๏ฝต๏ฝฎ,7่ญ˜$i\Z??ๆคนG้ดป<๏ฝฌ2๏ฝฝ?๏พ—๏ฝญ^?^๏พŸx๏พ‹่ฟฉ๏ฝผ]๏พŒ๏พ๏พŽ่‚ญy\Z?Y.2ๆ€ๆฐพ่•ญPuๆพŽgS=E๏ฝธ็‡ปA็ฌ4O็ซๆ›พ๏พZDs/๏ฝขW๏ฝน?-๏ฝถ๏พ:ๆฐธ7?;?rMๅœฆ?!่ฑŽ๏ฝฌ๏ฝฅๅธฏH)?!๏ฝบJ#(๏ฝฆdๅบ—4?l๏ฝฉ??\nx๏พž๏ฝถๆ”…ๅผ๏ฝฑ๏พ‡c%่—ท ๏ฝฑ๏พๆขขY*Q๏ฝด?DH&๏ฝณ?3ๆกU%?๏ฝฎ๏พœ?๏ฝท?#๏ฝฏzX๏ฝงๆขน:?5X๏ฝฅ๏ฝบ๏ฝถ%YnD?7ๆ˜ถL๏ฝงex๏ฝฃn?๏พŒW็ด‹y่ฅd?๏พ†?_๏ฝฐ๏ฝป็ซกI?8?ๅ†ฒ:*๏พ่ซฑLBV๏ฝญ }dSD๏พˆ_ ๏พ—๏พ‘๏ฝฝ๏พ—๏ฝถ$่‘ฌ๏ฝฑๆกŸ๏พƒ\"9่ฎš๏พ•?Q๏พ‰? ๏พ•Zะ‘j๏พ๏ฝซๅพ˜้กณX*๏พ‡\0ไผ\"gๆนzC๏ฝฃๅญค๏พ„๏ฝคๅ€ถๆ’ญ-?๏พ•o๏ฝญ๏พŒ็ฐ‡3,ไฟธc xy๏ฝคIๅ™EdN?X้ž๏พ‡๏พ…?P้™๏พ‰๏พ;๏ฝณๅฎถE๏พ”?๏ฝทy ๏พ—X$ur๏พŒ?&๏พŒP,๏พŽK?่Žต?\':V๏ฝณ9็š89G;Y๏ฝฐ๏พ„??J๏พœๆธฃbd๏พq๏พ?A4๏ฝฒ\Z?*๏พ‘H0๏ฝฏ๏ฝช?J+่Š\r?$,ๅ‹ž|?๏ฝฏ4?M-?ไบฐ?๏ฝบ๏ฝฝd?๏พ˜9๏ฝนJ3\0?\"๏พˆ?8l .P๏พŸgP๏พ„๏พ’H{๏พ†ๅ’๏ฝพ( {๏พŸ$๏พˆ๏พ—ๆ”ปH~่ŠF๏ฝช๏ฝธ.๏พ‰ =๏ฝฅ๏พ€๏พŽ๏ฝฆ๏พ–\\๏พ“๏พ—k?-็›๏ฝฐ่ด9^้„๏พJๆฎฒ?\0๏ฝณ็ฒพ?l&$๏พ‹๏พ“-&่ฟน๏ฝถ๏พa่จ“C๏พ†-?1mJ?;A๏พšC?ะ‘+๏ฝค)o๏ฝซ]mVnh่ข’๏พ†+้‡ฆEx๏ฝพ a๏พšๆผฌ๏พ‰In)#๏ฝฆ็ฑ?๏พ…๏พ‰?!<5่œฅ7jq๏พeๅ”ณ๏ฝก* ๏ฝฆJ? i๏พ›$ul๏พ“K็ฉด๏ฝผ๏ฝฑX๏ฝน%ๆ€ฑ่ฟฝ?eๆถ“๏พ“๏ฝฌm๏พ–:Dp๏ฝธโ™‚๏พ™WieDๆœทY๏ฝจ๏พ‹๏พ‰๏ฝคn3P็ฐ๏ฝพ๏พ’Tๅ“Sv๏พ‚h๏ฝต$่ชฅ๏พŠ๏ฝถ\"W?ๆ„ฟz?x?;Ye๏พ‰\Z๏ฝซ๏พ•๏ฝฎkl]?g\'๏ฝฒ๏พŠs??O๏พ‹|๏พŠ9๏ฝซh?G๏ฝฅ๏ฝฉ๏พ™??๏ฝถ?? ๏ฝพๅ‹็ผ\nQ\'๏ฝด]nๅŸ๏พ–t๏ฝณ?,2J๏พ”Ww๏พ๏พjy?/๏พ‡1?(e๏พœ _3g๏ฝข๏ฝญๅ‰ฉaC๏ฝฃ.๏พ‚๏พ€๏ฝฉ๏พ˜y-็›ด{Ai๏พ?๏พ›X๏ฝณ้ผA่‡บ\r??ไบซ6๏ฝฅ??p๏พ™๏พŒ๏ฝซi๏ฝถ?m้‹ฒ*E}L ่ธช๏พ™UPV้™Ÿ๏ฝด\"!D๏ฝน๏ฝถ\0?\n0X๏พ‰๏ฝขEs็ธ’H๏พ‰^๏ฝฒ=็ฉฐB๏พ…c?๏พE๏ฝพ๏ฝต๏พ›0[?.๏พ๏ฝฌ}ๆ„ผ๏พ“้›ซ็พฏ#๏ฝด?;2๏พˆHe่˜l$(]iZ;่ผ?\'็™พ)5XmW?l๏พ•๏ฝฟ*gๆœฌ0๏พŒbw่‡ฅ?8f\r๏พŠ>?,๏พ„๏ฝจ?5๏พ–?g?ๅ‰ช?:;ๆŸฏๆƒ‘[\\?๏พŽ่…rWm{[9?(?2?ๅ 8?c?n๏พ“้™บ=๏ฝจ๏ฝค๏ฝพCN๏ฝจe5่ผK%๏ฝฒ๏พˆ๏พ˜q?๏ฝจๅญ?๏ฝต=I้งขๅฅ‰๏พ•G9?b?๏พŸ?*๏ฝช5~Uz๏พšg??/๏ฝจ๏ฝทk?๏พ™๏ฝข๏พ€.ๆฑณ?w<่ŠนG\'X=+?่ณฃ๏พ•-vๅฝผ>?x่žซ๏พ›ๆฝ”X๏ฝซ๏ฝบ๏พ˜๏ฝก? ?=r?๏ฝฐๅ–ฎ\Z๏ฝท.๏ฝซO๏ฝฆ๏ฝต>๏ฝข๏พ˜2k๏ฝญ๏ฝช๏พŒ*๏ฝพ๏พa?B๏ฝฑ ๅˆง03!๏ฝฌ?๏พ…?7้ฎซ๏ฝต๏ฝฒCV๏ฝพๅ…‰r๏ฝญ~[C็จฟj๏ฝซ๏พ’&\\P?!?๏ฝฒN?=๏พ‘*๏พˆ???0m? m*0๏พœ่ปขๆธฉ>๏ฝฏIN?๏ฝฐVYu๏ฝณWg?*rV?๏พ”? ๅงซS-c?<๏พ›P3้ ค5-.r๏พ”?H].๏ฝก๏ฝฒ๏พœc??ๅž *h0?๏พ?Yo?็ญ‹?g๏ฝช้ญŽ?๏พ•?่•พๅฅชไฝฟ}้†ด๏ฝบ๏พ๏พ‡?6๏พ…\\๏พ˜h๏พ‡ๆฃ g9e?5?B๏พi๏ฝฐๅ‹…๏พ”2๏พ“?|H=t๏พ4qf\r\n?๏พšlN? ?!ๆˆ–๏ฝบๆข—\Z๏ฝญ/๏พ“๏พ‰I,๏ฝข๏พ˜่ณ›pC๏พ‚๏พ„J๏ฝฒV1?2?<;7๏ฝฑโˆฝg?rMZ?๏ฝฏd๏พ~Hๅณ่›น๏ฝค\\PH??2๏ฝณr๏พ…๏พ—nO?UๆˆŒRk7}?๏ฝซๆ†๏ฝถๆ‚’๏พŽ๏ฝค็ดฟ่ก†[F^๏พŸ็šด้‘ ๏พ‰9j๏ฝฉ4W6 K๏ฝฟ๏พœ๏พ™Vใ€†ๅ‰ฑ9๏ฝฐ๏พŠ*๏พ—๏พhM0๏ฝณ๏พ‹6}๏ฝซe4w๏พ‚u๏ฝฝ๏ฝบn??9 {c๏พƒq๏พ„๏ฝฃA๏ฝช๏พ๏พ๏ฝน๏ฝผ๏ฝณไผ๏พ„?~๏ฝขC?(\r๏ฝจk?๏พu?๏พ‹?y๏พŽU?\"F ?C\rCๅ‚‘๏พ–ๅ“จ?๏พƒ้ญŽRU๏พ•K]A๏ฝก๏ฝผ้ŠƒANC๏ฝดๅ–™๏ฝซR๏พ†dA๏พ‡๏พ“\\๏พŠ๏พ‚46๏พ€๏พƒ้ƒ?5\rIJ๏พ‰?i๏พ๏ฝจ4?4๏ฝฏX๏พ€Q๏ฝฑ๏ฝชl8?W๏ฝข่…ธYZ๏พV3Wๅด๏พ’Wๆท‘dv}๏พ‡aBp๏ฝฑYs?๏พ‹ๆด™๏ฝฃ^๏พŠZๆŒŸ?(z๏พ•e๏ฝช่œš๏พ–/??L๏พ ?่•Š๏ฝฌๆ‰‡?b?\Z๏พ€?\Z|?้กดq็ฒฒ??๏ฝก?&๏ฝธJ๏ฝป๏ฝฉ?>K๏ฝฌr?ๆ‹ถ\"\"\'ๆŠซ?y\"๏พ‰ ไฝฏ้นน??m๏พˆใบ%.r๏ฝบ๏พˆ๏ฝฒ๏พŒGm๏ฝญ๏ฝผๅฏ›b๏พ…๏พGS\\๏พ›ๆŸ”๏พ•C?F๏พ็—ฒ,๏พŒๆ›พ<๏ฝช๏พœHl็‘ฏๅฎrt<_้ ’๏ฝคS็ฏ๏พ™?๏พ‹๏ฝธ๏ฝญ๏ฝณโˆ‚V๏พŽ่œœ?)r\0?\n๏พŽ๏พ‘?๏พ‰b?,?๏พ‡??ๆ€™๏พŸ๏พ‰ๅพฉ]SuKs๏พŒ?ๆจ’ๅกขk ?)q?4?G?0yฮฃ&ๆฟก[FH??\0๏พ•\"s้ฏ”ๆ น๏ฝฑC?๏พ๏พš?\0๏พ’๏ฝบ๏ฝธs๏ฝง๏ฝช็พ†๏พ็ฝตะšb๏พ•(#๏ฝฝ6A๏ฝซ๏พ‹%x้ฃฝ๏ฝญ?h$w\nL?}๏พŠ/-?5๏พ“Dzๆ›œ๏พ˜๏พŽ๏พ›๏ฝฟ^ZI\\้‰ขe๏ฝฌVJ1N๏พ๏พ+i๏ฝฌQ? J$๏ฝณ๏ฝธd็ญฎ๏ฝง๏ฝฆ๏พ๏พŠ|yG๏ฝบ่–‡b๏พ‚?\0-ๆบบ๏ฝพ่“L๏พˆ? ๅฏคl๏ฝญ?๏พ๏ฝฅๅฏฉ^<็›_-๏ฝฐ๏พ˜h่ฟš๏พ‡W๏พ„b?t%? ?ไป–??้ถ๏ฝท๏พˆq? \\?em?๏ฝฌ?KoW๏ฝผ๏พŽ๏พ}cAv ๏ฝฃ?3?!๏ฝด๏ฝฆC ๏พŸt๏พ™ ๏ฝฐๅธธ๏พš๏ฝซ#๏พ“๏ฝง-๏พ๏ฝฏp?\"_r๏ฝท%XD8E?1็œฅ๏ฝญๅนŒTiPVN๏พ‹?๏พŒ!๏พ‰!๏พ•?Ia\n[้จ&Ll็ฅท๏พ™\":)ะณ=๏พŒ?็„”๏ฝณ?;N???+P-gwQMU๏พœ๏พ‡๏ฝถ๏ฝธX๏พƒ๏ฝฌd๏ฝป๏ฝฉ๏พ‹\\8๏พ๏ฝฝb\ZAy๏ฝฏBtใจ?2๏ฝญ๏ผตP๏พƒ ๏ฝฑD๏พŒ?6m?,n\n?็ฎ‡%ฮบK#๏ฝถ๏พ—๏ฝง0ZrF(๏ฝฌ๏พ›-??\"่ฒฌ?*?๏พŒ๏ฝฐ๏พŠ/๏พ‹๏ฝข๏ฝจ?R1E8๏ฝขO?๏ฝปs]/dๆ’ผ?/2Gy๏พƒ?7้ถšh??ๆฌ??h๏พ‰bE4H5X๏ฝฟn:76\".??8???.๏พ—1๏พšO)jD|๏ฝฟPU๏ฝปbN๏พ„v๏ฝฎr9d็ฏ‰๏ฝฑ๏พ‹3๏พ”w??n๏ฝฑ?๏ฝก๏ฝคb7?้ ค้ŽŒmKๅฐ8็ต–xy๏ฝซ๏พ ็ฟŒ๏ฝณ=c\Z๏ฝฏp๏ฝฌBrW?j๏พ„<๏ฝฏ้…ฉ้ฃ›?N?/๏ฝซ๏พ‚?๏พ‚\"\'่ฌฌDETDo๏ฝฉU|\"\'็ฒง๏พ‚?ๆฒปDlv?\0N๏ฝฏ?TjlI๏ฝฉ8;่ˆฉEะซ%?#<#?0?ๆ˜จ๏ฝชๆผข??๏ฝข๏ฝง๏พ‚๏ฝง?๏ฝฒๅ‡งW?E?5EN่‹ฃ\0jg๏ฝฐI๏พ„๏ผฆ?๏ฝฐvN3๏พ0?,##๏ฝฝlz๏พ‰bV9๏ฝฉ?-๏พ…q๏ฝฉ???\0๏พš๏ฝง??\0ๆญฏn\'่š“Oh\"๏ฝฝ๏พŽๆ›ฐ?\0๏ฝถh๏พ‰y๏ฝพ๏พ๏พ“F๏ฝฑ๏ฝต๏ฝซ่ฅท\"H๏พŸ(่†‚๏พš?ๆธฌๅ–š?I๏พ„้ž‹{๏พ? ็”ฃ?๏พ„๏ฝฆj่…ฟ1๏พ•๏พŠๆฟ†?็ดฒY๏พ›?b๏พŽ๏พ›๏ฝถ๏พ„4๏พ‹ๆ˜”KJ9๏ฝชc๏ฝค๏ฝฒDEไฟพ?๏พ‰๏ฝข๏ฝดq๏พˆ#<๏พˆ7, ๏ฝงๆ…ถbK็žฌ๏ฝฟXๆญข)??)k๏ฝญ?Cy\n๏ฝนC\Z*Z3๏ฝฒๅˆถ๏ฝจ๏ฝฒ๏พ›๏พšๅพ‘?๏พ.?๏พ๏พ‹2๏ฝข๏ฝดv็€งๅปทๅ‡ช*\0cL.??่Žจ?3S๏ฝก?xM็‡ง?๏พŸb๏ฝฉ)?๏ฝฅ๏พ‡6bU๏ฝญ็บœ๏พ†? ๏ฝน}๏ฝด่‰๏ฝป๏ฝถ gJtLH44?X\"?๏ฝฆx๏พ˜??H๏ฝญ๏ฝช่†ˆ~ๅฃ™[0๏ฝถ้ผ ๆ€ฅ๏พŠ๏พŸ?๏พ–A\\%๏พŒV?=e\rๆ‚งIa๏ฝค๏พ‹ใ† F็ตž๏พž๏พ€๏พ‹ๆŽง?Dๅš€m๏ฝปd่ณ?+๏ฝด๏ฝน็ฎ’ๆพน?N๏พ–๏พ›๏ฝป๏พใƒ„q๏พŒ=๏พ€๏พŸ๏พ•๏พ˜็คช- ๏พ’yd>๏พˆ~๏พŽ่ฑธๆจ…[\Z๏พšd๏ฝค?๏ผˆๆฟ†็™จ๏พ–\n?\r9๏ฝฆ?%v&[?๏พ‹ๆนฏR??7?๏ฝฉ@๏ฝฒ\Z๏ฝฌ?๏พ’\"%็‰™็พ*?๏พ†^?๏พ€ๆง? B$H?(?๏พ—๏ฝท$๏ฝฑ?;E2ๅกž%๏พ™๏ฝฝ๏พ„n7=5๏พˆ๏ฝฐ.๏ฝฝ่ฃ„9๏ฝณ?ๆผธ่‡พt่ฆ“]k๏พ‰็ด๏พœj๏ฝน?๏พ›ใ‹๏ฝณyb%W?A๏ฝง.๏พ‚๏พr๏พ๏พŒ๏พ’๏ฝฏ๏ฝบ๏พ‹$๏ฝฒ๏พ‘?7]ๅคฒ?๏พ€๏พ๏ฝบ?1ๆฅขs\n?cp๏ฝฝ๏ฝบf๏ฝฌsๅ…ช/m.่Ÿ‡๏ฝณ๏ฝง่ฌn.ๆฅท๏ฝถ+f้ท‚n๏ฝพ๏พš?\0?๏ฝฆs.\n2<\n?3\'โˆฝ๏พŽ??Tๆ„๏พ‹?h??W๏ฝฎ๏พ“.?๏พœZT๏ฝณ๏ฝค๏พ nA๏พ‹๏ฝถ4๏ฝฃ\"๏พ€๏พš๏พ๏พ’Wๆ‹ฎEh๏พ–?;H\'๏ฝกๅ€…็—‚๏ฝต?p?5q?;ใƒœt๏พZv็ฟŠ๏พ?๏ฝฉ๏ฝด๏พ—9๏ฝซ๏ฝก3๏พ™z่น„็ถด?T:?๏พŒU?Z๏พ˜deๆธฉ6่œทq JD๏พ…K๏ฝฉ๏พ—2๏พƒๆšฆ๏พ—็ธซ็ t๏ฝซ๏ฝด๏ฝฐ๏พ‰M_^Icx)๏ฝฉU?๏ฝนy๏พˆ ๏ฝทjJๆ–Ÿ๏พ”Ndๆ‡ธ?>ๅ…ธ_๏ฝจn๏ฝญ8R{ๅœง๏พ ้Œ†$?๏พ—้ฎญ๏ฝฐ?b????๏ฝง๏พ”cๅž‚๏พ็‘•k$? 5\r/๏พ๏พžXQ๏ฝŠ๏พ8%่ฒง๏ฝณE๏พˆไบฆ๏พ€v?a\n?๏พ›?9ๆฑ‚๏พ“W+?\"x?๏พ˜@?,๏ฝฎ?g#๏พ•R?\nJa๏พ…๏ฝฌ๏ฝณZKK๏ฝข้– ?*๏ฝฟ๏ฝน*๏พŽ๏พ’๏พ˜{/M}pๅก็ˆ›๏ฝป๏ฝช๏ฝผ๏ฝฝ๏ฝท๏ฝถ%lep๏พ„?+gH:}Y๏ฝฝg๏พ„u\Z^๏พŸ?:,๏พ๏พ‡,\Z?๏พ‹?๏พœr?๏พ„ๆˆฒ๏ฝท๏พ๏ฝค?๏ฝพ๏ฝฟ?5?๏ฝฉ5e ?rvh๏ฝขI? ?ใ‚‚?.๏พš?๏ฝซ?|ๆต™็ฝง๏พ™ds?bk?ๅนขK๏ฝง่Š’v?&??\0๏พ“\\j๏ฝป)CZ&}็‰†? ็ฏท-E๏ฝป๏พ†ใœd??๏ฝบๆฅ”Xๅ™>ๅŽญ็˜Ÿ๏ฝข\Z#?3-ๆ‚ŸZ๏พ“่ฌ‡F๏พŸ?๏ฝบ่บ๏พ“ac๏พ”Iๅ‡‹i๏ฝข|?้Œจ่…‘?9ๅ‹˜ๅญฃ?+๏ฝธ๏ฝถY๏ฝฅ๏พžQhs{็šฟ๏ฝฌ๏พ…๏พ‰rsg๏ฝง๏ฝถ0?ๆตธl๏ฝฐg๏พˆ๏พƒ๏ฝข6๏ฝค๏พŠ๏พ˜\\kQ่‰8R๏ฝฌ?!:WQ๏ฝพ๏ฝฉ?7๏พ’ๆจŸ๏ฝบ๏พ‹?๏ฝน!K?? ?๏ฝฒ๏ฝฝ!|๏ฝจ้„r!๏พŒ\Z๏ฝฝ}๏พ‡ (?๏ฝนYๅตŒๆค„่—๏พ›่ทณ\0๏ฝฉ@Y่ฒžA\'z6R?๏พ–/๏พ“๏พ\Z4๏ฝฌๅท?##{Mๅฌพ๏ฝบK๏พ“?$๏ฝกX๏ฝพ?/=xjXD]?๏ฝป๏พŠ๏ฝฃ?็ตฎ?ๅƒT^Q๏พ†๏ฝฆ>๏ฝด?=~|D?\'่ฌฌDUWxO>|๏ฝซ๏พŠ๏ฝง?U?้Ÿ‹zx_??\0?I๏พ›๏พ‡??P?๏ฝธ?\0?๏ฝบ้ฐŠ(่–€??๏ฝฏ?้ผˆๅ–ฐ๏ฝฉ้…ฉ?~:็ฝ?็†•pv?๏ฝท?uS๏ฝฏ๏ฝถ๏ฝฐ๏ฝฌ> Ip๏ฝฆ:O5ๆ˜‚J๏พ—๏ฝค๏ฝญTj3๏พ‘?$j/๏ฝกZ๏ฝฌT?๏ฝช๏พŸO๏พ‡O?yX?็ง‹๏พŸ๏ฝถ๏ฝพ๏พš\Z[๏ฝธ๏ฝขSๆป๏พ„K้ญ…~๏พ’S]?\'?\'??I}๏พ™๏พ˜๏พ„่ณŠF๏ฝฑ<๏พ‘U>????\0h๏ฝฝz๏ฝฒG๏ฝต=H๏ฝชไธ”?J๏ฝฑ=/o?+<|?๏พƒ๏ฝผ||?? ๏ฝฝ๏พ“๏พš?#๏ฝฆ??efZ๏ฝถ๏ฝซ๏พ™ๆŸฑ๏ฝฌ๏พJ่ป›Dn๏พๅฃปไธถT๏ฝช;#๏ฝดM๏พ…๏พ“fU#AๆธพไฝปERj๏พ—๏ฝกA3๏พ‚?u#_๏ฝช๏ฝซ๏พx่žบ_๏ฝพ๏พ๏พ•?0WVeo?>ๆ—?!C๏พ!i?๏ฝฏ?#๏ฝพ~n???e๏พ‰?0??%?=?ๅ†ถEjE+๏ฝฆWF#่ƒฏU!|๏พƒ๏ฝดzn>ๆฏ˜ๆฎฑ9๏ฝฆ๏พž๏พˆ?๏ฝฉ?c5\"็Œถ\r]?ไป็ณŸ?C๏พœD่ค‡็š‡:\n็บ‚็นฆ๏ฝฌr็ถข?๏พŸ?1?s?๏พˆ7๏ฝฎ๏ฝฎ?&?๏พ‚ไผ้‰„?ๅฅงKqKๆ–ญ๏พ›?้€ข๏ฝซc?๏ฝต,? *E2๏พ„๏พ‰%??<7๏พ•\\๏พ‘๏พˆe\\?+?๏พ‘er๏พ‹>N\r<๏ฝค๏พ•๏ฝฒ๏พ†๏ฝฃ[Cv?6SN?๏ฝญP ้ค?็•ฐ??0\Z?\0O่’ก[9K?=๏พ™f?mD๏พ‹^#;?ๆ˜”๏พ’?$ๆŒ‡p๏ฝช_?๏ฝขK่„Š:? \\dBHaH่ฑน๏ฝฐ*๏ฝฏwโ”ฃ๏ฝฐ๏ฝญ?่–ฆ!Sๅ‹ ๏ฝฑ๏ฝธ๏ฝฝ๏ฝพ๏พ‡@ ?k๏พ‚65T๏พ•๏พ‰ n~{Y๏ฝฐ๏ฝต[ 3ๆฟƒm|?ๅฃ˜?F?\0ๅ„•E๏ฝฐ&๏ฝฅ=ๆธฌ\\?N#)๏ฝด๏พ็กผ8\'_[๏พžVO+ๅŠฑ?#?w%s?๏ฝฝ?๏พ๏ฝต?๏ฝค?่ช˜-๏พž๏ฝดB๏พ ๏ฝบ๏พˆๅฑ‹ๆฉKE \0ๅขจ??-?๏พ˜\r?้ฉข๏พ€&๏ฝณX๏พ‰r่†จ๏ฝฌ๏ฝฃ๏พ›[<๏พๆซบ#Y็•ฅ;>}?๏พƒ:ๅ•†?๏พ› ?7??\"F>U????;?iไบˆ^+4\r๏พŽ็ง˜4r8\\๏พž6?๏ฝณU!๏พ“๏พ‹_๏ฝฅ๏ฝปm\r๏ฝซ%๏ฝฟ๏ฝด\\๏ฝฝ็ฐฟ\\๏ฝฑb๏ฝกX๏พ‹lrKZ๏ฝกๆฐ“ๆ“ก๏ฝฆ?e๏พ‡๏ฝณ-j?๏พ˜?0wZ+๏พ…)8่’?่ณค๏ฝฒ?&w?^็”˜628๏ฝญ๏ฝก2๏ฝฝ?!N?3๏ฝณJR!&?b.?\"zๅ™ด?0b?๏ฝฃ?๏พ™?ๅ“‰่˜‚๏ฝฅ๏ฝฉ็ผบ๏พ„ๆฑพ?r๏พ–\0m๏ฝด๏พ?7\"X๏พ•:๏ฝฌ๏ฝช๏พœT?*sWOaๆจ—๏พ™H?็ข3ๅผ๏พƒdv็”‘๏พž?97?rd๏ฝนB?/(?4m๏พ‘?7?3X]๏พŸ$๏พ™<7d๏ฝธ๏ฝฉ๏พ“ๆŒฏๆงฝg?5๏ฝค่‡“<&1 Y๏ฝฃ้จ’๏ฝน+๏พ‰S?)o+x_ๆ’ฒx?๏ฝฆ็šธ[\ZA-4S๏พ’?^๏ฝถๆฉฆใ€ƒ?;?:+\Z?|ไฟฎ~h4๏พ“+,\'??C+๏ฝฝ๏พšw็ต›๏พ‚<๏พš๏ฝฆ้ ƒ?๏พ—c?t๏ฝธKh?qix๏พŸMg?้ฌผY ?๏ฝต๏ฝฒ๏ฝฏ\'๏พ˜๏ฝธ๏ฝฏ๏ฝซ๏ฝซ๏ฝฎ๏ฝณ?\0cK?;x๏พ‰!?๏ฝฒP๏พžๆฃฏT?๏ฝฏzq็ฅจ๏ฝถ+๏พ?4๏ฝฃy๏พ–๏พ€๏ฝฌ?\ZGe\\e0!๏พ๏พ‚ใ‚‡Pใƒผj๏ฝช4v๏ฝฑ?g๏ฝธๅง†-?/p๏ฝถ#,๏พ‚?<๏ฝถ๏พŽ6*#?K๏ฝฏ+?h๏พ๏พ๏พœ?~๏ฝป๏ฝญ๏พ‚๏พ“่ฉ๏พˆ?3๏ฝตXH?x๏ฝฒ๏พ“}T๏ฝฆT้บพ๏ฝญ๏พ•ๆˆฏ[T2[๏พ†๏ฝณ]๏พ”5?b๏พœ+๏พ˜?่„ฑ\'่ผฉCๆŸป๏ฝฆ๏พ›๏พ‡๏ฝบๅ†…p{N>^A๏พ‘a)uV:๏พŠ๏ฝช๏ฝญ<่ˆตQ๏พ‡ๅฟค*๏ฝบๆ‚›๏ฝฏ๏ฝฌ?๏พš?,๏พši๏ฝช*\'H\\ๆฟ‚$k๏พŸ๏ฝด๏พp่ฅฆ๏พž;??? ?y๏ฝฟ๏ฝน?๏พ‡้‡๏ฝก?#๏พ…๏พ•\"๏ฝธe๏พ“G!๏ฝด%D?/?๏ฝฃ?x1ๆšฎUg]{Mๅป๏พš่ทj*ๆขฆmๅฉช$o่พฟIp$ะ‘,่‚ข๏ฝผ?ๅฌ1๏ฝค๏ฝธ?!?_4๏ฝช?Z๏พŽ๏พ–็ทฌ็พˆ๏พš)h??$D๏ฝถ๏ฝช๏พŠ๏พ“+y๏พ‘๏พˆ $๏ฝญ๏ฝณ%้ผกI3EZXๆ†ง๏พ„๏ฝฒ๏พ€?h๏พ–๏ฝฅ[V๏พY๏พŒ๏ฝฒglv?w+!๏ฝฉh๏ฝฅ้ณฅ)๏ฝณ๏พ?#pvv๏พ˜?fEUTU_?Q|x?๏ฝช?ๆกŽUS๏พŠ?os\"xT??\'?Q???๏พ๏พŽ๏พ„?ๆธˆ??๏ฝฟๅบŠ?|?\' ?;๏พŸ???๏ฝฃ๏ฝฃ๏ฝฃ๏ฝฏ:::?S??\0I???๏พ‡\\tttu๏พ๏ฝฏsQZ่ฑZ่–คkW๏พŠ๏ฝท๏พ?>Q๏ฝบ?๏พ‚?E?;{???|??#]่›ฌ~W๏พŠ/?\'๏ฝฉ๏พž?/?7๏พŠ?:??>F๏พ‡๏พˆ\0?๏ฝฃ๏ฝซ๏พ›5๏ฝพ๏พ™e?๏พ’ๆ‹พd!u๏ฝฉ4Aๅ›ƒx๏พ‡้ฉ๏ฝฑ๏ฝณ๏ฝฒ๏ฝงY!้ 5๏ฝญl็ฐก๏พš๏ฝฎ??jt๏ฝฌ๏พ›?1๏พ‰่ฆ?I?\Z๏ฝซMๅœป\Z้ญ…Gๆšพ๏พœ??@่ถ?zr?e\"๏พ๏ฝฏ5ะธๅฌฐF5A.ไธ™๏ฝข๏ฝช\'ๅŸŽ?\'??๏พŸ๏พ›๏ฝฎ๏พ‰#ๅธ™๏พ‡???๏ฝฌ??๏พ“??๏พŠ๏ฝง๏พ‚?๏ฝฐ?+่ณŠ]?v๏พœu่‹Ÿ&hR๏พ„?~><&?๏พ‰๏พœN +?\0๏พ˜:??>/e๏พ–Y้ž…่„ฑR??9C?๏พ“?>wB๏พ…?AK\'n]??[C๏พ„๏พ™lx\\Y๏พƒGC๏ฝญ๏ฝฐ๏ฝถ?a๏ฝฒ*๏พŽ๏ฝณI๏ฝฟa๏พ•\r ้บ‘ๆฎบ่ตญ?=?(1๏พ“Azt?1(๏พ“๏พ™YLE๏พ‰๏พˆP?๏พž๏ฝช๏ฝพa๏พŠ๏ฝจ็นป๏ฝต๏พ–๏พ€?6๏พˆ_]๏ฝบ่ดŠ?๏ฝฒ๏พ™้Ÿ‹*6 ๏ฝฝ๏พžๆŠปๅŠตๆ™~๏พž๏ฝธ?\'๏พ‘P็ฆฎ?R?65ๅๆฟ ่™ง็ฟEsๅ€ก~๏พ•EO๏พœ้ผ๏ฝฎ?๏ฝป๏พ๏พ”_(๏พ”D?๏พ’๏พ„?๏พ–9?็ซœ๏พƒ\\ๅŸ๏พๅฆŠ?D?ๅปŸ*๏ฝพUUU้ฎช๏ฝฝ๏พ”? gK\r\rไพญZdV?็†ŠP,Q๏พˆyK?mGzc๏พœ?;?.่ˆฉN\"?๏ฝช=gh๏ฝธ/jI8sw?+1?2ๆ—Y๏พ‹?]้ž?(.๏พž?๏ฝฟไฝ๏พŒ?%\\้?::FNn??\0๏ฝฐ๏พ“ๆถ›4c?,R\n๏พ™GX๏ฝฝ็ง•$๏ฝฑ๏พŒ?cTIF)๏ฝฎ{_๏พ?6๏ฝน๏พ‹#Xๆก?๏พ“๏พ•?4qCfๆ…ด?\'ๅ†ฅ๏ฝช๏พˆ๏พˆ\0๏ฝซ่ฒž่—๏ฝฒQ๏พ…@ๆฏ๏ฝก๏ฝง้‰„็”จ\"๏ฝท้‹บ?y(#nj็“ง๏ฝฐ๏พŸ๏พ‚๏ฝฉ lH;y?9๏พ‡s ๏ฝณ๏ฝฅ๏ฝซ\0?0??๏พ‰๏ฝฏ,?j*).?9K๏ฝต๏ฝง๏ฝต?๏พ˜?ๅบๆฃš้ปน๏ฝธ??<*๏พŸ.่ฒฟ]}๏พœ0ๅŒธ๏ฝฟ&W\\้‚„??ๆ‰ž)72๏ฝฝ่ฉฎ(r๏พŠ?E?)b|qC<่˜#ๅฃ•๏พž๏ฝฑ}๏ฝฎ?c!clM?4u=??L็ขฉๆœบ๏ฝต?p3?๏พˆ๏ฝฆๆ$j๏ฝง๏ฝขifG๏พŽ้Žš๏พ–๏ฝซo\r|๏ฝฒZ๏พ•๏พ“4?๏ฝฌ-๏ฝฌ็ตตY}๏พ„็ธฆ ๆฃ’*๏พ•$ไธผ๏ผง1?*๏ฝป๏พ€n?*๏ฝฏ๏ฝฉ?#S+๏ฝฎ?{o:๏ฝฌ๏พ‘ Ll็ฃ”?*๏พŠ๏พœั†Q?\0???ๆ•ฆo็ปไน˜๏ฝฝ๏ฝซ๏ฝญ?่ซก๏พๆฎซU\"el$๏ฝฑ็ธท๏พ๏พ‡ๅ†™/๏พš๏ฝฌv่ฒฟ%็ฒ?zๅ•พ๏ฝฏ๏ฝตVgJ๏ฝญๆญฏ?๏ฝถ๏พ‰^?2๏ฝพ?ๆฏ˜?๏พ›k?๏พ†a็ญ–40๏ฝฆX็ธฒtr๏ฝฃaIQ๏ฝฉ7ไฟฎX๏พ…F๏พˆ๏พ–z\Zๅญ๏ฝง?n๏พz๏ฝน๏พž๏ฝฅr๏ฝฝ๏พŠๅฅ๏พŽ?*๏ฝช๏ฝช๏ฝฟ?๏พ•U|??_>~z?ๆฏ๏พž7Q็คฆ๏พ’?5<\\?๏ฝต)s๏ฝฐ๏ฝทrq๏พ–_?๏พ–\"AV๏ฝผrๅ ค?${\0/uG๏พ•๏ฝฃ๏พ“๏พŸKli๏ฝผ๏ฝช?๏พ•๏ฝต๏ฝฑ่™ซ๏ฝฉ?Hๆ˜ƒ*2p๏ฝฑ/6D?4่›ธ๏ฝจd?็ธ}?้–‘F9๏พ„?๏ฝพ>๏พŠ๏ฝฏ??>|?\0่—?้ฝ๏ฝข๏ฝช๏ฝฏ๏พŠ๏ฝฏ???๏พ”๏ฝซOGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\\๏ฝฃ?๏พ‚~???\0่ป†?็”ฆ็ฟ•๏ฝผyO ??>>?้ž?>็•๏ฝฃ๏ฝฃ๏ฝฃ๏ฝฃ๏ฝฎ}oO๏ฝน~๏พŠ??\0H? ??\"*|*/้†‹#๏ฝฟ?๏พ‡?S๏ฝฃ๏ฝฃ๏ฝฏw?๏ฝน?้€Ž๏ฝก่†‚ ็ฟฉ??-_๏พ‡?S?\0ๆป‚?้…Šu๏พŠ๏พˆ่—UT?๏ฝข5๏ฝจ??(่กฃ?๏พ‡GGF้Šท?|?๏ฝฟo??>::็นs๏ฝฟ๏พ”๏ฝฟๆธ‰\"\"\"~W๏พ‚5่›ž\"\'๏พ‡็พ‚๏ฝช๏ฝพ๏ฝท?\"\'?ttu่น GGGGGG_?๏พ™?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Exif\0\0MM\0*\0\0\0\0\0\0\0\0\0?๏พ›\0C\0?๏พ›\0C?๏พ€\0\0x\0?\"\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0 \n ?๏พ„\07\0\0\0\0\0! 1\"\nAQ$2a?q#B่ดˆ้Žฎ๏พ‘?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\05\0\0\0\0\0\0!\"1A#2Qa3?$q๏ฝฑ?CRb???๏พš\0 \0\0?\0๏พ—?\0๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ‘๏พ—๏ฝผP๏ฝฌ่ณ€FH?\0l~ๅนŒ?๏พ‹?๏พž๏พ›๏พš๏พ…s้€€=J๏ฝซ\'็ฟ’Z?๏พN๏พ‡๏พƒ๏ฝต?\Z?Z]๏ฝฅ_3๏ฝท๏พž๏ฝธโˆž๏พŒๆ•ˆ uๅ›ฐ๏ฝท๏ฝฌๅธฏ1M๏พ…gb๏ฝญ^๏พ‰๏ฝจ้ƒข *๏พ*\r?9๏ฝข้‚ช๏พœ๏ฝฆ@}๏พ€?้…ฒ\0ๆฟค?^3*๏ฝซ3๏ฝช?O?~๏พŸ>H?\0๏พ‡๏พ‡?A#้ต™_|y_ๅฑ๏ฝช\"y?7๏พ‡๏พ‡?O๏พ—่‚…๏ฝฎ?๏ฝป๏พ“?๏พ”z?Es??้ฅ•๏พˆ?/๏พ‡๏พŒk?~U:๏พ™K๏พš๏ฝฟ??>xz๏พ–๏ฝค?๏พ‘r?{p&๏ฝญไธธ }๏พ”\\)๏พƒ๏ฝฐ?$๏พŒj?m๏พ‹๏พˆ๏ฝค ๏พŸ#๏ฝขY?๏ฝฐ๏พ๏พo7$๏พŠ??.๏พ‘๏ฝพๅŸ’๏ฝฌ๏พšยข็—ฟ๏พ{]๏พ‹๏พŸ่ˆŸu๏ฝฃ๏ฝด:๏ฝงๅธŒ77\"U๏พ#ๅžˆ}?k+R4่€‹?้Žฌ>B_T!F๏พŠ\Z>X้€ž%hdf(๏ฝต้„+๏ฝดO7i??๏ฝค่ˆˆ๏พ?bๅ’\rๅด็ฎ˜๏พž#,w๏พ›_&co,๏พ–็พค,?l<GP๏พŠd๏พ…ๅ‰–W?1?\"t\\\'๏พŸN7?H๏พ—g?+๏พ†๏ฝฝ๏พž็›†ๆƒš๏ฝป๏ฝถU_K]?%O*ๅ—ฃ๏ฝฝ\nๅ’ฝkๅฃผOKๅœปU๏ฝฒ็—ฟ^๏ฝฅๅทฅ๏ฝธ็ญG๏ฝฉ#t๏ฝซ-๏ฝฆN mๆญค้ฝฃ\\Mtๆฏ็–†_ ??๏ฝข๏ฝขnๅŸท?ๆญ้ฃขYEๅƒ๏ฝฐๆ—?ๆ”ป%๏ฝฝXๅญฑ?a+๏ฝฌ3@? D๏พž๏พ’๏พ˜>F~ๆŸ†T^๏พ‹๏ฝกYO2\"๏ฝถ๏พ•๏พ”?๏ฝฟ๏พ’ไฝ‘?๏ฝด?๏ฝข่จ“้‡ถg๏พ—?\nIai๏พ๏พ‡)?\nWF๏พ…H?(?ๆœˆeV้คฝ?ๆ†พ?ๆ†งjW๏ฝฅYๅงช๏ฝฌ?๏ฝฝx้–ข?๏ฝฑ5๏พ€?##?0?\0H$.๏พ™?K๏พƒ ๏ฝตk???X?;??๏ฝธ\rwๅ–‰-?7.๏พƒ?๏พ„?๏ฝต8s 2๏พ€X?f๏ฝซU?๏พ—C*\"๏ฝง้ซญc๏พœ๏พ—3่„ฃ==H๏ฝฟ?)๏พ—?๏พŸ*ๅญ?|๏ฝฃ๏ฝพ[?๏ฝพ^๏ฝพ๏ฝต?E??็ฒŸW๏ฝญ๏พ„|?ไน—f๏ฝฆkๆ”ด=?X\"XX๏พ–๏พš่ฑข\\_ b๏ฝฐ?\ZQ๏ฝค้…˜๏ฝฒๅ˜‰ c]r๏ฝง๏พ•๏ฝพ๏พ€gAmd?,๏ฝฌ?-๏ฝน๏พ—?>็ดฏ๏พ‰VOๆ‰ˆw๏พ˜0ๅญ€๏พ†๏พ”v๏ฝท๏พ‹?๏ฝขL้Žฐโ–ณ๏พšIใ‚†u๏พ•g-+f?้ฌ˜?D้ฐฏe#๏พ$ๆ“พgDeb๏ฝฏ?๏พƒd\ZHไปถ?)%ๅค™T ?๏ฝฃ?,\nๆฉข๏พœr?6?P?X? ?ๆดป็”บi,๏ฝดๅ‰ณ๏พ‰Nl?Q๏ฝผ*๏ฝปK G\0๏ฝฉA;k w๏ฝฅ}+??๏ฝข???้ผก้…Š?\0๏พ›๏ฝฎ๏ฝฝe๏ฝซ๏พ้Šœๆผฟ-?๏ฝบ่†€๏พˆ?#๏พNT$ๆ€๏ฝธๅค๏พƒ;?A?y?% ๏ฝฅ่œ๏พ‡๏พ‰?IZI๏ฝพ๏พ๏ฝต๏พ’K\Z๏ฝฌไปŽrWr?8?๏ฝฐๅฃœ3๏พžfๅด๏พ˜?\r๏ฝฆgMLtnV<{Jๆ‹’๏พ8T?V????ไบ•?๏ฝฅf ้ฏก๏ฝต ๏ฝต่–AIcd\'o๏ฝบ๏ฝฑ]?e?๏ฝฟฯ†๏ฝญ;็“ถ-ๅ”ฎ๏พ…b\0?๏พ•ๅฅ‡?๏พŸ?6?\n๏ฝบ??๏ฝถ้ฐ•G]๏พž?๏พŸ ่€†Z๏ฝซ?๏พŠ?ๅŸœ;๏พŠ|?๏ฝต|9็‚บ*#็ขง๏พ—N๏ฝพG??\0้›„=z1๏ฝจ๏ฝพ๏ฝฏ?\n็‹—๏พ๏พŠ๏ฝข\"?๏พ†๏ฝต?*??๏พŠ??๏พŠ\'?\'GCQๅทป๏พŸๆŽ’๏ฝช??\"xDj9๏ฝพ|/๏ฝฅU๏ฝพๅทด#?}J๏ฝฉ้‘ ๏ฝป>๏พ{?๏ฝฟไฝฟ๏ฝฃ็‡ป๏พ˜8๏พš๏พ›็”Ÿ?C%๏ฝค๏พ3?3๏ฝธ๏พŠGใƒฑ๏ฝง๏พ›้š—_๏พ’?9๏พ‘๏พžH๏ฝฐ๏ฝฐๅˆณ?\Z? ่ข$)๏พŸM??>}L๏ฝปๅฏพv?u\r?-๏ฝฝ่ŠฌB๏ฝธl??R!ๆ“[๏ฝฆ๏ฝฑไป•\r่‰ฎ?ๅœ–d?๏พ›๏ฝจ่”ฝ๏ฝฒGO*๏พ…๏ฝถ๏พ‹๏ฝฐๅฅจ๏พŸl?\0M๏ฝก?>๏พ›3#ใ‚ˆGๆŸ๏พŠ6a?B่ฎk\Z3o?๏ฝฌๅคC็‚ŽF๏พ•่–‘?:ไบค๏ฝช๏ฝก๏พ€\"%?&?6$ ??\0}๏ฝพ๏พ‡้„o๏พ”X?)๏ฝฟ?๏ฝณo๏ฝง?fW้“๏ฝพๅฏบ๏ฝบๆฎŠ?+ \r๏ฝพ๏ฝช๏ฝญ๏พ–?๏พ‡Oๆญณ?*๏พ„ใผY$o่ฌ›Z๏ฝ€๏ฝณ??!EF?2 ๏พ–๏ฝญ=่—ท(??๏ฝฎ้ˆทuR?6u็›’q๏ฝค?๏พ“๏ฝฝๅผๅฆ{๏ฝฟl็ญฌ_*KL?๏ฝข/๏ฝฐ๏ฝป๏ฝน?!?caๆ…Š%ๆ˜ฟ??ๅˆ‡่ˆŠ๏พ‘๏พ‚้‚ตI%๏ผฉ๏ฝฝ๏ฝจd?๏พŽ{]\Z#Y๏พ’Ukr+๏ฝญ ๏พ^๏พ’SQU๏พ•๏พmxA๏ฝฆWยง\n?!ๅ…Kๅฉw๏ฝคๆŽขX๏พ˜P๏พ‚ะฎ๏ฝบ#ๆฟ 5ๆผ=๏พ‰X๏ฝนTb๏ฝต๏พŸGๆธฆ?<\Z7ๅถŒ๏ฝฒ๏ฝฒ๏พ„?๏พœ้ถด๏พ ?7๏พ๏พ–?,@!1๏ฝณLK?๏พI&&?๏ฝคไฟฃ?8?8#1>7=T47rRVY^๏พ—?6๏พ„$3(๏ฝก๏พW?8?q๏พžP?๏พ›DEx๏พ€1^้†ฏ#ๅฃ‘Q็ฒ‚๏พ…sๆ™้ฎจ??Sd๏พ็ชฉ?็ถด ๏ฝฆๅˆŠ3h=๏ฝฅ?@โ€˜๏ฝจ๏ฝฐไน™jf๏ฝณ$V?RV๏ฝญ|๏พ•๏พ„็ฅขๅ‡‹?ๅฟ  ้Ÿœ๏พš๏ฝฏ%?[L6xz้†ซM๏พs?u๏ฝฆ$x2๏ฝณ?\"\0?!c๏พ•Q?$่–ฆ?5้คŠV๏พœ๏ฝฌ๏ฝณD\n?k ั‚%๏พ0๏ฝพT่Œ‰๏ฝฝ๏พ…๏พ@?่ฎ“๏ฝซ๏ฝฝ๏พ??M๏ฝจ๏พ–ๆšผ๏ฝก{ๆ‰๏ฝฃ๏พŒ{?:๏ฝน๏ฝจ๏ฝช[๏พ˜๏พ‡๏ฝณ๏ฝตๅ‹บF?[b?#B๏พ›+ๅคœ๏ฝก}=๏พ‰\\๏ฝด?&D?&๏ฝญfIg1,MjZqBๆ•X?%๏พ˜ๅทฝYQkXT?ๆฝบ้ฏ’^!๏ฝฌu๏ฝต8+ไฝปrIj๏ฝฌK[๏ฝนi๏พŒ n{&4i๏ฝข?8j๏ฝตๆณŒๅŠต่ธˆ๏ฝผ๏ฝฐH้ปŽy\Z?๏พ—๏พ่ญ›\'4๏พž็‚ธb๏ฝพ?๏ฝฎๅนน๏ฝฅ๏ฝป.๏ฝท%๏ฝต๏ฝฅ๏ฝปH)@~ๆฟ :๏ฝบ่ณชE[AJHBD8W๏พ’๏พšCX!X๏พ—๏พ‰ Gะบ3๏พ™๏ฝฏr๏พ…? 5?ๆกœ?\0๏ผจt\\?eๆ”ธ2pๆจบ+,?็คบ๏ฝดkrn(eOZ๏พƒ๏ฝขd\"ๆฐธ??๏ฝก#๏พˆT๏พ‹๏พ‡?2W?\r๏ฝถ๏ฝค๏ฝท๏ฝต?\0 ๏ฝธ?(๏ฝผDๆ„ฟJJ4]w\0V็ž>?#่„ฏ)g*็–ผ?.ๅ™ด็›ฃ:๏พ‰@y&>]๏ฝจ(s๏พœyFa็‡GZ\0๏พ‹izM๏ฝฉ๏พž,+๏ฝซ๏พ“๏ฝฑIQJg๏ฝฐQ๏ฝคM\r๏พy#่ฝŸc\n??zฯ‡mE๏ฝฃ๏ฝก|M{๏พ›KrL];ไบ‚q๏ฝถ5?๏ฝด??\Z๏ฝต?I$่ญ˜6hโ”ฐY๏ฝฏ?t้˜?]dd\'่ป\\r๏พ—\\๏ฝญ๏ฝจr6ek๏ฝฆ?$q๏ฝกๆจ0่ฑน๏พ›w๏ฝฅU๏พ™๏ฝคE*๏พŒ8๏ฝนcๅ’’๏พ‹y\0๏พƒ๏ฝต^z๏พ—dy\"๏ฝฝ๏พ–fSEG_๏พˆ๏พ’BaQ?KL๏ฝฃ๏พ—๏ฝช๏ฝญๆ™ฎ3๏พ‹(R๏พ•Nๆœ•?H?๏ฝฐ๏ฝน=O๏พš๏พ”๏ฝป๏พ้ปŽq?๏พƒ๏พ…!ๆฃงๅพด่Šฝ๏พ’?\Z๏พ’??๏ฝค๏ฝตE?๏ฝณV?#{2ไบญ??\n?๏พ็พŒ3๏ฝฌih๏ฝฅๅ‹งn๏พ„๏ฝด????๏ฝณ๏ฝณ\r๏พ—ๆงŒๅญณ๏พ˜โˆฝ๏พš๏ฝคvH๏ฝดZ{~N?5ๆˆช?h๏พ?\0FEd๏พ’๏พŒ๏พŸ?๏พˆNๆ™??๏พœ????๏พ‰?CI่•‰้ฌฃ๏พ›๏ฝง๏พ”C่ณช้œ็žฅ็ธขW๏ฝต๏ฝต๏ฝก๏พ•d๏ฝน@j?0๏พ…ฮฅ๏พ’๏ฝฒEๆฆ‚s่คช่‘ฌ๏พ”๏พš็™’ๅ‡„๏ฝก๏ฝฐ๏พ™ )*๏ฝคiๅˆ†m0ใ€?๏พ“L?H\0๏พ”๏พ‘ๅ ‚๏พž@>\\?OM๏พๅ†ฒ่‡ ่ค‚?๏ฝฌ?L=๏พŒ๏พ†?๏พˆ\r๏ฝท? y๏พ˜!?:๏พ”๏ฝท???=?๏ฝฝ~๏พˆ?่šฃ๏พ˜?๏ฝง#๏พŒ๏ฝดc=V่•ชๅ€๏ฝฌ๏ฝค่’‚็ƒน;๏ฝฒ็ฅ๏พ‚?\0ๆ…“%๏ฝค้ กq๏ฝฆ? ๏พ˜2?\Z๏พ—xo็ฟŠy?๏พˆ?\0?๏ฝป?#Z่ฑ|?๏ฝง๏ฝง๏พ‡??่ผŸ๏พšSWl1\\ใ‚ฒm่ฌ„่™<๏ฝณ๏พ?5๏ฝท๏พ6?GD้‡v๏ฝซ่‹“??่šซg?๏ผฅHDnใดXๅฑ\\ๆฝ}??๏พ’.?;H๏พƒM๏พ™?$X?i[1v๏พ–๏ฝฝ๏ฝฟ้ดƒ็งคD๏พ๏พš็Ÿณ?๏พž๏พŽD?ๆ–›โ™ฏDk%๏พŠ๏พ›๏พ‰4?ๅทฝๅšข๏พ‚X?(๏ฝฉ;ๆš—\0่…†?c ?๏พ“๏พšwM๏พ‹๏ฝฌไป‹Gๆพฑz๏พ‰๏พ‡๏พš,Zๆ‡ฟ3๏พ™?+๏พ‰๏พšV๏ฝฑ<;็ˆ๏พ…\r๏พ๏พ‚5dlๅฎŒ@lVz:?ๆงฟ๏พ•?๏พ•oะฅ๏ฝฝ๏ฝฏE?ๅฒ*?๏พ?๏พ•Us\n๏ฝช๏ฝฉ้ฝ>๏ฝพl?:::::::T??9 ๆทนK๏พ‚๏พœO?;]๏พ‰<ๅฒซ๏ฝง๏พˆ?3๏พ•๏พ:R?๏ฝญ้™ฐ๏พ‡?๏พ„z๏พ€,\n?๏ฝฐ%??Mๅ‘ถ๏พ€<๏ฝฎ?2ๅฃ•๏ฝฉ่•พ๏พ‹?(ๅฅ=K้ค ?๏ฝข\"\"?๏พ‹้†‹#๏พ“๏พ‡๏พๅฎ๏ฝบ?ๆดซ๏พ6G7๏ฝฏ?r๏ฝพn๏ฝต6๏พ–๏ฝผm๏พš?ใƒณ?U๏พ—๏พ ๏พœ๏ฝก๏พ‰1๏ฝถgGx๏พ’c๏พ‹g,\\;่บ™?s๏พ… ?6l?)/O๏พ›ๆญใ‹i\nๅฝฉ?}่—ท?l $๏ฝฟZ๏พŒ๏ฝถF,]7๏ฝฑ)\0๏ฝฑB7P ๏พ็—่ˆถ]?7๏พŽ๏พƒ๏พ†้šจ๏ฝค???\0N~.?vๅฐ…?<8่Š™r๏พ่š“^๏ฝป?9e้šŽ\r๏พ#\0๏ฝฟ๏ฝฉEZo๏ฝก๏พ„)fHdๆผ‚\ZI๏ฝผ 0๏พIo ๏พŽ๏ฝท๏ฝท๏ฝฒ4๏ฝฉ๏พ’XOๅ’๏ฝขi%8I?\"Gไฝฐm๏ฝซ่„‚$$ๅ‹l๏พ‘๏ฝต?๏พ’๏ฝต?$H๏ฝฎz+๏พœ่—\"?Xr0๏พ‚ๆƒŸfๅท–๏ฝฝ6\n๏พ˜\r?๏พŠ๏พ‰,?\r?๏พ‚*็ ’๏พ?่กฟt๏ฝก๏พ‰้ก??๏พžf็ฉ€{๏ฝซ๏ฝจ&๏ฝฒyl$ ๏ฝฃ?2๏ฝฐFV๏ฝฑ\\๏พ‘๏พ๏พ‘๏พ€q ๏พ|Q๏พ‚???,?%ๅ‹น๏พ›๏ผ—I๏พ—็พŒ๏พ†?,๏พ&$?vX็ฌ‚?!@;lN?ๆ ฉP่ฃ•@#๏ฝก้€‹ๅก˜ๆคŽ \r?#๏พ’\"ww?e l้ฆฅ;APฮปๆฅ<๏ฝผ?๏ฝน้ค”๏ฝฉ่Œจ๏ฝฐ?\06?0??R5??;$้ถ\Z๏ฝช่‹บ!๏พ‹?่†ˆ๏พ…๏ฝฝ้ฝ’่‹ž่ฉซ๏พ๏ฝน&๏พŒkl,๏ฝต๏ฝฎ,7่ญ˜$i\Z??ๆคนG้ดป<๏ฝฌ2๏ฝฝ?๏พ—๏ฝญ^?^๏พŸx๏พ‹่ฟฉ๏ฝผ]๏พŒ๏พ๏พŽ่‚ญy\Z?Y.2ๆ€ๆฐพ่•ญPuๆพŽgS=E๏ฝธ็‡ปA็ฌ4O็ซๆ›พ๏พZDs/๏ฝขW๏ฝน?-๏ฝถ๏พ:ๆฐธ7?;?rMๅœฆ?!่ฑŽ๏ฝฌ๏ฝฅๅธฏH)?!๏ฝบJ#(๏ฝฆdๅบ—4?l๏ฝฉ??\nx๏พž๏ฝถๆ”…ๅผ๏ฝฑ๏พ‡c%่—ท ๏ฝฑ๏พๆขขY*Q๏ฝด?DH&๏ฝณ?3ๆกU%?๏ฝฎ๏พœ?๏ฝท?#๏ฝฏzX๏ฝงๆขน:?5X๏ฝฅ๏ฝบ๏ฝถ%YnD?7ๆ˜ถL๏ฝงex๏ฝฃn?๏พŒW็ด‹y่ฅd?๏พ†?_๏ฝฐ๏ฝป็ซกI?8?ๅ†ฒ:*๏พ่ซฑLBV๏ฝญ }dSD๏พˆ_ ๏พ—๏พ‘๏ฝฝ๏พ—๏ฝถ$่‘ฌ๏ฝฑๆกŸ๏พƒ\"9่ฎš๏พ•?Q๏พ‰? ๏พ•Zะ‘j๏พ๏ฝซๅพ˜้กณX*๏พ‡\0ไผ\"gๆนzC๏ฝฃๅญค๏พ„๏ฝคๅ€ถๆ’ญ-?๏พ•o๏ฝญ๏พŒ็ฐ‡3,ไฟธc xy๏ฝคIๅ™EdN?X้ž๏พ‡๏พ…?P้™๏พ‰๏พ;๏ฝณๅฎถE๏พ”?๏ฝทy ๏พ—X$ur๏พŒ?&๏พŒP,๏พŽK?่Žต?\':V๏ฝณ9็š89G;Y๏ฝฐ๏พ„??J๏พœๆธฃbd๏พq๏พ?A4๏ฝฒ\Z?*๏พ‘H0๏ฝฏ๏ฝช?J+่Š\r?$,ๅ‹ž|?๏ฝฏ4?M-?ไบฐ?๏ฝบ๏ฝฝd?๏พ˜9๏ฝนJ3\0?\"๏พˆ?8l .P๏พŸgP๏พ„๏พ’H{๏พ†ๅ’๏ฝพ( {๏พŸ$๏พˆ๏พ—ๆ”ปH~่ŠF๏ฝช๏ฝธ.๏พ‰ =๏ฝฅ๏พ€๏พŽ๏ฝฆ๏พ–\\๏พ“๏พ—k?-็›๏ฝฐ่ด9^้„๏พJๆฎฒ?\0๏ฝณ็ฒพ?l&$๏พ‹๏พ“-&่ฟน๏ฝถ๏พa่จ“C๏พ†-?1mJ?;A๏พšC?ะ‘+๏ฝค)o๏ฝซ]mVnh่ข’๏พ†+้‡ฆEx๏ฝพ a๏พšๆผฌ๏พ‰In)#๏ฝฆ็ฑ?๏พ…๏พ‰?!<5่œฅ7jq๏พeๅ”ณ๏ฝก* ๏ฝฆJ? i๏พ›$ul๏พ“K็ฉด๏ฝผ๏ฝฑX๏ฝน%ๆ€ฑ่ฟฝ?eๆถ“๏พ“๏ฝฌm๏พ–:Dp๏ฝธโ™‚๏พ™WieDๆœทY๏ฝจ๏พ‹๏พ‰๏ฝคn3P็ฐ๏ฝพ๏พ’Tๅ“Sv๏พ‚h๏ฝต$่ชฅ๏พŠ๏ฝถ\"W?ๆ„ฟz?x?;Ye๏พ‰\Z๏ฝซ๏พ•๏ฝฎkl]?g\'๏ฝฒ๏พŠs??O๏พ‹|๏พŠ9๏ฝซh?G๏ฝฅ๏ฝฉ๏พ™??๏ฝถ?? ๏ฝพๅ‹็ผ\nQ\'๏ฝด]nๅŸ๏พ–t๏ฝณ?,2J๏พ”Ww๏พ๏พjy?/๏พ‡1?(e๏พœ _3g๏ฝข๏ฝญๅ‰ฉaC๏ฝฃ.๏พ‚๏พ€๏ฝฉ๏พ˜y-็›ด{Ai๏พ?๏พ›X๏ฝณ้ผA่‡บ\r??ไบซ6๏ฝฅ??p๏พ™๏พŒ๏ฝซi๏ฝถ?m้‹ฒ*E}L ่ธช๏พ™UPV้™Ÿ๏ฝด\"!D๏ฝน๏ฝถ\0?\n0X๏พ‰๏ฝขEs็ธ’H๏พ‰^๏ฝฒ=็ฉฐB๏พ…c?๏พE๏ฝพ๏ฝต๏พ›0[?.๏พ๏ฝฌ}ๆ„ผ๏พ“้›ซ็พฏ#๏ฝด?;2๏พˆHe่˜l$(]iZ;่ผ?\'็™พ)5XmW?l๏พ•๏ฝฟ*gๆœฌ0๏พŒbw่‡ฅ?8f\r๏พŠ>?,๏พ„๏ฝจ?5๏พ–?g?ๅ‰ช?:;ๆŸฏๆƒ‘[\\?๏พŽ่…rWm{[9?(?2?ๅ 8?c?n๏พ“้™บ=๏ฝจ๏ฝค๏ฝพCN๏ฝจe5่ผK%๏ฝฒ๏พˆ๏พ˜q?๏ฝจๅญ?๏ฝต=I้งขๅฅ‰๏พ•G9?b?๏พŸ?*๏ฝช5~Uz๏พšg??/๏ฝจ๏ฝทk?๏พ™๏ฝข๏พ€.ๆฑณ?w<่ŠนG\'X=+?่ณฃ๏พ•-vๅฝผ>?x่žซ๏พ›ๆฝ”X๏ฝซ๏ฝบ๏พ˜๏ฝก? ?=r?๏ฝฐๅ–ฎ\Z๏ฝท.๏ฝซO๏ฝฆ๏ฝต>๏ฝข๏พ˜2k๏ฝญ๏ฝช๏พŒ*๏ฝพ๏พa?B๏ฝฑ ๅˆง03!๏ฝฌ?๏พ…?7้ฎซ๏ฝต๏ฝฒCV๏ฝพๅ…‰r๏ฝญ~[C็จฟj๏ฝซ๏พ’&\\P?!?๏ฝฒN?=๏พ‘*๏พˆ???0m? m*0๏พœ่ปขๆธฉ>๏ฝฏIN?๏ฝฐVYu๏ฝณWg?*rV?๏พ”? ๅงซS-c?<๏พ›P3้ ค5-.r๏พ”?H].๏ฝก๏ฝฒ๏พœc??ๅž *h0?๏พ?Yo?็ญ‹?g๏ฝช้ญŽ?๏พ•?่•พๅฅชไฝฟ}้†ด๏ฝบ๏พ๏พ‡?6๏พ…\\๏พ˜h๏พ‡ๆฃ g9e?5?B๏พi๏ฝฐๅ‹…๏พ”2๏พ“?|H=t๏พ4qf\r\n?๏พšlN? ?!ๆˆ–๏ฝบๆข—\Z๏ฝญ/๏พ“๏พ‰I,๏ฝข๏พ˜่ณ›pC๏พ‚๏พ„J๏ฝฒV1?2?<;7๏ฝฑโˆฝg?rMZ?๏ฝฏd๏พ~Hๅณ่›น๏ฝค\\PH??2๏ฝณr๏พ…๏พ—nO?UๆˆŒRk7}?๏ฝซๆ†๏ฝถๆ‚’๏พŽ๏ฝค็ดฟ่ก†[F^๏พŸ็šด้‘ ๏พ‰9j๏ฝฉ4W6 K๏ฝฟ๏พœ๏พ™Vใ€†ๅ‰ฑ9๏ฝฐ๏พŠ*๏พ—๏พhM0๏ฝณ๏พ‹6}๏ฝซe4w๏พ‚u๏ฝฝ๏ฝบn??9 {c๏พƒq๏พ„๏ฝฃA๏ฝช๏พ๏พ๏ฝน๏ฝผ๏ฝณไผ๏พ„?~๏ฝขC?(\r๏ฝจk?๏พu?๏พ‹?y๏พŽU?\"F ?C\rCๅ‚‘๏พ–ๅ“จ?๏พƒ้ญŽRU๏พ•K]A๏ฝก๏ฝผ้ŠƒANC๏ฝดๅ–™๏ฝซR๏พ†dA๏พ‡๏พ“\\๏พŠ๏พ‚46๏พ€๏พƒ้ƒ?5\rIJ๏พ‰?i๏พ๏ฝจ4?4๏ฝฏX๏พ€Q๏ฝฑ๏ฝชl8?W๏ฝข่…ธYZ๏พV3Wๅด๏พ’Wๆท‘dv}๏พ‡aBp๏ฝฑYs?๏พ‹ๆด™๏ฝฃ^๏พŠZๆŒŸ?(z๏พ•e๏ฝช่œš๏พ–/??L๏พ ?่•Š๏ฝฌๆ‰‡?b?\Z๏พ€?\Z|?้กดq็ฒฒ??๏ฝก?&๏ฝธJ๏ฝป๏ฝฉ?>K๏ฝฌr?ๆ‹ถ\"\"\'ๆŠซ?y\"๏พ‰ ไฝฏ้นน??m๏พˆใบ%.r๏ฝบ๏พˆ๏ฝฒ๏พŒGm๏ฝญ๏ฝผๅฏ›b๏พ…๏พGS\\๏พ›ๆŸ”๏พ•C?F๏พ็—ฒ,๏พŒๆ›พ<๏ฝช๏พœHl็‘ฏๅฎrt<_้ ’๏ฝคS็ฏ๏พ™?๏พ‹๏ฝธ๏ฝญ๏ฝณโˆ‚V๏พŽ่œœ?)r\0?\n๏พŽ๏พ‘?๏พ‰b?,?๏พ‡??ๆ€™๏พŸ๏พ‰ๅพฉ]SuKs๏พŒ?ๆจ’ๅกขk ?)q?4?G?0yฮฃ&ๆฟก[FH??\0๏พ•\"s้ฏ”ๆ น๏ฝฑC?๏พ๏พš?\0๏พ’๏ฝบ๏ฝธs๏ฝง๏ฝช็พ†๏พ็ฝตะšb๏พ•(#๏ฝฝ6A๏ฝซ๏พ‹%x้ฃฝ๏ฝญ?h$w\nL?}๏พŠ/-?5๏พ“Dzๆ›œ๏พ˜๏พŽ๏พ›๏ฝฟ^ZI\\้‰ขe๏ฝฌVJ1N๏พ๏พ+i๏ฝฌQ? J$๏ฝณ๏ฝธd็ญฎ๏ฝง๏ฝฆ๏พ๏พŠ|yG๏ฝบ่–‡b๏พ‚?\0-ๆบบ๏ฝพ่“L๏พˆ? ๅฏคl๏ฝญ?๏พ๏ฝฅๅฏฉ^<็›_-๏ฝฐ๏พ˜h่ฟš๏พ‡W๏พ„b?t%? ?ไป–??้ถ๏ฝท๏พˆq? \\?em?๏ฝฌ?KoW๏ฝผ๏พŽ๏พ}cAv ๏ฝฃ?3?!๏ฝด๏ฝฆC ๏พŸt๏พ™ ๏ฝฐๅธธ๏พš๏ฝซ#๏พ“๏ฝง-๏พ๏ฝฏp?\"_r๏ฝท%XD8E?1็œฅ๏ฝญๅนŒTiPVN๏พ‹?๏พŒ!๏พ‰!๏พ•?Ia\n[้จ&Ll็ฅท๏พ™\":)ะณ=๏พŒ?็„”๏ฝณ?;N???+P-gwQMU๏พœ๏พ‡๏ฝถ๏ฝธX๏พƒ๏ฝฌd๏ฝป๏ฝฉ๏พ‹\\8๏พ๏ฝฝb\ZAy๏ฝฏBtใจ?2๏ฝญ๏ผตP๏พƒ ๏ฝฑD๏พŒ?6m?,n\n?็ฎ‡%ฮบK#๏ฝถ๏พ—๏ฝง0ZrF(๏ฝฌ๏พ›-??\"่ฒฌ?*?๏พŒ๏ฝฐ๏พŠ/๏พ‹๏ฝข๏ฝจ?R1E8๏ฝขO?๏ฝปs]/dๆ’ผ?/2Gy๏พƒ?7้ถšh??ๆฌ??h๏พ‰bE4H5X๏ฝฟn:76\".??8???.๏พ—1๏พšO)jD|๏ฝฟPU๏ฝปbN๏พ„v๏ฝฎr9d็ฏ‰๏ฝฑ๏พ‹3๏พ”w??n๏ฝฑ?๏ฝก๏ฝคb7?้ ค้ŽŒmKๅฐ8็ต–xy๏ฝซ๏พ ็ฟŒ๏ฝณ=c\Z๏ฝฏp๏ฝฌBrW?j๏พ„<๏ฝฏ้…ฉ้ฃ›?N?/๏ฝซ๏พ‚?๏พ‚\"\'่ฌฌDETDo๏ฝฉU|\"\'็ฒง๏พ‚?ๆฒปDlv?\0N๏ฝฏ?TjlI๏ฝฉ8;่ˆฉEะซ%?#<#?0?ๆ˜จ๏ฝชๆผข??๏ฝข๏ฝง๏พ‚๏ฝง?๏ฝฒๅ‡งW?E?5EN่‹ฃ\0jg๏ฝฐI๏พ„๏ผฆ?๏ฝฐvN3๏พ0?,##๏ฝฝlz๏พ‰bV9๏ฝฉ?-๏พ…q๏ฝฉ???\0๏พš๏ฝง??\0ๆญฏn\'่š“Oh\"๏ฝฝ๏พŽๆ›ฐ?\0๏ฝถh๏พ‰y๏ฝพ๏พ๏พ“F๏ฝฑ๏ฝต๏ฝซ่ฅท\"H๏พŸ(่†‚๏พš?ๆธฌๅ–š?I๏พ„้ž‹{๏พ? ็”ฃ?๏พ„๏ฝฆj่…ฟ1๏พ•๏พŠๆฟ†?็ดฒY๏พ›?b๏พŽ๏พ›๏ฝถ๏พ„4๏พ‹ๆ˜”KJ9๏ฝชc๏ฝค๏ฝฒDEไฟพ?๏พ‰๏ฝข๏ฝดq๏พˆ#<๏พˆ7, ๏ฝงๆ…ถbK็žฌ๏ฝฟXๆญข)??)k๏ฝญ?Cy\n๏ฝนC\Z*Z3๏ฝฒๅˆถ๏ฝจ๏ฝฒ๏พ›๏พšๅพ‘?๏พ.?๏พ๏พ‹2๏ฝข๏ฝดv็€งๅปทๅ‡ช*\0cL.??่Žจ?3S๏ฝก?xM็‡ง?๏พŸb๏ฝฉ)?๏ฝฅ๏พ‡6bU๏ฝญ็บœ๏พ†? ๏ฝน}๏ฝด่‰๏ฝป๏ฝถ gJtLH44?X\"?๏ฝฆx๏พ˜??H๏ฝญ๏ฝช่†ˆ~ๅฃ™[0๏ฝถ้ผ ๆ€ฅ๏พŠ๏พŸ?๏พ–A\\%๏พŒV?=e\rๆ‚งIa๏ฝค๏พ‹ใ† F็ตž๏พž๏พ€๏พ‹ๆŽง?Dๅš€m๏ฝปd่ณ?+๏ฝด๏ฝน็ฎ’ๆพน?N๏พ–๏พ›๏ฝป๏พใƒ„q๏พŒ=๏พ€๏พŸ๏พ•๏พ˜็คช- ๏พ’yd>๏พˆ~๏พŽ่ฑธๆจ…[\Z๏พšd๏ฝค?๏ผˆๆฟ†็™จ๏พ–\n?\r9๏ฝฆ?%v&[?๏พ‹ๆนฏR??7?๏ฝฉ@๏ฝฒ\Z๏ฝฌ?๏พ’\"%็‰™็พ*?๏พ†^?๏พ€ๆง? B$H?(?๏พ—๏ฝท$๏ฝฑ?;E2ๅกž%๏พ™๏ฝฝ๏พ„n7=5๏พˆ๏ฝฐ.๏ฝฝ่ฃ„9๏ฝณ?ๆผธ่‡พt่ฆ“]k๏พ‰็ด๏พœj๏ฝน?๏พ›ใ‹๏ฝณyb%W?A๏ฝง.๏พ‚๏พr๏พ๏พŒ๏พ’๏ฝฏ๏ฝบ๏พ‹$๏ฝฒ๏พ‘?7]ๅคฒ?๏พ€๏พ๏ฝบ?1ๆฅขs\n?cp๏ฝฝ๏ฝบf๏ฝฌsๅ…ช/m.่Ÿ‡๏ฝณ๏ฝง่ฌn.ๆฅท๏ฝถ+f้ท‚n๏ฝพ๏พš?\0?๏ฝฆs.\n2<\n?3\'โˆฝ๏พŽ??Tๆ„๏พ‹?h??W๏ฝฎ๏พ“.?๏พœZT๏ฝณ๏ฝค๏พ nA๏พ‹๏ฝถ4๏ฝฃ\"๏พ€๏พš๏พ๏พ’Wๆ‹ฎEh๏พ–?;H\'๏ฝกๅ€…็—‚๏ฝต?p?5q?;ใƒœt๏พZv็ฟŠ๏พ?๏ฝฉ๏ฝด๏พ—9๏ฝซ๏ฝก3๏พ™z่น„็ถด?T:?๏พŒU?Z๏พ˜deๆธฉ6่œทq JD๏พ…K๏ฝฉ๏พ—2๏พƒๆšฆ๏พ—็ธซ็ t๏ฝซ๏ฝด๏ฝฐ๏พ‰M_^Icx)๏ฝฉU?๏ฝนy๏พˆ ๏ฝทjJๆ–Ÿ๏พ”Ndๆ‡ธ?>ๅ…ธ_๏ฝจn๏ฝญ8R{ๅœง๏พ ้Œ†$?๏พ—้ฎญ๏ฝฐ?b????๏ฝง๏พ”cๅž‚๏พ็‘•k$? 5\r/๏พ๏พžXQ๏ฝŠ๏พ8%่ฒง๏ฝณE๏พˆไบฆ๏พ€v?a\n?๏พ›?9ๆฑ‚๏พ“W+?\"x?๏พ˜@?,๏ฝฎ?g#๏พ•R?\nJa๏พ…๏ฝฌ๏ฝณZKK๏ฝข้– ?*๏ฝฟ๏ฝน*๏พŽ๏พ’๏พ˜{/M}pๅก็ˆ›๏ฝป๏ฝช๏ฝผ๏ฝฝ๏ฝท๏ฝถ%lep๏พ„?+gH:}Y๏ฝฝg๏พ„u\Z^๏พŸ?:,๏พ๏พ‡,\Z?๏พ‹?๏พœr?๏พ„ๆˆฒ๏ฝท๏พ๏ฝค?๏ฝพ๏ฝฟ?5?๏ฝฉ5e ?rvh๏ฝขI? ?ใ‚‚?.๏พš?๏ฝซ?|ๆต™็ฝง๏พ™ds?bk?ๅนขK๏ฝง่Š’v?&??\0๏พ“\\j๏ฝป)CZ&}็‰†? ็ฏท-E๏ฝป๏พ†ใœd??๏ฝบๆฅ”Xๅ™>ๅŽญ็˜Ÿ๏ฝข\Z#?3-ๆ‚ŸZ๏พ“่ฌ‡F๏พŸ?๏ฝบ่บ๏พ“ac๏พ”Iๅ‡‹i๏ฝข|?้Œจ่…‘?9ๅ‹˜ๅญฃ?+๏ฝธ๏ฝถY๏ฝฅ๏พžQhs{็šฟ๏ฝฌ๏พ…๏พ‰rsg๏ฝง๏ฝถ0?ๆตธl๏ฝฐg๏พˆ๏พƒ๏ฝข6๏ฝค๏พŠ๏พ˜\\kQ่‰8R๏ฝฌ?!:WQ๏ฝพ๏ฝฉ?7๏พ’ๆจŸ๏ฝบ๏พ‹?๏ฝน!K?? ?๏ฝฒ๏ฝฝ!|๏ฝจ้„r!๏พŒ\Z๏ฝฝ}๏พ‡ (?๏ฝนYๅตŒๆค„่—๏พ›่ทณ\0๏ฝฉ@Y่ฒžA\'z6R?๏พ–/๏พ“๏พ\Z4๏ฝฌๅท?##{Mๅฌพ๏ฝบK๏พ“?$๏ฝกX๏ฝพ?/=xjXD]?๏ฝป๏พŠ๏ฝฃ?็ตฎ?ๅƒT^Q๏พ†๏ฝฆ>๏ฝด?=~|D?\'่ฌฌDUWxO>|๏ฝซ๏พŠ๏ฝง?U?้Ÿ‹zx_??\0?I๏พ›๏พ‡??P?๏ฝธ?\0?๏ฝบ้ฐŠ(่–€??๏ฝฏ?้ผˆๅ–ฐ๏ฝฉ้…ฉ?~:็ฝ?็†•pv?๏ฝท?uS๏ฝฏ๏ฝถ๏ฝฐ๏ฝฌ> Ip๏ฝฆ:O5ๆ˜‚J๏พ—๏ฝค๏ฝญTj3๏พ‘?$j/๏ฝกZ๏ฝฌT?๏ฝช๏พŸO๏พ‡O?yX?็ง‹๏พŸ๏ฝถ๏ฝพ๏พš\Z[๏ฝธ๏ฝขSๆป๏พ„K้ญ…~๏พ’S]?\'?\'??I}๏พ™๏พ˜๏พ„่ณŠF๏ฝฑ<๏พ‘U>????\0h๏ฝฝz๏ฝฒG๏ฝต=H๏ฝชไธ”?J๏ฝฑ=/o?+<|?๏พƒ๏ฝผ||?? ๏ฝฝ๏พ“๏พš?#๏ฝฆ??efZ๏ฝถ๏ฝซ๏พ™ๆŸฑ๏ฝฌ๏พJ่ป›Dn๏พๅฃปไธถT๏ฝช;#๏ฝดM๏พ…๏พ“fU#AๆธพไฝปERj๏พ—๏ฝกA3๏พ‚?u#_๏ฝช๏ฝซ๏พx่žบ_๏ฝพ๏พ๏พ•?0WVeo?>ๆ—?!C๏พ!i?๏ฝฏ?#๏ฝพ~n???e๏พ‰?0??%?=?ๅ†ถEjE+๏ฝฆWF#่ƒฏU!|๏พƒ๏ฝดzn>ๆฏ˜ๆฎฑ9๏ฝฆ๏พž๏พˆ?๏ฝฉ?c5\"็Œถ\r]?ไป็ณŸ?C๏พœD่ค‡็š‡:\n็บ‚็นฆ๏ฝฌr็ถข?๏พŸ?1?s?๏พˆ7๏ฝฎ๏ฝฎ?&?๏พ‚ไผ้‰„?ๅฅงKqKๆ–ญ๏พ›?้€ข๏ฝซc?๏ฝต,? *E2๏พ„๏พ‰%??<7๏พ•\\๏พ‘๏พˆe\\?+?๏พ‘er๏พ‹>N\r<๏ฝค๏พ•๏ฝฒ๏พ†๏ฝฃ[Cv?6SN?๏ฝญP ้ค?็•ฐ??0\Z?\0O่’ก[9K?=๏พ™f?mD๏พ‹^#;?ๆ˜”๏พ’?$ๆŒ‡p๏ฝช_?๏ฝขK่„Š:? \\dBHaH่ฑน๏ฝฐ*๏ฝฏwโ”ฃ๏ฝฐ๏ฝญ?่–ฆ!Sๅ‹ ๏ฝฑ๏ฝธ๏ฝฝ๏ฝพ๏พ‡@ ?k๏พ‚65T๏พ•๏พ‰ n~{Y๏ฝฐ๏ฝต[ 3ๆฟƒm|?ๅฃ˜?F?\0ๅ„•E๏ฝฐ&๏ฝฅ=ๆธฌ\\?N#)๏ฝด๏พ็กผ8\'_[๏พžVO+ๅŠฑ?#?w%s?๏ฝฝ?๏พ๏ฝต?๏ฝค?่ช˜-๏พž๏ฝดB๏พ ๏ฝบ๏พˆๅฑ‹ๆฉKE \0ๅขจ??-?๏พ˜\r?้ฉข๏พ€&๏ฝณX๏พ‰r่†จ๏ฝฌ๏ฝฃ๏พ›[<๏พๆซบ#Y็•ฅ;>}?๏พƒ:ๅ•†?๏พ› ?7??\"F>U????;?iไบˆ^+4\r๏พŽ็ง˜4r8\\๏พž6?๏ฝณU!๏พ“๏พ‹_๏ฝฅ๏ฝปm\r๏ฝซ%๏ฝฟ๏ฝด\\๏ฝฝ็ฐฟ\\๏ฝฑb๏ฝกX๏พ‹lrKZ๏ฝกๆฐ“ๆ“ก๏ฝฆ?e๏พ‡๏ฝณ-j?๏พ˜?0wZ+๏พ…)8่’?่ณค๏ฝฒ?&w?^็”˜628๏ฝญ๏ฝก2๏ฝฝ?!N?3๏ฝณJR!&?b.?\"zๅ™ด?0b?๏ฝฃ?๏พ™?ๅ“‰่˜‚๏ฝฅ๏ฝฉ็ผบ๏พ„ๆฑพ?r๏พ–\0m๏ฝด๏พ?7\"X๏พ•:๏ฝฌ๏ฝช๏พœT?*sWOaๆจ—๏พ™H?็ข3ๅผ๏พƒdv็”‘๏พž?97?rd๏ฝนB?/(?4m๏พ‘?7?3X]๏พŸ$๏พ™<7d๏ฝธ๏ฝฉ๏พ“ๆŒฏๆงฝg?5๏ฝค่‡“<&1 Y๏ฝฃ้จ’๏ฝน+๏พ‰S?)o+x_ๆ’ฒx?๏ฝฆ็šธ[\ZA-4S๏พ’?^๏ฝถๆฉฆใ€ƒ?;?:+\Z?|ไฟฎ~h4๏พ“+,\'??C+๏ฝฝ๏พšw็ต›๏พ‚<๏พš๏ฝฆ้ ƒ?๏พ—c?t๏ฝธKh?qix๏พŸMg?้ฌผY ?๏ฝต๏ฝฒ๏ฝฏ\'๏พ˜๏ฝธ๏ฝฏ๏ฝซ๏ฝซ๏ฝฎ๏ฝณ?\0cK?;x๏พ‰!?๏ฝฒP๏พžๆฃฏT?๏ฝฏzq็ฅจ๏ฝถ+๏พ?4๏ฝฃy๏พ–๏พ€๏ฝฌ?\ZGe\\e0!๏พ๏พ‚ใ‚‡Pใƒผj๏ฝช4v๏ฝฑ?g๏ฝธๅง†-?/p๏ฝถ#,๏พ‚?<๏ฝถ๏พŽ6*#?K๏ฝฏ+?h๏พ๏พ๏พœ?~๏ฝป๏ฝญ๏พ‚๏พ“่ฉ๏พˆ?3๏ฝตXH?x๏ฝฒ๏พ“}T๏ฝฆT้บพ๏ฝญ๏พ•ๆˆฏ[T2[๏พ†๏ฝณ]๏พ”5?b๏พœ+๏พ˜?่„ฑ\'่ผฉCๆŸป๏ฝฆ๏พ›๏พ‡๏ฝบๅ†…p{N>^A๏พ‘a)uV:๏พŠ๏ฝช๏ฝญ<่ˆตQ๏พ‡ๅฟค*๏ฝบๆ‚›๏ฝฏ๏ฝฌ?๏พš?,๏พši๏ฝช*\'H\\ๆฟ‚$k๏พŸ๏ฝด๏พp่ฅฆ๏พž;??? ?y๏ฝฟ๏ฝน?๏พ‡้‡๏ฝก?#๏พ…๏พ•\"๏ฝธe๏พ“G!๏ฝด%D?/?๏ฝฃ?x1ๆšฎUg]{Mๅป๏พš่ทj*ๆขฆmๅฉช$o่พฟIp$ะ‘,่‚ข๏ฝผ?ๅฌ1๏ฝค๏ฝธ?!?_4๏ฝช?Z๏พŽ๏พ–็ทฌ็พˆ๏พš)h??$D๏ฝถ๏ฝช๏พŠ๏พ“+y๏พ‘๏พˆ $๏ฝญ๏ฝณ%้ผกI3EZXๆ†ง๏พ„๏ฝฒ๏พ€?h๏พ–๏ฝฅ[V๏พY๏พŒ๏ฝฒglv?w+!๏ฝฉh๏ฝฅ้ณฅ)๏ฝณ๏พ?#pvv๏พ˜?fEUTU_?Q|x?๏ฝช?ๆกŽUS๏พŠ?os\"xT??\'?Q???๏พ๏พŽ๏พ„?ๆธˆ??๏ฝฟๅบŠ?|?\' ?;๏พŸ???๏ฝฃ๏ฝฃ๏ฝฃ๏ฝฏ:::?S??\0I???๏พ‡\\tttu๏พ๏ฝฏsQZ่ฑZ่–คkW๏พŠ๏ฝท๏พ?>Q๏ฝบ?๏พ‚?E?;{???|??#]่›ฌ~W๏พŠ/?\'๏ฝฉ๏พž?/?7๏พŠ?:??>F๏พ‡๏พˆ\0?๏ฝฃ๏ฝซ๏พ›5๏ฝพ๏พ™e?๏พ’ๆ‹พd!u๏ฝฉ4Aๅ›ƒx๏พ‡้ฉ๏ฝฑ๏ฝณ๏ฝฒ๏ฝงY!้ 5๏ฝญl็ฐก๏พš๏ฝฎ??jt๏ฝฌ๏พ›?1๏พ‰่ฆ?I?\Z๏ฝซMๅœป\Z้ญ…Gๆšพ๏พœ??@่ถ?zr?e\"๏พ๏ฝฏ5ะธๅฌฐF5A.ไธ™๏ฝข๏ฝช\'ๅŸŽ?\'??๏พŸ๏พ›๏ฝฎ๏พ‰#ๅธ™๏พ‡???๏ฝฌ??๏พ“??๏พŠ๏ฝง๏พ‚?๏ฝฐ?+่ณŠ]?v๏พœu่‹Ÿ&hR๏พ„?~><&?๏พ‰๏พœN +?\0๏พ˜:??>/e๏พ–Y้ž…่„ฑR??9C?๏พ“?>wB๏พ…?AK\'n]??[C๏พ„๏พ™lx\\Y๏พƒGC๏ฝญ๏ฝฐ๏ฝถ?a๏ฝฒ*๏พŽ๏ฝณI๏ฝฟa๏พ•\r ้บ‘ๆฎบ่ตญ?=?(1๏พ“Azt?1(๏พ“๏พ™YLE๏พ‰๏พˆP?๏พž๏ฝช๏ฝพa๏พŠ๏ฝจ็นป๏ฝต๏พ–๏พ€?6๏พˆ_]๏ฝบ่ดŠ?๏ฝฒ๏พ™้Ÿ‹*6 ๏ฝฝ๏พžๆŠปๅŠตๆ™~๏พž๏ฝธ?\'๏พ‘P็ฆฎ?R?65ๅๆฟ ่™ง็ฟEsๅ€ก~๏พ•EO๏พœ้ผ๏ฝฎ?๏ฝป๏พ๏พ”_(๏พ”D?๏พ’๏พ„?๏พ–9?็ซœ๏พƒ\\ๅŸ๏พๅฆŠ?D?ๅปŸ*๏ฝพUUU้ฎช๏ฝฝ๏พ”? gK\r\rไพญZdV?็†ŠP,Q๏พˆyK?mGzc๏พœ?;?.่ˆฉN\"?๏ฝช=gh๏ฝธ/jI8sw?+1?2ๆ—Y๏พ‹?]้ž?(.๏พž?๏ฝฟไฝ๏พŒ?%\\้?::FNn??\0๏ฝฐ๏พ“ๆถ›4c?,R\n๏พ™GX๏ฝฝ็ง•$๏ฝฑ๏พŒ?cTIF)๏ฝฎ{_๏พ?6๏ฝน๏พ‹#Xๆก?๏พ“๏พ•?4qCfๆ…ด?\'ๅ†ฅ๏ฝช๏พˆ๏พˆ\0๏ฝซ่ฒž่—๏ฝฒQ๏พ…@ๆฏ๏ฝก๏ฝง้‰„็”จ\"๏ฝท้‹บ?y(#nj็“ง๏ฝฐ๏พŸ๏พ‚๏ฝฉ lH;y?9๏พ‡s ๏ฝณ๏ฝฅ๏ฝซ\0?0??๏พ‰๏ฝฏ,?j*).?9K๏ฝต๏ฝง๏ฝต?๏พ˜?ๅบๆฃš้ปน๏ฝธ??<*๏พŸ.่ฒฟ]}๏พœ0ๅŒธ๏ฝฟ&W\\้‚„??ๆ‰ž)72๏ฝฝ่ฉฎ(r๏พŠ?E?)b|qC<่˜#ๅฃ•๏พž๏ฝฑ}๏ฝฎ?c!clM?4u=??L็ขฉๆœบ๏ฝต?p3?๏พˆ๏ฝฆๆ$j๏ฝง๏ฝขifG๏พŽ้Žš๏พ–๏ฝซo\r|๏ฝฒZ๏พ•๏พ“4?๏ฝฌ-๏ฝฌ็ตตY}๏พ„็ธฆ ๆฃ’*๏พ•$ไธผ๏ผง1?*๏ฝป๏พ€n?*๏ฝฏ๏ฝฉ?#S+๏ฝฎ?{o:๏ฝฌ๏พ‘ Ll็ฃ”?*๏พŠ๏พœั†Q?\0???ๆ•ฆo็ปไน˜๏ฝฝ๏ฝซW่ ่œ˜็ฃ๏พ€?่ทp?\n้ถg๏ฝทl๏พ–o๏พƒ๏พˆ5.?%m5ie๏ฝท\\O๏พž.e๏พ™??้‘ข*>้ด‡?ๆจž็ฟ”็ณŸbN็‘?๏พ‚[?;yH|b๏ฝณu}v๏พ’๏พ#๏พ’?๏ฝถ๏ฝณB๏ฝพIz๏ฝฒ _่ˆ‚๏ฝญ?{็ฅฅๆขฆ่Žซ?๏ฝฒ๏ฝฉV๏พ‹ๆ‹ณ{๏ฝง?\n๏พŽ๏พ’๏ฝฒ๏ฝงๅฃ˜}๏ฝง๏พœๆŽข่ŒธT?๏ฝฎj:๏พœ๏พ™?่˜ขch?(; ๏พ„?2FN๏พœ?\0๏ฝซ๏ฝฟ๏ฝฉ? mD๏พ†๏พ—?ๆ•ข๏พŒ่€ฝ๏พ„A๏ฝณ?้œ€๏พ†0;่ฑธ่Š๏ฝซ๏ฝถ?\r่ฆ–e๏ฝฌ$3Ow(_๏พ„x๏พŠ??a\\๏ฝณะก๏พ‘k,Z๏พ—Z?:่ญฐ๏ฝจk๏พ–๏ฝท?*Y;w๏พ–w๏ฝจ?$๏พ™๏ฝฒ?ๆˆฏ๏พ•๏ฝบ่’™?้ดƒ็ดณๅƒ–๏ฝป0?๏พ‹?่ซ‹ๆกงk6?66๏พ“j~-?P่œ†๏พ™้ ๏พ—ๆขง๏ฝข:?๏พ‚๏พ›P?-.้”*?๏พž๏พŽ๏พ€??pGzๆฟคFRvVๅขซ%eQ(Q้ˆ๏ฝณXXNn?๏ฝซK!8Q๏พ๏ฝธๆฅT๏ฝผ๏ฝท6๏พ‘x๏พ›?.pv??๏พœ้ทฝ\Z??7$?ๆœฝ??*U#๏พ…\Z๏ฝงNG๏ฝฅ้ซ“??๏พšjK๏ฝต๏ฝพY?2๏ฝฌ๏ฝก็’ƒ่ต?๏พ”VW๏พ‚๏ฝญ?C๏พ”?๏พ“:ๆจธ๏ฝญt่พญGGkg%O๏ฝฏ?__Nj๏ฝฅ,๏ฝฏu6 ๏ฝฒH๏พ€a|F๏พŽ\0?๏พ’๏ฝบ?@๏ฝจ๏พ?d?๏ฝซ๏ฝฉ๏ฝค?v๏ฝฝ็ญ‘Y๏ฝฅZiZ๏ฝฌ๏ฝถ๏พ–WF?,?1๏ฝต๏ฝฃ=็ดน?X๏ฝบ%๏พ‘๏ฝฒ๏ฝฟYK?6?๏ฝฆ๏ฝฑ๏ฝท6๏พ•@W8๏พ€่“?๏พ„??ๆ—pH?r๏พ๏ฝข๏ฝฆ๏พ‰๏พ“๏ฝตb๏พˆ?๏พŒd3(๏พ€ ?๏พƒ่ทจ -WOๅฅจ?*?k?5X๏พ™็บŽ=๏พŽ7aT๏ฝฃ??๏พ‡่–๏ฝฉ?KS๏พœ๏พž*๏ฝพ6๏พ‡\\่ฟŽ๏พ…d้ฐฒ๏ฝช4{I๏ฝปp\\? ??=;????,R่Š{T]?๏พ–7ๆฎซm๏พ“?!\"l่ทB๏ฝณn๏พ๏ฝง๏พŸ๏พŸ๏ฝฌ?้ป„๏ฝช? ็ขตJ๏พ ????๏พ†G๏พš๏ฝฅ5dๅขฎF๏ฝณ?๏ฝญ-่Šซ๏พ„B๏ฝฉ?่ŠŸ?#๏พ}้ถธ็™กๅฒกj6?Y๏ฝค๏ฝป๏ฝฐโ”ฏ8A๏พ‹๏ฝจ=๏ฝพๆฒธ,ๅฝทๆตš\\y*5??๏พ‰<&??6๏ฝป๏ฝน\"<ๅป๏พˆ๏พ‰??๏ฝฝ\'๏ฝขImm๏พ‘<8๏พ‹ P๏ฝชA?qYh๏ฝถ iๆฝบ๏ฝฉ ?pk??d๏ฝณ๏พ›๏พeL\')๏พ\0?๏ฝซ๏ฝฒy2d?)๏ฝป&๏พ”#]๏ฝฑ.???O๏พŠ๏ฝต๏ฝฏXhๅค่ผ‰๏พŠ๏พžkๅŒป9?*็‡นl{๏พ–ๆ‰ˆใ‚›ไฝœ1?1jBๆŒ‘๏ผด๏พ๏ฝจp๏ฝฒ๏พ”yP๏พ‘z็ฅ‡๏พ–.#KiE\'?๏ฝฏ\0{?=*M?*?๏พ‘kw๏ฝค๏พˆ๏ฝป?Mๅ‚ญ;q้ฏจ๏ฝต้ง‘B๏พ†่‰๏พ„3๏พŽ้‡ต๏ฝซ๏ฝทv n?!.I๏พ‡<๏พ—๏ฝฃ!๏ฝจ๏ฝค๏ฝตFkGๅ‚™๏พŽๅƒš??dhๆซ›๏ฝฐA#\'๏พ”z\n?:h้จท|7๏ฝฉj๏ฝค๏ฝถrL๏พ›๏พ‚?Lq[??(๏พœ๏พ‹$๏ฝฆ7่ชน}๏ฝงๆ’ฒz๏พ–_๏พ’ๆˆ๏ฝพPM$ga$๏พˆ+ๆป„?+xeri\"๏พ”็ซฟ็•ฆt๏พ™R?๏ฝต๏ฝต่ผฟv?\r๏ฝป?๏ฝก?9๏ฝจๆฅพ๏พ•๏ฝฉ๏ฝฉ=๏พ’D8่ผƒ๏ฝค?9_zๅณ™็ซŸw๏ฝฉ?๏ฝพ๏พ“่ƒ๏ฝฃ?4๏พš(??\0?s๏ฝก?.$ๅฃ™]๏ฝทๅ‘[๏ฝป๏ฝจm๏พ›ๅณบ8?[ไน‹๏พ›\"ๆ™ƒ?;๏ฝฌi๏ฝพLvQ๏พ??๏ฝฑ๏พ’?w-ๅผ‰๏พœ\r๏พ–b๏พ“/?)๏พ˜N?3Rp?&็ฐ’๏พš๏ฝฌ76้‘?t๏พ‹๏ฝธ\" ?8?่ฐฟ๏พ—ๆ‰“k๏ฝฆ๏พ}lDa6๏ฝป๏ฝบ๏ฝถJ(??Nk9่ ข๏พ’JEm๏ฝญ?Ql๏พ–qI\r๏ฝด๏ฝพ+๏ฝข๏พ€N๏พž???๏พ—๏ฝฌ/๏พ“P๏พ—ng?่ฃ…x๏พš>ๅผ–๏พ‡?~๏พž๏พž๏พŸP๏พ“4Xๅ‘Ž}่ฒผ\\? ่คซ๏ฝจ?2~๏พ•๏ฝจ๏ฝฎ๏พ›๏ฝถ๏พ€?\'>ๆตœk๏พ›!?8๏ฝงl\Z?o๏ฝจ๏พ|๏ฝซั‘๏พŒ็ณŠ๏ฝฌ๏ผš๏พH๏พ้ฅ\0.๏พ“ๆช ๏ฝฎ?ใƒพๆ‘บ้Š›๏พ…t?n๏พ็ฅMuใƒช?\rI {R1?\0=ๅฒก-๏พŒ??O?\0??๏ฝด?๏ฝก???๏พœj6๏พŒ_%?uๅฆจSๆ‡ด็–ฑ9่€†้‘ท?๏พ‹็†ˆU๏พ๏พ??๏ฝช.๏พ5๏ฝญ๏ฝฅ๏พ™้Œซไพต๏พˆ๏ฝฅF็ตต\0rJ๏ฝฌ้™z?g?7\"?ๆนŸ้ซช8๏พ”R็ฎฑ๏ฝฅ()JJR?๏พ•?\0๏ฝตn๏ฝซy๏ฝฃ?๏พ}]ubPK-๏ฝชY๏ฝถ??&? ?=?6๏ฝก๏พ…xW๏ฝฆ็ขฃ?๏พ˜\n?/??\0๏ฝซ๏พBt๏พN?n๏ฝต\r\\๏พ(Q่‡ง?้ด›๏พƒ?S๏พ„@?j?็…ค!N๏พ™?\0?๏ฝฏw้ ?6w๏พ’3b?๏ฝถ๏พ”$โˆต๏พ{?\0QXw?,๏พ€๏พ‰่€™d?\0๏พ’๏ฝฅ?C$๏ฝฒ?\0??;่ƒ–๏ฝจ้ž?b9๏พ๏ฝฅ{้Ÿ†\'&๏พ??ๅฎœ?\"๏ฝฌ๏พ˜??/๏ฝท;A?่†š;?๏พ•๏ฝฐ~้†คun๏ฝข?๏ฝฃ๏ฝผ\'๏พ€๏ฝณR่ชš๏พœ7ๆˆ”๏ฟฅc้บ‘??๏ฝบkG๏พ”zM4?j่ด5๏ฝฅMJO\nd๏พb๏ฝซRTg๏พ“\0ๆทค๏ฝฌ้ปY_ไบฐ่‚ฏ?้ผปW#๏พ„9?่’๏พ•๏พ?\';?hๆตœ๏ฝจu\n\\ZhP๏พ…-๏พๆ›ฆbๆฅ•๏พžT่ฟฐ๏พ‹?y>๏ฝง๏พT_L๏พ›:jq๏พ›|๏พˆYw,yB๏ฝฅdr่›†?๏พŽ}{Uๆช ?kI็ฝฎGๅฃฝ0๏พ\'ไฝ๏พ•c? ๏พˆ?j๏ฝท๏ฝข+$?๏ฝซy?q1?๏พ”q็›ดw๏พœๅพŒ?๏ฝฎๆบช๏พ??#_๏พ˜๏พ๏ฝฑ๏พžK๏ฝกg็–‹q,ๆฑบ86๏พœNx??๏พ”?้€ฎๆˆฏ๏ฝฅ็จฟ?#?@๏พœS้ณฐy?5s?๏ฝด้œ„q?-J่ด“๏ฝง๏พ›#B ๏พž=?A?๏ฝธ?Un๏พ’๏พžS,๏พ‘ๅ†ฑ92I,?? |๏พ„่‹œ๏ฝถH?3ๅ“˜?#๏พ™๏ฝณ๏ฝบnhc๏พb?xb๏ฝฉ๏พ€^1๏พŸ?<้„‚Z?6A} 7{|๏ฝช2๏พž๏ฝงo?๏ฝช?@๏พ๏ฝฅ?+q?ๆ“กๅ‘ทs๏พ€๏พ‡;N\0??๏พ๏พ’๏พž๏พ’๏พ˜๏พ„?๏พ—?}๏ฝฑ^~mZ5?<%๏พž๏ฝท T?ๅ‡บ๏ฝญt]๏พ™ ่މๅฏ‚?่ถ…~๏ฝคc๏พ„่ทๅฎฮบ๏พŽ>๏ฝต?Fๅทฝๅบ–+1???๏ฝข?๏พš๏ฝข๏พš๏ฝฅ๏ฝณ๏พŠLM$๏ฝธ๏พš๏ฝป.๏พ’Oc๏พ>ๅฃ?้ซm๏ฝฅ๏ฝป๏พ–??่ŒฃAec dTb2๏พœ่‹Ÿๆฎ•?\0๏พ’๏ฝข_R๏ฝทๆฉฆ๏พ‚๏ฝท๏พx็—’๏ฝนโ˜…?๏พŽ๏พŒp=๏ฝป\Z่ป›๏ฝถ๏ฝบๆ‚—็‚ญ๏ฝญ-?1๏ฝฅ๏ฝป#2่•๏พŽrv?๏พ›ใ€ƒK๏ฝด๏ฝฐ{eๆ—ขmV๏พ–1๏พ„j6?๏พ‡๏ฝก>๏ฝธ๏ฝฃu๏พ˜+?>่ฟซ0๏ฝด?#x๏พŸๆ”…??๏พq?3?u4๏พ? w้ ฝๆฌ„LAf?\r?<b;้€ง็šš?๏ฝฌ:DN!??U๏พ‡๏พ๏พŸz๏ฝฆ๏พk๏พ†Wโ‡”๏พ“H๏พ„S(\'๏พ“ๅธ‚?\\sVQl??๏ฝจ??-?.ๅƒๅผพo$๏ฝฏ\0๏พ›้ถ‰q๏พ‡j่ทกzๆฆด็žถrTyJD??\0๏ฝฟj๏พ—๏พšN่€€๏ฝจ๏ฝฅ๏พ๏พ•๏ฝญ็ฑ ่จถๅนค}6?~ๆšŽ๏พš๏ฝง5?3G๏ฝท๏ฝฐๅญ›็˜‹?(๏พŒ?#้ฅ๏พ†=A??J1๏ฝฑgN๏ฝฃ๏พ–\Z~้ ป?Kii#z๏ฝณใ‚?>ใ–๏ฝง๏พ‡mJ๏พ“W๏พ’ๅผพ๏พ•?็žฐ?๏พ™ๅ€ฆ๏พ‡๏ฝน๏พNk๏พšN็ ฟ๏ฝฝ๏พ๏พ…๏พ…๏ฝญ๏พƒๅขœ๏ฝด|็€ฌ๏พŽ8?๏ฝฅu}>{M,Itd๏พž.ๅƒ‰?9+็„ผ8?vx?ๆ˜ƒ๏พŒ่ฌ๏ฝบ8xๅฟ@6?#\'๏พ?๏พ†๏ฝธ๏ฝฐ?4fF? ๏ฝถ๏พ›p๏พ๏พ†็ง’?๏พ:lj:๏พŽ๏ฝน5๏ฝฟ?็ซ‹๏ฝพ๏พ›}โ—ฏwๅก‘B้ ˆ?SV 0๏ฝด็ฉŽ๏ฝฌ๏พž๏ฝฑ*๏ฝบH๏ฝธlๅฝซ}๏พ๏พ“๏ฝธ๏ฝฏ??๏พ‡๏พ‡2ๅฅ˜๏พŸ??\0๏ฝฃO ?H๏พ„?>๏พ‚\"๏ฝบ?๏ฝปeL? ๏พ???]๏พˆ๏พn๏ฝซplO? ?3๏พ†@?๏ฝตP4xd๏พ“๏ฝตc๏พ‘๏ฝฉQ\'?m็ˆl??\0ๆตœ]0๏พƒ?n\"r๏ฝค้ฏ›* ๏พ“๏พ“ๅธธ^๏พš?๏ฝฑZ\\HX๏พ•$?b๏พ…๏พ‘ฮธ็นฟ๏ฝด?\0^q๏พ‰๏ฝฉ~?k]R=J ๅ›˜๏ฝด;๏ผฎ๏พœ๏ฝฐ*๏ฝซ?s๏พ?rG๏พš๏ฝธ๏พŒ้ˆ‘~] I9?5๏พŽ?oๅฌๆˆŒ?x๏ฝฆ\\ๅง™? }k ๏ฝŽp??้ซซ๏ฝฃv?8๏ฝซ๏พ™๏พ‡๏ฝฏ็ถธ{?V??3x่‘ฆ?8=๏พ‰?๏ฝฃ๏พ™.ๅฝฑmu๏ฝช๏พšE๏พž\\.Z๏พŽ@l?5??\Z๏พ†๏ฝฐ.cๆ–ฝ๏ฝฅ้ณณcH๏พ˜\0๏พŠ๏ฝผ่•๏พ‡่†5๏ฝฒ?f๏พŠ๏พ†๏พ่‘ฑX๏พ๏ฝฐ|u๏พๆฅข@้†บ็น•m๏พ†?0๏พ„๏ฝฒ7.?.๏ฝท๏ฝจqp๏พˆ?<}1?+Fๅ”นj[๏พ5?U๏ฝฆ๏พ€๏พœๅฒธ๏ฝธ๏พœ๏ฝค r}?]ww36๏ฝฆc๏ฝฟ?+?,๏พŒ?ๅฏฉ@Fx๏พˆ=๏ฝซ?}{? ๏พšLKGๆšƒ๏พƒL} a๏พ‰98๏พ‰็ญ?Lๅฐ…%ๅกน่บ„ฮผ0?y1๏พ™08ใชr>?๏ฝฝ}๏พ-๏ฝข๏ฝผ2]ๆ•,๏พŸ?6^่ฟบX๏ฝฉ<ๅทž\rH๏ฝฅ๏ฝค[?;๏พˆ๏พŽUNTc๏ฝฝVsI้ซ„\r2Fๅ“?<๏ฝจ๏พ™๏ฝฌ i้š™s่ฃณ๏ฝฌ2๏ฝคI#|๏พๅบœ๏พ†๏ฝธ?7?S๏พ\Z๏ฝดc??x๏ฝช]ๆ•L๏ฝซMh๏ฝจ]?็ญ”?๏พƒ็ฑค๏ฝธ???๏ฝค???C?[๏พ…่ตด่ฒŒ\\?๏ฝฑ4่งœ๏ฝผU๏พž)e9\"L?J๏ฝฒ{0ๅพ‚๏พŒ๏ฝท๏พn๏ฝฌ?๏ฝพkYv)\'๏พƒ?\nๅฃ๏ฝน?N}๏ฝปW;๏ฝซๅญธไฟŸ+?๏พ˜่Œ‚y;[๏ฝผ๏ฝฃ่งฆ๏ฝตDM๏ฝจ้ฝงR๏ฝป็ชฎ?e่ชน๏พ๏พ่Œ…๏พ?-H?t๏ฝจm\Z~๏พ’D๏พŒ๏ฝฑ;? ?\0๏ฝฅY5๏พ‘?\r๏ฝฑๆœดcๅค]๏พ‹๏ฝฎ=q็Šถ?Hl?-:I๏ฝท\n9ldc8?R๏พ‰๏ฝข^%๏พ‰K6ใ‚ฑ๏พ˜๏ฝก๏พ…๏ฝฐ?้„’?=+ๅฝ\\๏พƒ๏ฝฉZ๏พ™hZ๏พ’b๏พž4๏ฝฑN\nC๏ฝดgๆซป๏พ๏พ‰๏พ๏ฝตk]ๅ…ธX๏ฝบn๏พš๏พ‹๏ฝจ4๏ฝฆ\\๏พŸ๏พZ?5&v!6ๅฏŸq??n๏พ•/๏พ“W:}ๆŸi๏ฝฐN๏ฝท๏พš๏ฝฌ๏พ‘?\"kH Ulๆ ‚๏พ‰=?8๏พ‰?H๏พŽ็ณปbใ‚€mAๅ’ค๏ฝธh#a?๏ฝพ\0่‰˜?๏พŽ*๏พ™๏พ“vM ?&๏ฝน-๏ฝถ๏ฝตv?ๅขป๏ฝฉ%q๏พ€?;G9่‡Ÿ๏ฝบ!็šท.๏พ‰n๏พ‘ivfY๏ฝฆ_(\r้šปvs?;?U?86?็พฃ๏ฝฌ8,๏ฝฆi?? ?Q?\0,{?ๆœฆk X๏พ”c??ๅซบ๏พŒ๏พ—b=?๏พ„q๏ฝง๏ฝน๏พ~}+๏ฝต:/๏พ‘๏พ๏ฝท๏พ…ๅฆฌ๏พ‰๏พ‡<๏พ—&ๅ…ฌ?>ๅ‹‰k+๏ฝค{๏ฝฆ\n๏ฝฏๆ›„๏ฝฎ&้กฐ๏พƒ+p=1VL??\0๏พŽrj๏ฝจ-?2๏พŒ่‚โˆจ?๏ฝตHM๏ฝญ๏พš๏ฝฝ?? 6๏พIๆ ž??่ญซ6ๆš‡u;A๏พ‰\r๏พ‡๏ฝทz๏พ™_d\'eWQ๏ฝผ??F?ๆ—ฌg?๏ฝต๏ฝกz๏ฝฟZ็‰๏ฝบ?-;NAh้ž0๏พ‹?$็…??๏ฝฅn๏พž๏ฝบ๏ฝบ๏ฝท~ๅคช?%๏พ‹๏ฝขๆ€งs?}x5๏ฝข4K?2r๏พšK8๏พ„\'๏พ‡\\๏ฝฎw\03๏พ‰๏พ‰?=?๏พ“d3u??๏ผช\Z้บฟm 6b)l๏ฝณ?Ny๏พ๏ฝฉ๏ฝฎ??[้นนR๏ฝด? s???็ญง?่นฒ๏พ–?w๏พ๏พ‹ ๏พ‚ๅ› ?๏ฝธ?๏ฝฏo๏พ–๏ฝฏ}S๏พ”Vv๏ฝบ8}ๆจน?F_?.๏ฝฝ๏ฝฑ??๏ฝช๏ฝฎ/O่†พS๏พu่ฟ”?s ๏พƒ๏พ‚็ฃS\"ๆ€งๆช c๏พ†k๏ฝซ? ?\'H}M?\'?a ?(f?C้ค ?~?[-\Z?i่ฌ€๏ฝดๅปš ๆฉ?8\'๏พŸN*๏ฝฅ๏ฝฉyq-๏พ??s้ดปa\Z7$?Ol}Mk[๏ฝฒ็ต„{ ่ฆง๏ฝพn\"๏ฝฐ{h๏พ™๏ฝน๏ฝฏ?\n~?g?๏ฝตR%็žปๆ›ต?๏ฝท=๏ฝผZE๏ฝญ?\ZEgๆš–๏พšrI?9#๏ฝญ๏พ“^[T้ผR็•‘ๆซจ\0๏ฝฅ)@)JP4?๏ฝผuKๆ€ฏ่Œ…/?2๏ฝง๏พ‹๏พ˜?/y๏พŒ^y?\'๏พ›??kTi@**$?๏ฝซw?๏ฝจ]้ธš๏ฝด้ตกmpT๏พ…๏ฝฆZ๏พšZ[่€ก3\n๏พŒs?\0่€„?๏พ“๏พ‘JL?่ก’?E}?๏พ’๏ฝฃXl่€„?8ๆ—w%?๏ฝจๆญ™๏พ–๏ฝข ๏พ˜s?๏พ•?e็Žณ?ๅŽ–6๏พ๏ฝคd.~?8๏ฝจ5Bn๏ฝผfBeGv??#^?5ST๏พ’?็Š€Dๆช€๏ฝข๏พ้˜œ??/\'่‡ด๏ฝช๏ฝฑ#๏พ”๏พ”gZk y3๏พ›๏พ\"๏ฝฃ;๏พ†็ผบq?5ow??๏พ‹qwng็ฅ–M? ๏ฝถ|๏ฝฟ๏พ‹โˆ?9๏พ‰๏ฝญ{pn=?<#rl๏ฝต็›†ๆ”ค6๏พ’[๏พŠQๅฝŠT๏ฝฟ$.\0\0่–ฉ{J่žข๏พžIQ)๏ฝน?)9?g*A ๏พ›?x?๏พ‰z?๏ฝขไธ‰r)A๏ฝด2ๅพ„NA?ๆ…ต๏พ›่ฉญ้ฌผqn?๏พ„? ๏ฝพ๏พ–??0๏พ™ๆ‡ฝ๏พVK{?.?ๆƒบ?!๏ฝฐ{S\r้ถ‡๏ฝข#\n?.??,qใ?8๏พ‡๏ฝฝP? ๏พ€๏พ™๏พ‚็‰พ?\"๏พ่ฟท>oA๏พ€ๆซบ๏พ˜\n๏ฝฝh่กฒMๅญฆ๏ฝน็ซฟ?4[Ufc๏ฝฎ@๏ฝน,??X#o๏พ’่‚ชq}qi\r๏ฝบK๏ฝบ\'๏ฝน $[๏ฝฐ\n๏ฝก??5๏พ๏พB๏พ“4๏ฝซ#๏ฝบR๏พ“๏ฝญใƒญ? \\D๏พ€๏ฝฉ\r๏พ‰?Ej๏พ‹#k๏พ„?w๏พ•??9?๏พ“้ฝ‹๏ฝง}๏ฝคu็งฐ๏พˆๆŽˆ๏ฝน๏พ˜๏พˆF?0\0?\0#๏พ—ๅฆพ๏ฝญ้€๏พˆgๅ€‹๏พ„o๏พ†?๏ฝข๏ฝฃ?L?๏พ˜๏พžJ]่œฟj๏ฝบ๏พˆ#8๏พœ~๏พƒ๏ฝน?HKๅนป]่จญ+|?๏พ‘๏ฝฆX?๏ฝฆF)?\n[?H๏ฝฝ๏พŽ+๏ฝช?่ด๏ฝกtๆทตPI\"๏พˆpA?s?qYs~?+๏พ’^i?+Gi๏ฝธ\\๏ฝณ๏พ„U1$?๏พ‡\'๏ฝฟoJ?๏ฝถ๏ฝถ๏พ„๏พ็‹ $?๏พ‰่ปซ9๏พƒ๏พ–๏ฝฃ.n๏ฝญ/dX๏พž??;A่–œ๏ฝฟ๏พ”zA๏พš๏ฝฅh\Z๏พŸ๏ฝฌ๏ฝฅ๏ฝพ๏ฝฐ๏ฝฑ{;?2ZM?$?8?ฮ‘๏ฝจ๏พ๏ฝญ+๏พ–j?๏พš๏พšx๏พ“๏พœ๏ฝฌc๏พŒd ?\'๏พ’๏ฝฝ๏พ–็นญ๏ฝฉไป‹\\??\0?#\r?F;VๅŸ†๏พnๅฅง?่ณป:๏ฝฒn9็˜\0}*?%๏พ™Vๅˆป?1้ฉฉ?+ไบ’H๏ฝกB?8๏พ้ชญ๏พ–N๏ฝต๏ฝก๏ฝพ่•‰Zaๅ ๏ฝคE4๏ฝง๏พ$N3๏พœ?\"๏ฝญ?]}๏ฝฅ๏ฝฝ?\0M๏พ™้บM๏พœๅŽ„ ็จฑDqm??>๏ฝต้พ ๆป}kO้‹ค[ๅฑ‘<<2๏ฝถ#?>๏พ‡?8่‚ญ^_๏พ•q<๏พ‘o๏พ™๏ฝฆ }๏ฝน/ใ‚ถk๏ฝฐ\\F๏พ–?4bi?๏ฝธE6๏พA๏พˆ8?๏ฝฎ6้‚ฆl๏ฝฐ4๏พ–้›? ?*s๏ฝด1๏พƒ0?*1๏พ–k=v;^๏ฝช๏ฝฒๆ–?RIW\nT7๏ฝก$ๆๆญƒV๏พ…\Z5?๏พๅตณy\nF?\ZC๏ฝช่ฑš?๏ฝฟๆ€–๏ฝค่‘ข?zๅ€ญๆฆ *?(YL8๏พ–๏พ่•ช๏พ„ๆ™ฎD๏พ™็‚ฎ>x\"๏ฝข๏ฝฏ๏พŽ?5๏พ’๏ฝฃ@็ฒ›S?G๏ฝบB๏พ™๏พ†็บœๅพŒ๏ฝทoZ๏ฝต?qe็จš?L๏พ‚D๏พŸ๏พ‰$w๏พ€???๏พ”1G?0๏พˆ@oM๏พ๏พ•?้ž˜๏ฝฅD]๏ฝณn่Œ‚?่Žž้ปจKO๏ฝต๏ฝทH๏พŒ๏ฝจRW |๏ฝฟ่ก›?~U9 ๏ฝด๏ฝธๆน›?\nI?0M๏ฝธfP8>๏พ˜่“™๏ฝช๏ฝฝ9๏ฝฉ๏พž๏พ›?่ฑŽ?้™ต#;๏ฝค\n$cๅŽš?V็ฃ๏ฝด๏ฝบ๏ฝป๏ฝด๏ฝผ\Z{็ตƒE๏ฝฟ*{้‡๏พ”J/ๅญ˜,็ƒ๏ฝฅ?ๆคจ้ฝMB+msM?(?4j๏ฝฃ!I?๏ฝฅEX?M^?๏พžz็Ÿญ๏พ‡5๏ฝน็ณงa๏พ„e@*๏ฝก@่กพ0{๏พ•๏ฝท๏ฝง?่ถ?\0?๏พ–D๏ฝทE%2๏ฝปๆ—ฑ>e^?๏พš๏ฝฃ?I?๏ฝถ[?\"๏ฝด้ ด&N๏พ–๏พ˜่ˆ๏พ€๏พ€๏พŸ๏ฝญk\rjGๆฒ’\Z่ฌŽ้€ธ>?.ๅญฐ๏พ’๏พ‰?๏ฝบ๏ฝบi77hP?\0?\"==2s?ๆˆš๏พŠ\\้ฃŸc๏พnOo๏ฝฝci?$V?๏ฝกh๏ฝญ3*8\\?\0่คŠๆจ‚?Jไพฟ๏ฝก??9๏พœJh็ƒ‹}๏ฝชr?๏ฝจ๏ฝด๏ฝฌไธ‹๏ฝท๏ฝธ๏ฝนๅƒ\n๏พ›F@็ž๏ฝบe?<๏พŽ+%bH?v็€พs๏พœWSD๏พŒ๏พ‡s่ฟฉ&๏ฝน๏พ›๏พ‘\rH\r๏ฝป@่ปŸk\'๏ฝฅt็–ซ็ฌˆ?g??๏ฝช?\0=Mc๏พŸF๏พ†๏พ?๏พŠF03้œœ๏พ™๏พŸ\n๏ฝฌ็ธท่€—?๏พ…๏พ๏พŸurๅฑค?!๏พŠg ๆˆ”๏พ–?!๏พ‰?/h๏พ–?:|R๏พŸ4๏พ—v??D๏พ™๏พœ??๏พž๏ฝป:]m#๏พ—-m>V\"๏พ‡?๏พ‹ๅขพ๏พ๏ฝฑ๏พŽs๏พ่บฑ็—›hmะฆ ๏พ› ๏ฝค๏ฝป??# ???Zๅ ~ๅญบvU๏ฝนk=Elๅ๏พ™b๏ฝถ 7๏พ‚?๏พ€๏พml๏พ‡๏พ™}๏พ’:mๅฒ‘u๏ฝต๏ฝพh๏พ?Z๏ฝฑ๏พš๏ฝฐ?\r?๏ฝท๏ฝญe๏พ›้‘ฟB๏พ–็ช•๏พ–๏พ•็ทค ๏ฝฐ๏ฝน?<)?\0๏พ”๏พŒA๏พœ๏ฝคqฮณ?h๏พ?๏ฝฃ้ฌฅ๏พ๏พ๏พ„??9YH้…”?ๆŸ”๏ฝฟo๏ฝฅK??[ 5๏พ’๏ฝฎ๏พ‹๏พ†6?@sๆ“=๏ฝณ?+๏ฝถ1]๏ฝข\"๏พ›๏ฝฃ๏ฝฑ๏ฝฃ๏พš๏พŸ?7็Ÿญ๏พ‰&๏พ–๏พ‚?_??๏พ•๏พ‡๏ฝฅๅจŸy!? ่ฒฉ๏พ๏ฝถo9? ๏พaๅฏพ๏ฝฝkZ๏พ–ๆคฐEim๏ฝฌ1๏พ›Xๅฆป\n๏พˆG8?้€Ÿ[๏พŽ๏ฝฃ??}7L็€•?9?!(๏พžlN{O#๏ฝถ5๏ฝฌx๏พ…้‘ผ^u๏พ›?n๏พn?=?!?Rssr๏ฝพ,?F@๏พ›้ฃฎ๏พ—๏ฝฝ_๏พ—๏พš๏พ–่ˆ‰L๏พ‰๏ฝซ๏ฝซ[ใ‚ƒ#[u%0J๏ฝซ@x๏พ<๏พ•5?็ฉƒNmb?b?|ฮฝ็จ๏พŠq๏พ˜ๆ ๅ‹ฆ่ฌ€7N๏ฝตzๅƒ•?&@๏พ›w่ฒง?ๆถ•j๏ฝฑ๏พ”ๆŠ”c๏ฝฅi^๏พœ๏พx nU๏ฝฐX??๏ฝญR๏พg๏ฝจ้ทธๆƒถ\\๏พ†??\'ๅ‰q๏ฝฑO??ๅฃ…?๏ฝบ?๏พ•?ๅฅไบŠ๏ฝฅๅœญ๏พ™๏พ?(X?,=[??c๏พ‘็ฏฅ?๏ฝต๏พ’(่ˆ‚Iz๏ฝด?Mๅนผi3-?ๅ–˜+๏พ€W#8?๏พ๏ฝปๆ˜ฟbj]Mw๏พ’?๏พš ๆ˜ผ?<)v็ชฎ? q?;?9๏ฝญY๏พ‘\Z๏ฝซ้ฎจO๏ฝฅup๏ฝค๏ฝฉ$็ขผg?#?f๏ฝง๏พ’+}WR&๏พš้ตบๅซป็นŠY๏พ“ |๏พ?;?๏พž๏ฝพ๏พž๏พ•???k๏พ“?๏พ?๏ฝบ๏พ‚[?V?ๅœ๏ฝฝ๏พ“็‹†?#??W๏ฝด?๏พŠ๏ฝชl๏พ•t)JVdๅด–?ๆซจ\0๏ฝฅ)@~v|d๏พ•ๆญ™??\0๏พ–๏ฝบั$F-M?๏ฝฉ$l๏ฝธ a๏ฝธ?3๏พ˜็ธt่†œ๏พ‘=}\"hk{mkx?๏ฝดb@|๏พ’?ๆทณ{๏ฝธ๏ฝช๏พ…๏พ„2%็ซ•่ˆž? ๏พ?\rc๏พœ\\Kss-๏พŒ๏พŒ๏พ#๏ฝถ?\\?๏ฝฃ4W n๏พ‰03\\?;?i?ๆฑจ๏ฝชW๏พไพr๏ฝฑ๏พŸ4?\'ใ‚ŽOๅ„ป<ๅฅจn?7๏ฝคj--?่ผ”#\'๏พŠ@๏พ†9$?v#๏พ๏พ”u??)$Vๅธญ\'็ซช?+2๏ฝฑc?\rXy???้ ป้‘„่ฑธ้บ‘๏พ†?_?\'? ?๏ฝน?9็ˆฒ๏พ‘2?t๏พš?๏พœ,Mๆ“บm่ณผ{ vA๏พˆๆท’ๅฝญUk่‰คN@cๆธฏpX* ?-?x#๏ฝพ9?1ใƒผTๅ””?sgt๏ฝช? ๏ฝช๏ฝธH๏พ˜>WUzๆ>๏ฝธ?๏พ•๏ฝค๏พ้ดพ?6๏พ—.๏พ(O:๏พ˜R?๏พˆ ?c\\*m-ๅ•ฃ๏ฝขj\n?6g๏พŠ๏ฝปZ7???c๏พ›?\0sๅ‹น\\๏ฝฃ๏พ‡็ชฉ่ˆธ?? ้ณณ๏ฝช?ๆ‰˜๏พŽA๏พ#๏พŸโ†‘๏พ˜๏พ›้ฌฏQ?ไนž8๏พp3?๏พ™๏ฝจ{[่•šdๆจขVh?&U??(F2๏ฝถ3้ŒซqQI?T?๏ฝฅo&๏พ“\'?4๏ฝธ๏พŸPW?;@#q\\็‰พH\0ๆดซ=๏ฝก:#๏ฝฉ5ๆคข๏พ”๏พ–๏พš?ๆฉ˜fm๏ฝญ?๏พ??9๏ฝซ?SOuwyor?๏พlIๆ‘บ\' ?็ท•a๏พž[้บ๏พ‹๏ฝน๏ฝนeๆ–งl4\"3๏พgc>?่ฑธRuRDJ๏พ”zkY?/#๏พ•็ขต\nไฟ.็’ขๆšธ้†บๅš ?9 K?๏พ๏พ†-#?@}ใ€œ<๏พ‡๏ฝน๏ฝฉ๏ฝช๏ฝฆๅด๏ฝฎ?4๏ฝฐx๏ฝฆ? ๏ฝซL๏พ€?9#!?๏พz?.\n๏พœ?4็ฟ Oeๆทกlg๏ฝพ\0G๏พ‰่ฑŒ??๏ฝฒt๏พ…?cๅทŒx็ฎvๆต่ฝคH<??็ฎ‹็ซ’๏พ—J๏ฝทๅฑž่ฃ…T??E^๏พŸ๏พ‹๏พ‰่‚“?}T๏ฝณ6p๏พ‹%?\rEๆขฐ็œผใƒ”?=@?๏พ–๏ฝฌโˆ’]?่ฉฌM?&H?2g๏พ”ๅ–๏ฝฉ\'L๏ฝฑK๏พ”:๏ฝปC?-๏ฝผW?[๏พ„6/๏พ‘๏ฝฝG่บกa?Z๏พo๏ฝฅ?8ๅƒปB๏พŠ๏พI?๏พ›5๏พ‡]้ญƒ??๏ฝฏ๏ฝญe~๏พ’?8???๏ฝฏ๏พœ๏พˆR[{p?0\Z-๏พ™q??m็พ๏พ’่ผ้ˆท๏พƒ\Z๏ฝจ??*?\Z๏พ‹b็—ฉ-?3?V๏ฝง???QF??%๏พ’๏ฝถ| c?!?๏พ?\\?OE้€Ÿ?5h๏ฝท7WV๏พšๅ…‹?๏พ?+๏พ…#dๆบ๏พˆ@๏ฝฝ?\n=๏พ†x?e??z่Žž็ตจ๏ฝฑ\r~?TFDS?r๏พœๆŸด?๏พš๏ฝน2๏ฝธi๏ฝฆuc็ข๏ฝฆๆ ข๏พ๏ฝฝ๏ฝฐ?6๏ฝถ็žฟr9?kๅซ‹๏พ’^=;?[-=็พ6Wm๏ฝนUW~?N}y?้ณซ๏พ–)C๏พŠๆƒน{๏พ–\\?/?%d2๏พ˜fEๆฑ T)\0??*]??๏พ้ฏต|61?8?+ๆœƒ๏ฝฃ๏พžYๅธ™a๏พˆ8Rx๏พf[๏พ๏พ&๏พ•่Šณ9๏พœ%ๆœ–ๆง๏พŸๆˆ€๏ฝซRh๏พ†qๆฝธ๏ฝถ?๏พ“[?8๏ฝญ๏ฝณkyop๏ฝฌ^Mๆฃ„G๏ฝถA?๏ฝท๏ฝญk๏ฝปm:T๏พ”--&๏ฝท๏ฝนๅ–ฎ้‹ญC<\'*Ow8?๏พ…๏ฝฟ้ผˆ็‹Ž[9๏ฝต;{Whๅ…œๅฎ‡๏พA๏พQๅฎŸc??]p|V๏พ‰Z;~\'?ๅซz4?9R?\n?่ฐท7!In๏พŠ?ๆก€็•œv๏ฝช#]?7??jๆ‰“๏พ‡wxN๏พˆ?7(๏พๅŽฎ>ๆšzf๏ฝป๏ฝฟx้ฆ—U๏ฝฝ?๏ฝธ้ฌผๆ‡‡UH|\r๏พ๏ฝณpn1? ็‚ณ่ปข]m๏ฝญ\r]!้ฏฑ/M[ ys?\0?ๆฆฎn?๏พŠ๏ฝพ9๏พ๏พ™?๏ฝช๏พ็ฟฉ๏ฝฃ?่ฆฒ๏พ•๏ฝณ๏พ•W???ๆจขXB๏ฝฃ๏พƒ๏พ›?๏ฝค?_๏ฝน๏ฝฌ้œ„O๏ฝฅlV??X็“ฒ7s๏ฝก๏พ†X?ๆณ›๏พŽ}๏ฝฟ:????่“]CQๅฑžZ6h๏ฝขF๏พ‚F๏พ›vU?0้ถค|๏ฝด?๏ฝป๏ฝญdGs๏ฝจ5๏ฝพ็„ก???g9๏พ‰c้ถฉO๏ฝช๏ฝฟk\'๏ฝถ^๏พD^A๏พ“๏พš^??0๏พ…o็ฅ€?3u+0๏พC๏ฝถ??y๏พ›?<2~?่ฒซั‘F}้šฒ๏พŒj@๏พ9?๏พ–P??๏ฝง~๏พ๏พ’Eo+3๏พˆ๏ฝชyu๏พๅบ„๏ฝง๏ฝฉ]๏พ_j}๏พ„;T?๏พ˜?็ฟ”็พ๏พƒe๏ฝทM๏ฝฝ:ๅฒธ๏ฝฎy/\"V?*๏พ‘๏ผฑI๏พŸnGqU?๏ฝจ๏พ”็–‰n๏ฝญ๏ฝก?9๏ฝฆ$ ?y8?]\Z๏พ–๏ฝก0๏ฝป่ž ๆ˜ฟH่‘ฉ๏พŽ6๏ฝจ็†”Ojใš?้ธ,๏ฝปๅนข้ฅ‚๏พ†๏พŠ๏ฝณ๏ฝญๆ„•9&?๏พœ๏พ—๏พ๏ฝฝ???๏พž๏ฝพ๏ฝจ๏พ€??X๏พ€๏พˆ๏ฝฎ๏ฝฌๆŸ“๏พ‰ (I\"๏ฝพm%๏พ‚ๅ–?U?๏ฝฒI๏ฝตs๏พ‹ๅฃป๏พˆๅ›˜V๏พœC1ๆ‰˜_d่ชš(B?r่€ก๏ฝน๏ฝช?๏ฝด?q??๏พšVN\Z๏พ‰๏พ“ๆพ—?4??9?๏ฝฉ$๏พ?<๏ฝฐ๏ฝซmr๏พ„?A๏พ๏พ๏พ๏ฝทa่ฝ„r๏พ—#๏ฝฉ๏พ‰\' ็ถœI?\0๏ฝญf?ๅท๏พy$?aN*=?๏พ๏ฝฐ[๏ฝช่„›?>๏พ€Vใ•eๅ€ŸC@\09๏พŽ๏ฝฎb6]๏ฝฃ9็ฏ‹0+o่‡ˆ:?$๏พ‹ฮฒ๏พ‚็นฉ๏ฝช ๏พž๏ฝฟ๏ฝฐ~๏ฝข๏ฝถ?Z๏พ˜๏พ„\\?\Z=๏พ…๏ฝฐ๏พ˜๏พ˜CG.~๏ฝฟ??๏พŸU???Ktๆนถ??\0้ฐ•_๏ฝฃU้‰—_ๅ‹z๏ฝฅ+๏พ‚ๆซจ\0๏ฝฅ)@)JPๆ–™่‡บ.!ๆ”ธ๏พ‹๏ฝธ?Nj็ธ‰?Q?ๅЇๆถœ๏พ?๏พ‰?ๅงซ้Ÿœ...dๅ™ๅœL๏พ#ๆนฏ๏พŒrI?mO?๏พ‡}๏ฝฌ้ด•๏ฝฆc ๏พ‰:๏ฝด??\0???a?>8? ?QY]็• ๏พˆ>o๏ฝฅv๏พ่‘ฏ๏พžX๏ฝฆb๏ฝฉ๏พƒ๏พŠ_~ๅฎw?A??2\r2?m?๏ฝคS๏ฝตDK\"7รท>๏ฝฃ๏พœ}j๏ฝฎ้ ?\'๏ฝฌ้ฐ›๏ฝฎๆฃŠ@?๏ฝผ๏พŽ?>?2u;v%!่‹’v}?๏ฝต๏ฝฏ?t๏พœ[J?5?Y2 ]๏ฝณ?3?+Z?=e๏พ“๏ฝท๏พ—:|W๏พ’๏ฝช$?่”•#ๅˆŠ๏พ›Rze๏ฝฌ?๏พ—\"%+๏ฝฎq็šฟgi๏พ›๏พ่ฆˆ๏พ„2\"ๆ•ทFr๏พƒ??X่žฏ??๏ฝจๅ†™๏พ?(็นฟ๏พŒ;?dq๏พ˜?้ ˆ?ๅฅ๏พ‚๏พP]๏ฝค6?3๏พ‰?;I30่‹”๏พ˜?=0{q๏พ…e?? ??4?๏พŽJ๏ฝข่ฃ๏พ†9๏พW?๏ฝฌtm^k๏พ‹}:d๏ฝน62,2๏ฝผg>b3โ€ฒ่š๏ฝฑ>#kS๏ฝฎ?m๏ฝฅK๏ฝป?๏ฝผ?WO?\"๏พ†&#0?9cๆฌ–?>?้ฐก(j๏พ’F๏พ‹l๏ฝฐ๏พ…ndf9\0?๏พ”F?#็ถป{K?๏พ€??ๆฅ ่ปŸG5๏ฝฑ?6z๏พŠ๏พ•N้€ ๏ฝป+:,๏ฝบๅ‚ๅฅ—?ๆฅญ๏พ…๏พ† =๏ฝปVo๏พt๏ฝฟFjPO%๏ฝตๅณฐ๏ฝณ๏พ‡๏ฝนg่ก›?๏ฝด\r?)<้œ€=๏พ#๏พ›5?_่„‰?๏พ–?-๏ฝญ1j๏พ“[?-U?}P่ ๏พŸZ?6H?9e?ud๏พ‡S^kw]=q็’ฝ๏ฝจ๏ฝฅๅผƒ๏พ??๏ฝท3g๏พ?08้‰ˆT๏พ’๏ฝกK=\"dใท>a๏พ™๏พŽ8๏พˆd1ๆ–ƒ๏พ—?\Zt๏พŒ%[z๏ฝบ๏พ‡ใ€†?4?๏ฝป๏พŒ2s?1]3๏พƒ4nf๏ฝฒrH??\0x5??,I?\0๏พˆ ?\rzm๏พ“้›‰\\?66๏พ–v๏พ–๏ฝฒ Z}๏พ…็œ‹?A?2}๏ฝช๏ฝฟw|๏ฝญ)?969\'*{??๏ฝซ๏พ‹$2๏พŽ?m๏ฝกs๏พŸ๏ฝฆ๏ฝบ็ซญF๏ฝฟ่‡ง๏ฝข๏พ‹๏ฝคๅฑŽ??๏ฝพs๏พš๏ฝธJK9๏พ๏พ‰w๏ฝฎx๏พšyvzcๆ…ต\0๏ฝฌ\\๏ฝถ่•€G๏พ’๏ฝญD\0๏พ๏ฝฐ/้ฅ‘_ ๅ›ณs_๏พˆe๏พŠV??๏พC๏ฝพS?*/>๏ฝธ?B:๏พ‡่†๏ฝฝ}๏พŽs_$*๏พ’๏ฝซ?O๏พ˜W0p๏พ˜S๏พ˜? ;QW ๏พ‰??๏พ˜๏พŠ๏ฝฏ8$ๆญƒ๏พ—๏พW9๏พ‡\'5๏พG#ๆญ›TeLๅญฅ็ˆถCOๅฅ(K}+๏ฝชH๏พž๏พž?rใƒ“???๏พ›่ˆฌ\Z5๏พ‹/9\0?็ซฐ๏พ%๏ฝค๏ฝก๏พ™rsๅค‰9?l๏ฝฐ๏ฝผ๏ฝถ?v๏พŠw๏ฝก๏ฝธ?P?#?๏พ๏ฝน}?;H1๏ฝธ่‰จX2้‡กvqTh้“?=ๅฃŸ+๏พ—@๏พ€๏พ‡>ใ @w๏ฝกB@?๏พ—๏พŠ?X?\"Y๏ฝถc๏พ?\09^??[๏พ?\0SๆฅžF๏ฝซ??>?\0?้ค”๏ฝฝ??\0๏ฝฉ๏พ_๏ฝฃ5๏พƒ่‰ค๏ฝณH?)JV?)JJR?R็ฎฑ?/>ๆšˆD๏พ€?&Z๏พš}/m&ๆธซ๏ฝบX?๏ฝด]๏พ‡๏ฝธ?ๆปฏ่ƒ„๏ฝชE๏พ?โ€ฐ7๏ฝจ?๏พ‹g๏ฝฆ?V๏พ–?$G??X่ฒ้‡ฃ็ฟ”<{iโ”ณ๏ฝถNH\rๆ”ธ๏ฝฎ\r}??I|~MH๏ฝด~๏พ?๏พ“๏ฝญ๏ฝผ*cx๏พ„๏ฝฃๆ??Qๆนฎ๏ฝตโ”ฟ๏ฝป๏ฝฑ๏ฝญ๏ฝต??\0ๆ„ฌ??41\n?๏ฝฉ????1?5๏ฝฉg?๏ฝก#๏ฝฆ๏พš๏พŠiI)GU?#๏ฝธ?WrZ0๏พŠ2H9?๏ฝท??5๏พ’?+??)๏ฝฌ๏พ˜้‹บ?๏ฝซ[?ๅช๏ฝง-?:\r๏ฝญ?้Žญy็บŽ?ๅ‚ญ.ZT???๏พt๏พ‡ ๏พ?๏ฝง??~ๅ“ญ0@๏พ—๏ฝณ^cd?3?O?*r\\๏ฝบ&็ •๏ฝฉZ๏พ๏ฝฉ๏พ‰\n[๏พ€๏ฝฑๅฆƒZywๅฎธ๏ฝฃ?y?\r?่ท‚M้ปฝ่€…s๏พ‹๏พ†V?๏พ˜*?๏พๆฟบw๏ฝฉ??>๏ฝฟ\r็ญต๏พ?ๆฃ‰๏พ‹\'ๆšๆ‰˜ๆ‡Š?ๆจ™๏ฝพ ๏ฝต}M5ๅซ้…Œ?h๏ฝฒN\\็„ฆๆฉก๏พj็บŒ๏ฝฅ๏ผฌ#V๏ฝบe๏ฝช3N๏ฝพ๏พ‘๏พ’๏ฝบ๏ฝขN๏ฝข้ณง?๏ฝฅKKๅซ–a9 ;M?;]s๏พ˜??A๏พ–Z๏พ…๏พ?$ๅ›Ž๏พ?$lQ๏พ˜ๆฅa๏พˆ๏พ•j๏พ’ไผ92๏ฝฆ่ฅท*BL๏ฝฅๆŒๆฌ–๏พ?C๏พe๏ฝฟoๆ „?๏พ„๏พœ3๏พ€;\\R?๏พœ๏พ†๏ฝฟ9่ ข๏พ†]?\0๏ฝฟ?H๏ฝฎ้™›๏พ›<๏พ‘๏พŽ่•่ช‘$ๅง™*?๏พ„(?็ฒง๏ฝซv?๏พ„่‚ฑ๏ฝช?O1?qๅ€ฃ่’ผ๏พ๏ฝฏ๏ฝญjๅญณ๏พoa?ๅงซ่กlg๏ฝน>๏พ•x๏พ’่ ๏ฝต ๆกy๏ฝฏ\ZLQ?*๏ฝฏ๏ฝก๏พœ=???5๏ฝฆ\\?)?่œ˜T;JG๏พŒ?๏พ‹?lWm๏พ–ๆฎณ๏ฝฐ??.1๏ฝธv๏พ๏พ†pq\\4??๏พ๏ฝด้šปๅง“ๅฎนR6?<๏พ€z๏ฝถ๏พn๏ฝถ๏ฝฒๆ ‚๏ฝฌ๏พ—N1$[T?้ž˜่ƒ„\')O๏พ‘๏พ?&๏ฝค๏ฝข?+๏พ•]Ku}\'๏พN|I#?e\0๏ฝฌy?่ผœ่‹ด็น๏ฝฆ๏พt็คซโ€œ!๏พ‡๏พ€๏พ?่‚ฌYbx??,?.?{?5๏พŒ๏ฝถ๏พ† ๏พ†Zg9y[๏พ“??๏พ—๏พ”RJ่—ปb๏ฝข๏ฝฉpๆ›นx?p๏พ‹c$d?ใ Z@๏พ—>H ๏พ‹๏ฝฉ๏พœ๏พ๏ฝผ) ?H่ฒ… sๅฆƒ๏ฝนV๏พ†A๏พˆ๏พˆ๏ฝซ๏พŽ?๏พƒ& B?\03g?๏พ“๏พW\\_?๏พ–P๏ฝถ? ๅ €็ฌ†Pr๏พžP?ๆขผ๏พ๏ฝปV4ๅฏ‚๏ฝฃ๏ฝฐ๏พ‰?๏ฝฑHF+ๅ’ฏ๏พ‹??p๏พ›?c๏พŠcU.๏พTO?๏ฝจ๏ฝข\Z๏ฝณg้œIw๏ฝฅ๏ฝต๏พŸ้œž?Gm๏ฝป๏ฝผ#?\0j้ฎญไฝต%๏พ‘n\Z(?๏ฝดh^Uiv8๏พš๏พ‡?\0}๏ฝฑP๏พ#v๏ฝถ? \'ๅด?๏ฝค?้ƒจๆŠA๏พ๏พ”}k๏ฝท?๏ฝณ๏ฝญ{V๏พ…vhc@?>ๅฉ?y๏ฝธ| ?๏ฝฑ???ๆฝๅ‹ณๅทต?๏ฝฝ๏ฝต๏ฝน5้˜ฒ Afโˆฝ?\0@๏ฝช๏ฝผ่‚‰?T,? {๏พ—TI#๏พ›้‘š๏พ›๏ฝทq[๏ฝฆ?N๏ฝฅ้จซ-๏ฝฎ๏ฝฏ้ถธ๏ฝข4Eๆ’ญ?\'8c??ๅœF?#๏ฝงDโ€•i\Z?IS๏พ??Oๆ…จq๏ฝฏ?/:็Ÿฅ$๏ฝฉ๏พ“?๏ฝจ้ด›๏ฝป+0 ?\n??๏ฝบ5$v๏พ}๏ฝบ็ฅญ?bx่†š๏พ•c$pq๏พ‡l๏พ—\n@]๏ฝถ?.1?c๏พN๏พŒ? ็™ฝ%๏พš?๏พŒ๏พ˜๏พ‰?,0ๅ…ขc\'g๏พ•๏พ›ko$๏พeUB๏ฝป๏ผ„=@?)ๅƒ‘?๏ฝช[??7??8๏พ™Q๏ฝจ๏พ›ๆ†ซ???ๆปž๏พ‡jD?7H}?~??t?]<๏พ’1d?๏พ??)๏ฝนๅ’‹mg?*๏ฝฏl q?@a๏พˆ0๏พ˜๏พ๏ฝต}ๅฉ๏พˆ๏ฝฎ?้ปถ๏พ˜๏พŽ๏พ–๏ฝค-?๏ฝฆ๏ฝต๏พŸ๏ฝฌ???๏ฝฃ ๏พ…?3D?f+?\'๏ฝฐ?\0๏ฝฑ]k๏ฝต[๏ฝจ?้ดˆ๏พ‹่˜๏พ‚๏ฝช9%๏ฝณX?4aQ๏พ™T{3r>็ญง(๏พ‹๏ฝณ๏ฝนKm>E@่‚ก่šถๆœถ?้š†๏พ/?+?่‰Ÿ๏ฝณ??:?/?? ??\0Z?2JT#? ๅˆ‡?Z๏ฝฃD?;U่จฑ~?;((๏พ?\0?๏ฝพe_๏ฝถๆ’ž?FJ๏ฝฒ?.j๏ฝฌ็›ƒ๏พƒ็ทš\0q?+๏ฝบ2J๏พžN8???p๏พ้คžBb๏ฝทi|๏พ?้ด‰X7D๏ฝข?#๏พ›๏พƒ??\'๏พ’QOuY.??๏ฝฅ๏ฝดๅ‰ฉ?D?็ซŸ~s~๏พ‰6ไป‡??๏ฝดn?็ฅ6๏พ’F๏พ๏ฝถ๏พ’?$่ˆŸ๏พ›~???๏ฝฎ#?G๏ฝกJR๏ฝฐ,)JP\nR?ๆซจ?๏พ—?Y??\']๏ฝบใ‚P??๏พŒ??T๏ฝฎ๏ฝงk$๏ฝณMp _\r๏ฝฃ๏พŸ? ๏ฝฃๆนถ?ๆบCmsi??็ฏคR;๏พˆm\'?้Š–?๏ฝถ?2?๏ฝธ?็Ÿง๏พ—๏ฝฐ???p่˜‹?,??%่น‰ZY๏พƒ+ๆ„ผ๏พ—๏ฝถ0๏ฝฟi\"๏พžD?=๏พ˜๏ฝป??๏ฝฏๆฟบv๏พ€๏พˆ้ฎ๏ฝณ๏ฝบ?๏พše?m?\"๏พš[๏ฝซZ็ฅ๏ฝจๅ”๏ฝฃ?U=๏ฝฎ๏ฝฃ0?(?4ๆ—ฉ?)๏พ†่ ฑ?+๏ฝทi_๏ฝฆf?*๏ฝฅn$Uq็ตƒ? ๏พ€??,๏พ”ๅ…i?\0๏พŠ.?>f8R ๏ฝบD]้ฑˆ?่ƒ™?\r๏พˆ่€จ5๏ฝฒ๏ฝบ~๏พŸL๏ฝด?๏ฝป๏ฝจBF๏พ„o้›ฒp๏พ† ๏พŸ๏พ€?๏ฝจ?E\r\0 *๏ฝปgo๏ฝฏ#๏ฝฟ๏ฝฟaW??่ž‚้˜?\\๏พ‰๏ฝฉ๏พšD? 7)๏พˆ๏พš่“ฟx๏พ‡๏ฝพ๏พ•!๏ฝช๏พk๏ฝณ?>]?ๆ‹ณ๏ฝค็†จ๏พŸๆนŸ๏ฝบ๏ฝฌl๏ฝฅ}\"?6ๅ–‡๏พˆ1*่ฎ)f;๏พ“๏พz๏พˆ้ซŸ๏พ•t?๏พŽ?-a๏ฝน?๏พ›[๏พŒO?8TrI๏พ?๏ฝฑ๏ฝช๏พˆๅฟ?๏ฝฒ?1?\n?0๏ฝก??ๆช ?d้™๏ฝคWz\"้ง˜ๅซ‚๏พ‰?)่”—=๏ฝณๆกŽ๏ฝต็‰ฉh?E๏พ•w6VWvๆ—…AZoๆพ๏พ ๏พˆ๏พ€!ใƒ‘G๏ฝฝV?่ปŠ่žๅค–่ƒ™่‘ฏs๏ฝฑ??๏ฝซJJ?\'t๏ฝฟ?๏ฝฒ้ขy\\ๆ…ถ?W๏พ†}๏พŒ?.๏พƒ??~\r๏พ๏พœj? HB๏ฝบ?๏ฝฃ?\\?70่กก้ซป๏พˆB๏ฝฑ??z๏ฝฃ,r๏พ๏ฝฅ?\0๏พ„?ๆฃฎ? (9>?Z๏พ›=1๏พ‘็ถ“็ณ X่œฅ7Lx? ๏พƒ๏พš1ๆ€ฉ[๏พ‘ๅฏƒๆขขj๏พŽๆŸง่‹ฅn?-??ๆ„›๏พ„๏ฝฃ?\0d s๏พ†v๏พ—๏ฝง?i???Aw๏ฝฎO? b?่ชฒ{๏พ„d(๏พˆ๏พ๏พˆ่‹”่จŸฮผๅฎธ๏พ‘๏ฝค?? zr?๏พ’๏พš;๏พ›ๆ›ณ๏พŸ,?! ๏พ‡๏ฝธ=?&๏ฝญ๏พ…่ธชeๅ›BG?bO}๏ฝฟn๏พƒ?a๏ฝบ๏พž+{๏พ•?=:็ˆป#๏พƒๆŸ๏พ‘+๏ฝณ1๏ฝด?1๏พ‰?๏พ•W๏พ•๏ฝบ๏ฝฒ๏พ“M๏ฝน7๏พšๅ…ฌs๏พŒ?P๏พ,P[๏ฝฆ7aG-!๏พŠ? ๆฅ8๏ฝฏ9๏พ‚sv๏พ4Ju]๏พ…?๏ฝฅๆชชๅกl0\n๏ฝชV๏พŸ?##๏ฝฟ๏ฝฎj๏ฝฟ๏ฝช๏พ๏ฝฉ๏พ…๏พ“r?-๏ฝข๏ฝคL๏พ–?@8f๏พp=๏ฝง่บก็ซนP๏พ‘๏ฝต?%๏ฝญ?๏ฝญ|๏ฝจh๏พ”\\๏ฝฌA๏พ—๏พ‘๏ฝ“ๆ”ถ๏พž๏ฝฟJ๏ฝฃ|d้ปœ$๏ฝณๆ„๏พ๏ฝฏ.๏ฝฎ??๏พ€Le?!๏พr๏ฝฅi r๏ฝด?\r๏ฝข?3่ช˜๏พ‘๏ฝฎ?5ๅฝ?]ๅ‘ถ๏พ˜.?๏พœ?\"๏ฝง๏ฝพ\Z?\n๏พ‰๏ฝพ[h??!S.?, ?;?๏ฝง๏พž๏ฝตf๏ฝคDๆ†ฉIv@@y๏พ‹๏ฝง\r็ณŸ?sX?๏ฝฅ~o-๏ฝก๏ฝด๏ฝบKyc>UY<๏พœ?8?๏ฝฟ๏พ“่€€๏ฝง๏พŸMey ๅฒฉ1๏พˆ??wD??ไฝ†b๏พ‘@NๆˆŸ๏ฝทc๏ฝน๏พ†8A?lu9o$้ต๏พšC#?\'็ฆ\rๆ“พ๏ฝญi v!?y N?}ๅ˜ฑ?Jๅ„ฒ \\๏ฝธ๏ฝฝ?+ๆฌ ub;??๏ฝฝWnLL๏พ†K}๏พ‚3๏พ›\'ๅผ–8๏พ—<c/?zdf๏พ†๏ฝฒ~P๏ฝบ?tQ๏ฝบ๏ฝณH้ฉ๏ฝปH? ?๏พ‚้‡‰๏ฝฃ๏ฝด9?5%ๅปฟ๏พ”.\0?+n^๏พš้™œC๏พ“๏พ‰Nๆ„ˆ๏ฝฒ๏ฝฅe~\'\0q?{U\n]๏พ„๏พœ a่ƒž?71N? <๏พ‡xQ๏พŽ\0\'๏ฝฐ>๏ฝต่‚„?่ฟ??๏พ‘?ๅนต๏ฝฆ๏ฝฉ??\0๏พ‡?zoT๏ฝพ๏พ“d?/3xๆ†ŽJ๏ฝฒ่œƒ| ?/N๏ฝบ๏พ’uK9$๏ฝพ้˜ช่›‹ๆœฑ๏พ€H?1ๅจฉ๏พžS?=9่ฑฌOC๏พm4๏พ‹hๆ…ฎ๏พŽ๏พ‘๏พŒ\"I? ๏พšI<~็ญ\r๏ฝฌ3๏พ›๏ฝซ๏ฝฌ๏พ’D๏ฝถ๏ฝซ้‹ฒ? ๏พ„c*@??X้ถฏ๏ฝฃ๏พ–ๆบF็ชn?+?O๏ฝผ๏พˆ๏ฝค๏พ… W@๏ฝฆ๏พŽN{?b๏ฝต๏พžๅ‡ m๏ฝฑ(?)?๏ฝก$Ma๏ฝต??๏ฝฅmD?;๏ฝต็–่งฆ p_๏พŠ6????\0b๏ฝต๏ฝฏ๏พ…G่จ˜๏พ–?.ๆฒ™@IๅฒฉDr๏ฝพ๏พ‡๏พŸ?๏ฝงS#i_๏พๅœŸp?๏พ˜?o่คŠ๏พ‚]?๏พŠ ??ๆšŽZ/๏ฝฌ?๏พ›๏ฝฝV?Im๏ฝฑ๏พŒ๏พ€๏พˆ ?่•?ๆพค๏พŒ้ญZN๏ฝกogy,ๆต„๏พŒ๏พ€;่ˆฎ(@#=๏พ‡?ๅš๏พ†{๏ฝข?{?tS?๏พ•?R???f?6๏ฝด|F๏ฝณ๏ฝธv[๏พˆ๏พ„x1?;Wๆก†๏พ‡5๏พ‘๏ฝน๏ฝธhcrPๆ“˜โŒ’\n็›ด?{X๏พš?/r๏ฝธ๏พƒ?2[?๏ฝง๏ฝฉzF}F๏ฝด๏ฝณ๏ฝน?\r0\\^๏พ› ?H??๏ฝขI ?3d?๏พˆ?=?่‹Ÿๅƒน๏พ๏ฝป๏ฝท?IpB็ถปW?G๏พ€?m๏ฝก๏ฝน๏ฝฟ๏พ›7?!|I!@่›”๏ฝฎq๏พœ?_|๏พ”๏พ†ๅ†Œ๏ฝฃ]_i๏ฝฐ:๏ฝบ๏พ†้˜ฟo\nR๏ฝฅ๏ฝค*๏พ…๏ฝฒ?0?T?=&๏ฝฒ๏ฝบ7F๏พ“?๏ฝจ,/oR๏พ‚[๏พ›๏พŸ๏พš?h๏พ‘๏พˆ๏พš๏ฝน?๏พ…|๏พ€ w๏ฝฉ่–Š?A\"๏ฝฒ๏พ•%?๏พŠ_r2?\0.\0?๏พ”ๆจž๏ฝฐB???๏ฝฝj๏พ›๏พ—}๏ฝจt้ƒต_?็›ฅ๏ฝนๅฃ—1!?)A็ธฆ.่™ฑ?2}๏ฝน?*๏ฝฉhๆ‹†v5h๏ฝด๏พ•๏ฝขl22 zzW;erX๏ฝฃ dๆˆ€๏ฝผ๏พ—S๏ฝท๏ฝฉmJ7๏ฝนๅฃบ๏พ”3่œ?e๏พ‹P?.?็จฎ&?>่ดK\'็ซ’GS ๏พž.๏พ•D๏ฝฐ ้ถซ๏พ‡|?X?.?{๏ฝธ?.$๏พ„๏พ˜$/>?๏ฝตy้จ๏พ’bqomk2๏ฝต๏พ˜r๏พƒ๏ฝถs๏พš๏ฝณn?๏พ†๏พ†??ๆ‹‘8$FUA=?ๆนŸ๏ฝนryY็‘™bn?\0?ๅ‘‚,27๏ฝพๆ›Jk๏ฝฒiๅจœ็€•ๆ˜‡๏พ†๏พŒ??่ฎƒj}\\;้‰พ๏พŸ้จ“่ณ๏ฝฎV๏ฝฝC๏ฝขEl?r๏พˆ๏พ€๏พ†๏ฝฅ?NO็พy๏ฝผ{T^๏ฝต๏พ“?S??,๏ฝถ$0่ง’;่„ฉs?๏ฝญ๏ฝชE5๏ฝฑq??ssZo๏ฝฟ๏พŸ?๏ฝฝZ่บ…๏ฝฝๆ“‡ๆฆฑ๏ฝฅEr?p?^9๏ฝฌ๏ฝญRE่‘ก8๏ฝฌ้››($9?O๏พ—?:่ฝ—๏พ“๏ฝทv๏พ“๏ฝก?O?<โ—†\\?vG\Z[๏พq๏พ„1*ๅŒป๏พŸe๏พ›??)<๏ผฌx่ฒฎ็”จvuB\n*้›ข5๏ฝฌl4?๏พ–??ๅ–€๏ฝฌ๏พ๏ฝผTc?9๏พ‰?X\ZmๅŠŸ7?๏พ‹&้…ข๏พƒๆžณ\"๏พŠ๏พ†??๏ฝพU๏ฝฃ?็  o\rTg??๏ฝฉ๏พ™?\'P๏ฝณ๏ฝพ๏ฝด?$? eV\ra่”†\'?๏พC๏พ?.ๆƒดLSKn๏พŠ~๏ฝฌ๏ฝญ๏พ’๏พ›N?d*@๏พ†๏ฝฏ๏พšWI[??๏ฝญu0?1Z๏พ™+??๏พœๅ€Ÿ ?๏ฝต]่Š’K}?\"z?Bใ‚ป๏ฝป? ๏ฝป๏ฝจ?[ๅ‹?d๏ฝฉๅฒธ?ๆถŒi.๏ฝณK\0q๏ฝจU้ญ?^้€๏พ˜๏พ™๏พ˜๏พ˜?,e\\L๏ฝป็บŒ? ?{ๆท‡O]_๏พ˜k==u๏ฝค[๏พ›o 9P๏พ™?๏พ†{?๏ฝฎ\\ๅฎฐ?๏พ„๏ฝญ๏ฝพ๏ฝถ๏พ“4k๏ฝซ)g๏พ’๏พ™Y-็ดœ?ไบž้Š›่ฑฌๆ—ก๏พ‰็ซช& C?\Z๏พŸJ? ๏ฝฆ๏พ’๏ฝฅi\Zๅฅ—S๏พŽN6็‡ผ?G๏พš๏ฝข5?)ๅฅง?-md็จ??!#๏ฝธ๏พœ}๏พŠ??Z ๏ฝค๏ฝคN\"m๏พ๏พ›๏พž๏ฝปgไฟ๏พž)e1๏พœo๏ฝญL๏พ‰g~?[๏ฝฌV้ต๏พ„0๏ฝซ??๏พ–๏ฝก?0๏พ‹;[G๏ฝธ?B1?95k ๏พ„ๅฑค็˜๏พ˜๏ฝน๏พ‚?๏พ–๏ฝฑnๆ“?v8๏ฝพ๏ฝต?6U6๏ฝฐaๆ†ŽMt???6yr*ๅˆธ,๏ฝญ?2<๏ฝชq๏ฝป\0{ๆปพ๏ฝฉ?๏ฝฐC๏พŽ6?/? ๅšด๏พ’cgไป‹Y๏ฝท?!@5๏พXๆด‹๏ฝฑ????็ฏ๏พž๏พ™+๏ฝฃo~๏พ‚0๏ฝฝ๏พ๏พ‡๏พ†่•จ?ๅฃฎ+as๏พh๏พ“ๆฎคXW๏ฝพ??:?\Z^๏ฝช?\rS\'m๏ฝฝ้›ฐ๏ฝนc2;๏ฝท๏พŸ?\0๏ฝคk๏พ™?ๅ๏พ™๏ฝคz๏ฝฅ+\"๏พ‚ๆซจ\0๏ฝฅ)@)JP8?๏ฝบt๏ฝปๅชฝ??1๏ฝฏ๏ฝณ๏ฝง๏พŠ๏พŸi\rg\Z?๏พŒ?๏พ“ ๅป ๏ฝช๏ฝงL๏พœC.?-๏ฝฎU rZ*?B๏ฝฏๆก+i?\0?\0๏พ’d}๏ฝฃzไพต๏ฝซ้ญ…=็•ฟ็Š๏พp๏พƒ?>X??\0V็ง˜k๏ฝธV๏พš๏พœ๏พŠN๏พ•่˜๏ฝฑ๏พŸk\0G?\0?+???.X?8?F?M?:?24็‘ tJ๏ฝฒ๏ฝช(m๏พ‰๏ผธ?kM๏พ๏พ›๏พŒๅฃผ?ไนข๏ผŠh๏พ?l?? ?\0Z๏พ?\n๏ฝบ?;๏ฝซq๏ฝง\\ync้†ธo็„ผ่œฟ๏ฝพk๏ฝซ๏ฝจ?zi+๏ฝงDๅฑถ๏ฝดๅž็ท .N<2}๏ฝฐN=๏ฝซ๏ฝซWๅŠพ*็ธตFๆนถ็ฐf่พปu?,1๏พ›๏ฝจU็ฝฒ?9^G่—•/๏พ“?Kwi[7y๏พm2>??Ak}\']/?:bp?๏ฝช๏พ?s๏พ‡๏พ›็ฆ…๏ฝญ;KๆกŽๆค่’Ÿ?;๏ฝฃ76?>๏พ’\'๏พŒ๏พŸ?8๏ฝญ!่—นm็พŒR้ดพๆตทj?\"๏พ›๏พ†3DQ๏พ‹)็“ท้N๏พƒ?๏ฝจ๏พn?้ธ›Nby-?๏พ‚๏ฝชr!P<๏ฝปN?๏ฝญ๏พƒm๏พ“V7๏พšB๏ฝญ้Žฎm๏ฝฎ%๏ฝฉI??๏ฝบ๏ฝฎK/๏ฝฐq?๏พ•\n?\0๏ฝกg?e๏ฝผๆฆ›๏พ=๏พ‚ๅญ…๏พ„2๏พ%๏ฝฝ;|V๏ฝฑ๏พ‹๏พ™๏พŠM๏ฝฝ๏พ†๏ฝจ๏พ—็”ท6?ๅผท๏พ›ๆผ่ผŒf8$ๆดธ<่ฎŽ:๏พ–๏พ’[?/?๏พŸ๏พ‘?$่ฉžd? ?*?vs๏พŸ๏พ๏พ—U๏ฝฅๆ‚๏ฝฝC??๏ฝบ?๏ฝถ ?๏พ˜;?้ธš๏ฝฎ็นฉ?๏พ“้‘?\'?%&)# ๏ฝน?3,p๏ฝน\'๏ฝพ9๏พVๅ…ฅ็น”6้ƒฝ๏ฝฆ๏พ๏ฝฃM่คฅ๏ฝต?๏พ‡??3๏พŽ1ๅฐ‹ๆซƒ้คกoq}๏พ‡ &d๏พ๏พž้‡†3?;ๅฟV=๏ฝฝ๏ฝฝ๏พƒ๏พ‹V๏ฝช&y๏พŽ๏พ…@99๏พ‡W;๏พ‹;๏พ‹ ๏พ‰๏ฝฌ๏ฝค ?a๏ฝผ2|2๏พƒ๏พ—๏พ›4iY$๏ฝฅๆฅน{๏ฝง๏พŸ๏พƒ2\\๏ฝฉhๅปฉ็’ฝ#p?F?6๏ฝถๆ‰๏พ“๏ฝฃR๏พ’?\"๏ฝท๏ฝนๆž‡77?VUQ?8?z?R2HH่ผŒ ๅนฒh\Z๏ฝฆ็€•g2Y\\Ex?%๏พŒR๏ฝฝ ?$(๏พ๏พ?/็‡ฅ?/Q๏ฝบ>0้žIo%๏ฝผ6๏ฝทS้ฝฌ\Z?!?#็‹ฌ?8%W\'\0gjAp?ๅฝฆ๏พ•ZX๏พ†9\'n\0?&๏ฝฐP?#L๏ฝฝ๏ฝฆ๏พŒ๏พ;๏ฝฏ:r?ๆ“ฌ๏พ‹9๏ฝฌ?๏ฝฃ๏ฝต?ๆณ•๏ฝธ?๏พ”z้‡€c?๏พŒ๏ฝฌ๏พ”๏ฝฉๅฃฏ๏พ๏พ†ๅŒš๏ฝต(๏พ”๏พ˜๏ฝฒ๏พ็ฏฅoq?2?0y่Ÿ๏ฝฝVz๏ฝณG?E?l่ฅฏ+็Œด๏ฝธ?.@f้‰…I๏พ‡๏พ–๏ฝฒ4~๏ฝฏ[wๆ?63!!๏พ?๏พ‡?\r?>๏ฝต๏พ›๏ฝงkV๏ฝบ?่žฏPAp่ž‚โˆจd^p๏ฝชๅŽฎa๏พ‡|๏พ•็”ŒU?9๏ฝง?๏ฝฃ[e๏ฝท้ณฌo๏ฝฟ?!๏พ†๏พ‘๏พ€๏พ๏ฝญr้บ—gf๏พ–ๅ‹™๏ฝง?,ๅปE\'rc \0G๏พœ?8๏ฝถ5๏ฝฝ.K-็ฌ›Xๅ–š่ก„H๏พ๏พ=๏ฝป???|๏พšn๏ฝก\"r?3๏ฝฎF?\0๏ฝฅz?\0Bๅ“ขx๏ฝฅ๏พžๅ‰๏พ‹tp>4\Z?6่“ผ๏พ“๏ฝซ(่ก—๏ฝพ?@๏ฝง<\\?๏ฝงRt๏ฝฟR้—ฅ๏ฝด}A๏ฝง^๏พ˜\\\\๏พ็ฟฆ.ๆ€ง2?<ๆžนๆญƒๆŸฌK็ฃ”P้ฐก๏ฝญh=]~้˜ป? 2๏พŽ,U๏ฝผ๏พ‘๏ฝข๏ฝณ) H๏พ€a๏ฝด?5;?|W?oR๏พ›jๅฅ”$?\Z}๏ฝฌ^I3?ๅ†’KI?>?๏พ5?.I%๏ฝฏๆจฝEsๆ‰็งŸ}๏พ„ ๏พ†G๏พ”๏พ–fๆญน0๏ฝฑ{??1glO้ฐR๏ฝฅr@๏พŽ=๏ฝณ?็›ฃ๏พ”cA)M๏พŒ๏พ…I็‚ณ}?*๏ฝต?7๏พ‘็จn็ญ๏ฝฝ=๏ฝบ๏พ†๏พ’๏พ‰eP่จฃ๏ฝน>??1Z่‹’?๏พŸKe$๏พ”J๏พœ0้ป๏พž๏ฝก$vqI+๏พ‰๏ฝทtqd๏ฝจ\n03ๆฅ}j็ฝ‘?&้ป ๏พžๆฆœ?M?๏ฝฎ?่ผ’ๅฑถS+c; ่žป?>๏ฝฃ๏พž๏ฝฏ?R]7๏พ‹้ซข็‚Š \"๏ฝท?\"?\0๏พ†N๏พž๏ฝฎๅฉ??D??ๆ“‚ๅซ๏ฝถ?\"+5๏พ๏พ”? [๏ฝฆI๏พ™?I,๏ฝตx๏ฝฑ?L๏พ“Q๏พ…\n_๏ฝน 6๏พ\'MV้‹บWo่’?;๏พŠ๏พ„pE็€๏พŸ?๏ฝต.ๆ˜ง(๏ฝฃi{{F๏พ„๏พ—้ˆŽๅฏพ;*?$๏พ–๏ฝซ๏ฝทVv้€€ๅ…Ž!?,๏พ…๏พž~๏พœๅฏพ~๏ฝต?))h๏พ€ใ‚ด๏พ”?8๏พ–9ๆˆฐ+๏ฝตB3?๏ฝฒๅฃฝC๏พ™๏พš;๏ฝฆo?4๏ฝฝ๏พœ;}๏ฝฝ~๏ฝต7๏พ’??๏พŸ?!๏ฝคf[j้šฃ้‚ธ๏ฝข็ฑ˜\'ๅˆณp<๏พ‹?ๆ‹›Dj๏พ้ตบ๏ฝฏ๏พŠ\"๏ฝปๆ›ต?\'e๏พ„aไบณpFNy๏ฝซPtๅ–ซ7๏ฝถ๏พ๏พ„s๏พ›๏พŒ๏พ›ๆญช ๅฝก๏ฝฟ>๏ฝตQ๏ฝบ๏พ•?ๅนป??๏ฝปๆดž?ๅ‡ๅ€Ÿ??#?๏พ™,๏ฝต๏พ˜๏พˆ๏พ“๏พ™๏พ†5)J๏พœ~\'O<๏พƒ?aN????๏พœ๏พ…lๅ“ข??dd็”ปPp???J[{๏ฝท?s๏ฝด๏ฝค?6็ฆฎ๏ฝฝH๏พ‰๏ฝถX?w๏ฝบๆกƒ๏ฝธ๏พ‰$?;๏พ–P?1๏พ†nR๏พŸ? :๏พ†๏ฝง๏ฝจ_k]๏พŸ๏พœIr?1,mU98S๏พ‡๏พ•mkmj?๏พŸP๏ฝปi\'?ไพถๅธ ๏พˆ9)็พš|็’ข?๏ฝค๏พ“ๆนง?4่ …่“ฎ๏พ’L๏พŒ๏ฝคๆ–›?o๏ฝทon?\0Jๆชei\'R๏พš๏พ‹๏ฝฉy\"่ฉ‘ๅซฃ\00ๅ‡?๏ฝฎ๏ฝฆ็Ÿญ]ๅฅ๏ฝถ๏ฝฉ}k๏พ’?m๏พ”1]a๏พŒ้€—2๏ฝธ\0c\'๏พ”?๏ฝซ๏ฝฟ๏ฝง?ๆŒซ๏ฝป๏ฝบๆ›ฐ|๏พ†pp0Nq๏พ๏ฝฆG?9๏ฝบๅนฝ๏พ’zใ‚„๏พ„?๏ฝณ้›T$crFH?๏ฝซ\r?-๏ฝญ้ถฏ๏พ‚่„†-๏พใ‚ฅ๏พ๏พˆ??\0๏ฝฒ1?gk?\"u๏ฝจFไฟฏๆท…?\"Zv?\n?๏พš๏พ„gๆ ฒG๏พ’๏ฝข?,[P-*๏ฝฌๅฅช๏ฝป?eNN{่‹Ÿๆฌ–?+่บช้ฎƒwS4๏ฝบx{๏ฝซ๏ฝซxB?๏ฝจ |v${?๏ฝจ:๏พ…๏พž๏ฝก๏พไนขk[๏ฝง๏พ„?\\19?#๏พ}\r^๏ฝต๏พ™\rๆบ€๏ฝฃ๏พ—?,??4๏พ‡#?8๏พkkๅฉ๏ฝธๅ‹ธ%่ฅฟ๏พ…๏ฝป็„ถ ๅญ่—พๆฆŽ3๏ฝธ๏ฝฆY๏ฝผ๏ฝป๏ฝฒs๏พc๏ฝถ?\'ไฝผ๏ฝฃ๏พ†๏พ€H๏ฝฉ๏ฝธ2๏พๆจŸ+UT๏พ€ๆผ p๏ฝฌI๏พ‡$๏พ–+?Nl?Q 7R[็ƒนbb๏ฝปๅฃฌ๏พ•?? c,่ฑ•?)?ๅชผ๏ฝฟh๏พ›?๏พ„?E๏พœ๏พŠ?๏พŒ?$ไธน๏พž๏ฝป5Sr?!๏พ˜1๏พ˜่Š๏ฝฑI็‡—X๏พ•l๏ฝฑ???q|=้บฅlHL่ž๏ฝธ๏ฝตd๏พ‡\0C\n09?้‰š๏ฝฏO๏พ–??ๅ–œ่”ฆ?้ณฌB๏ฝฒ๏ฝฝ๏พœ็ฅ๏พ‰ๆ›‡???U๏ฝญ๏พ^\\๏พ๏พ‰ๅฉ?)J๏ฝฉ\"ๆซจ\0๏ฝฅ)@)JP\Z๏ฝซ?๏พ‘?5ๆธŸ?็พŒ๏ฝณ้ ‘่ด…(๏ฝฏๅ†ฌ๏พcXeI%u-๏พ˜?N๏พœ่‰3?t๏ฝฝ๏พ€ๅขœd??้™ๅ ด๏พ–ๅฉๅฉฆ๏ฝฅ๏พŸ๏พ…็ถบ๏พž@?๏พ‡๏ฝธ๏ฝฎ?J๏ฝฐ๏พˆ ๆ’ƒy5?๏ฝงi๏พ—Z๏ฝป๏ฝฉt๏พ?๏พ‰u๏ฝฅ๏พž๏พcp?Q?7(๏พ…I\0่ฃ…8๏พˆ่ฉ?%dq9?๏พš๏ฝณl?:๏ฝฟ V๏ฝปxs\0Y\0\'98?๏พ๏ฝฏ@?o๏ฝซ้ง›%U$๏ฝจ??๏ฝต?\r\Z?)_?ๅฃ>_Z๏พŸ?5_ๅž‰?.๏ฝญ๏ฝฐ d ๏ฝฆ28?+๏พ”??0๏พ†??๏พ๏ผž๏พ‡๏ฝป ๏ฝด?๏พ•๏พ—HZA๏ฝชOz๏ฝถ๏พˆQ?*๏พˆ๏พŸ>่ฐบ็ฒๅงซ็”ณ็ฎšๅ‰–2[?๏พš๏ฝผ๏ฝต9G๏ฝฃf๏ฝฌ๏พz?๏ฝท๏พ—๏ฝตi.?zM?)๏พž่ชž๏ฝค๏ฝฏd ๏พ…ๆฏซ?z่ฐ:็›ฎ?;ไบ‹๏พ—! .\"๏พŒHTo๏ฝต?#?๏พJ๏พ]K๏ฝฅhzt?๏พ›A๏ฝธ\'?๏ฝจ่›ฉsZC๏ฝจ๏ฝฎ๏ฝดn๏ฝฒๅฑUfใฐ?๏พ‚6YV $w? ๏ฝฆ๏พ…gpI็‘ฐ๏พzf๏ฝฒz๏พ’?\0Bๆ…Œ๏ฝญ๏ฝต{mๅ †s?9ๆ‹ถ๏พŽ๏พ๏ฝง\0่€ฟc??@๏ฝฌ;g?Mr\rๅ™‚่ˆŒk?FH8?>๏พ•๏พŸ๏พ•XF๏ฝฑ๏พg%๏พ’๏พŠT๏พ‡q๏พ‘7่ปฝ๏พ?$?)่ˆ=๏ฝช๏ฝฟ?,๏ฝฒ,?;๏พ…p8็บœ?G?+๏พ‘J๏พ‘ๅ…ฎ๏พ‘~N๏พ—_%๏ฝข๏พij7?3m\rๆทจGb}๏พ†9?8ๆŸณ?C!๏ฝต๏ฝท๏ฝฐ?๏ฝธๆ…ถ}๏พ–Kmf*T๏พ‹wo^}j๏ฝฆ?.t๏พ”?0[?!?W\n0๏พ’q้ปฅ๏พ„ๅค›ๅฏฟpๅ‹™๏พ‰?๏ฝถj๏ฝฆ^๏พŠ? ๏พ‚e\'=?๏ฝต#o๏ฝฒI9$?[?\Zm9?๏ฝฑ๏ฝฌ็ฌ›O*N๏พ•ๅ ‚๏พ๏พ‰*y๏ฝญwt๏พ‡W^[uZks??9M๏พ„ๅ‹˜\Z\'๏พ‚;ๆฒŒๅธ‚?๏ฝฐ:[F??[๏พ ๏ฝท?!ไผธ๏พ™H?!}?>็ญŒ?#๏ฝด๏ฝฑy?K่พจ?่‘‰E dq?0?๏พ„่’ก?Ic๏ฝญ\"้ซฃ KF่ซ‡x ?๏ฝธ๏ฝบ๏พ‹l?๏ฝท๏ฝท๏ฝฅg?>%๏ฝผ่ตญiVVE)&?vqP:6๏ฝก>๏ฝฅ4๏พ–๏ฝฉd??ๆ”€๏พ™๏พ‡๏ฝก้‚?X4?Td]N๏พ–?+?๏พ‚๏พš?(A\rโ‰ ๏พ‡9?_๏พ‹็‰ง๏ฝฃD๏พŽ๏พ‹h?0 Dr๏พŽ็ญด?๏พŸm๏พšMO]??๏ฝพๆœŸE๏ฝฝ๏ฝน๏ฝถ๏ฝฑ@?๏พ…\rฮฒ\'๏ฝธ?๏ฝธ?*๏ฝกstๅ›บ?\n=?๏พ…็ด‹dๆ‚”Nๆ‰˜๏พš?๏พ๏ฝตdk:R๏ฝฃx๏พœ#๏ฝฏ็ฏ‡๏พŽT???mB๏ฝฟ๏พ—X๏พ‡๏ฝฆ?๏พๆชœ๏ฝถ$??u ๏ฝฏ่บฏ+๏พ‰t??๏พ‘๏พŠ๏ฝท?&??O๏ฝญZ1๏พ˜l๏พ‡๏ฝฝkq9ๆ —่ก„T?็ธฆ?ๅ†ข?a,? ;y^{๏พ–=่ก„Xๆฎฑ?ๆ—… HVld??-Qๅจฏ๏ฝค๏ฝฉๅŽฐZ%๏พŠไบ•F๏พŸใณ?,q๏ฝป่‚‰??5ไบซC?,?)q๏ฝขๆฃšN?HS๏ฝท*~๏ฝธ?&๏ฝซๅฟ:๏พžฯƒ๏พ–LZ๏ฝฑๅฑ $๏ฝชๆฒผR}?๏ฝท=?<๏พ๏ฝฅ่ ถ??๏ฝท๏พ”๏พ…6๏ฝด๏พ‰.๏ฝค๏ฝถ๏ฝน๏พ’๏ฝงs{i,๏พ„?๏ฝผ?๏พ‡?8??M?,-๏พ‡\Z 0!??=๏ฝฟ๏ฝฅp[๏พœG$็ด—#๏ฝฐ+\"๏ฝฎ|< ;ๅŽจ?\0_๏ฝพe๏พ”Z|๏พžu ?Z๏พ|$\r๏พ€e๏พšs๏พ˜$?๏พ๏ฝปW้›™๏ฝพ\r#6ๆข”๏ฝฎ๏ฝขy?/\"[๏พ™n.Q:๏พ‚๏ฝฎ6s???๏พž๏ฝฃ๏ฝพ#๏พ…i๏ฝช้คฌV๏ฝฐi้œง๏พ—i?y?pยข้ชผ็ช๏ฝถ๏ฝธ?=๏ฝง-?๏พ“๏พš?๏พˆ?๏พ๏พ‹(9๏พˆU8ๅฃโ—\n๏พ‚?๏พ๏ฝจ๏พœ๏พœC}?๏พ™๏พŸ๏พœ]๏พ‚๏ฝฌ่พฐ D?3๏พ€๏พ™?๏ฝณๅพญ]x??๏ฝด^[ๆ‹’๏ฝญ๏ฝต?่ƒด๏ฝถ?%๏ฝผ=J?3f73)\'+๏พO#ๅ…ผ๏พ๏ฝฅMt%๏ฝพๅธฏz๏ฝฝ๏ฝฆ๏ฝณ๏พ–\ZM๏พž๏ฝฅe?+oๅธฏ๏พ”๏ฝฐA#่จ—๏ฝญ?ๅฅจ็ช๏ฝบ?\\:k๏พ๏ฝฉi๏ฝฒ|็ฉ—่•ชk)<ๅ›ณๆฅฏฯ€3R๏ฝบๆน˜[๏ฝช๏ฝฏ่ข’??\0๏ฝช&้‡ฃYๆœ{ X?็ชฏ?๏พ›๏พ†H?5?~๏ฝง?,+_?็‡Ÿ๏ฝณ๏พW?่ฎŒu-๏ฝบ3๏พ‡๏ฝฝ??J๏ฝฝt?8?Xm?29?\\?๏ฝด2G?U?\"];P๏ฝบ๏ฝพๆถœ๏ฝต2๏ฝผ๏ฝด (r?7~O๏พŸ๏ฝฟ?๏พ—:?2+0\'\n?6 ๏พ??\\่ŽžmR[k?๏พ‚I?;๏ฝข๏พˆT?H๏พ›๏ฝด?3๏พ€?่ฑŽllXG&๏ฝก,O 0๏ฝฒ?%<๏ฝผ?(??~9๏ฝซ/๏พœ๏ฝฉ~?๏ฝญ๏พ‡๏ฝฃ๏ฝท?0\\,๏ฝฌ๏ฝฐx?๏พŠ็—๏พ‡๏ฝจ๏พ‡?๏พˆ้ฌฎ๏ฝปc+๏พœCiPF\n้˜ฟ<+๏พŸ?๏ฝญKbm็พฏ๏ฝถ๏พ†ๆถ็‰ข็šš๏ฝน;d๏ฝจ=?ๆžณ?้ป๏พ—? W/?่œ‘U\'?๏ฝฑ๏พ‡่œด?8\'?ๅ›‚e๏พŸ]้ผก-*๏พ‹Uๅ‹Y๏พ‡?๏พœ@๏พ†~?Zใ‚ฝ๏พ•n??๏ฝผx๏พ–e\\eF๏พ’y?\0๏ฝญH?v๏ฝฅsuekoipZH๏ฝ?2?๏พ˜>๏พŸ_๏ฝฅC๏พ๏ฝง๏พœ๏พƒs$mLj๏พ€๏พ€?W๏พ‡aIIZ:??๏ฝง๏พ“๏พ›?icEd??+๏ฝณP?\'๏พ‡k3mte๏พ??+๏ฝฟM๏ฝฑ๏พ›i9๏ฝน๏พ›U?c๏พŸ=๏ฝช?๏ฝฒ/e~RY๏ฝผ๏พ‡$?&?\"๏พ›๏พ„๏ฝฆ>+๏ฝฏๅˆงu๏พ‚๏ฝน๏พœ๏ฝฎ๏พ—๏พšy>๏ฝง๏พ’๏ฝฐ?9&๏ฝฑๅ†ฒu่ชฐI๏ฝฎ็•Œs๏พ‡8๏ฝญๅฑ‘5h?O?๏ฝค๏ฝด๏ฝป๏ฝญ๏ฝพ๏พž๏ฝน&?i๏ฝO!ๅพ„O๏พŸ๏ฝฑ?๏พ™%Ql๏ฝฒ??้—•?้œ“๏ฝง|a7?:๏พž๏พ‹๏พ„?(๏พ•7c๏พ“;sS๏ฝฅyf๏พ‚ๆซจ\0๏ฝฅ)@)JP\nR?๏ฝผ????\0๏พš ^ใ‚žๅ„ฒYa๏ฝซ๏พ›?37ๆ —่Žซv?2๏พŒ\0>?W๏ฝฟk๏พŒ_๏ฝท๏พž?O?W๏พ†?๏พ†?K Qa๏พ‰t?7๏ฝซ3่ฝข๏ฝฆ\0 ่ข๏พœz?y>๏พžd๏พŠd?(๏พ‘๏ฝขM๏พƒ ?y๏พš ?5m้“V?+๏พ•ใพ๏ฝฐๅบEld๏ฝฒๅบง}x๏ฝฉ:y3๏พ˜ๆ–ผ\'??๏ฝฏM๏ฝปK3g๏ฝซ@?.?a็ธท๏พž=๏ฝน๏พŠ??j?9~P\\?๏ฝค็’ž?่ฑฌ๏พ„๏ฝถ๏พ†7#\r??๏ฝกใ‚ฟ?9๏ฝฉ๏พ…36๏ฝจ็ธพa\Z่ป๏พ…็ขพ?่˜ข ?8๏พ€>ๆšŽX?๏ฝญ?๏พ’u็˜‰[๏พ„่ผ‰\r็™‡A่˜ญ\\ๅ็…Œ?๏ฝตy?V๏พˆWsD็˜ง?0๏พŸCๆจž๏ฝถ=๏ฝฌ??๏พ–๏ฝฝ-Wv็ฒ? ๏ฝฅ๏ฝท2?6๏ฝจ?4dgz๏ฝฑ๏พ๏ฝปp!B้„’+,ๆŒซ๏พ›Z,๏ฝถi?ๆตธ๏พ‰oo+ P?๏ฝฒ?N>??๏ฝซ๏ฝฃO๏ฝณ?๏ฝงg|๏ฝฐC๏ฝดc??่ณ“๏พ#็€‘๏ฝฝ?yu้Œ]ๅฒถ?@??q๏ฝท่‰ฒA=๏ฝช?+๏ฝฅn:Vm2๏พš๏พšh็ช—RN?u?ๆธ‰ ๏พ‡๏พ‡๏พš๏ฝจ๏ฝณ๏พ‚Oๅž‹๏พ‰็ณบ5?|๏ฝฝ๏พœ6๏พ‚Ek?:??๏พŠ?+7๏ฝฉu๏ฝจ๏พ??$??2๏พ‡๏ฝด1 ๏พ˜๏พ๏ฝง?๏พ๏พ€?๏ฝฐ?๏ฝข6๏ฝข๏ฝค๏พ‹?? ?๏ฝพ๏ฝฃ๏พ…[:?J?๏พum๏ฝช[้ป่ทŒ๏ฝฌ๏พ’๏พ’๏พž๏พ™็ถ›dS่ฌ ?๏ฝฐ๏พƒg๏พ“๏ฝน็ฎ‹ๆŸฏF|_e็จšh[๏พ›b?๏พ,N?>??๏ฝช??๏พ‡Pi๏ฝณ๏ฝฌ?zt0่–„Y?๏ผ#?\02๏พ‰^๏พ\'๏พ€g2\n๏ฝฆ0O#๏ฝตv๏พ€dๅฃฏ๏พe@?ๅ’ฅ๏พ€?Uๅณกz^?n/A๏ฝต?{i?]๏ฝฆ0 !็“ฐA ๆบๆชŽ5Mk๏ฝงๆ—ฆG $\nG๏ฝฅh๏พ’่ถ…I๏ฝณ:C?ใ‚ซ๏ฝผ๏ฝฝ๏พ”๏ฝตo P?๏ฝฐ?)!๏พŸq?\\a๏ฝณ?๏ฝง??r?๏ฝฌE|V?*๏พ—\0?w\0๏พœ?Wi?๏ฝพ+[t๏ฝญ?o๏ฝซ?๏ฝตj๏ฝฐ๏ฝบ๏ฝฒ๏พša$็›ธ??๏ฝด๏พœ็‘ฉ;T๏พœ?๏ฝบh6๏ฝบTJ?\\๏ฝฏ๏พŒG2\\๏ฝด?๏ฝน ?{??\rr๏พ๏พ‹Y?&๏ฝตs+M่ข๏ฝด?)๏พ‹c?๏พ˜?๏พŸๅ’จ๏ฝซWๆฒ“๏พŒ?&๏ฝฑ?>ๆ€๏พˆ|๏ฝฆ๏ฝท?)๏พ‡็ˆ6่•๏ฝฉ้ ธ?67V๏พŽbpw๏ฝท ?1๏พ€๏พ†}j่กฒ=O๏ฝฏ|๏พ•๏ฝพ้‹ฒ?(ๅซบๆฌ?&,๏ฝค๏พ™<ไพตI่ฑฌ๏ฝฏ๏พ?>๏ฝฑig-?๏ฝฐ a๏ฝถ?s้ด†?๏พ“๏ฝบeๆฌ’ ๅฑ่‘Ž?-ไผ๏ฝท๏ฝพ็‹ญๅŸŽ^&o๏ฝคK?\0๏ฝป็…‰ๅน•?$t๏ฝพ๏ฝฟ๏ฝด๏ฝฐ๏พ—๏ฝต9n4k[๏ฝญQ่œด9?๏พƒๅฅ„ใƒฒARFrsY??๏พ’7๏ฝผ็’ฐ[?;?#Iใ‚ฃ๏พ€ๅฝญ?=?F;๏พ•3?ๆ“ง๏พ๏พ’๏ฝทๅž“๏ฝถH.๏ฝฎeJ??๏พˆ \Z?r\0๏พ†q๏พš๏ฝด่žฏ๏ฝญ.๏ฝขd?ใ‚ŒC?\0๏พƒRx?้†ด๏ฝบ๏ฝฑ}.R๏พ‡|??\0\Z)๏พŽ\\๏ฝช๏ฝดo๏ฝธnt6?๏พ”๏พ–?ๅ””๏พŒ๏พ’ๆฃš?\'x๏พ๏พ๏พ€?๏พˆ?้›–๏พ„๏ฝฟ?ๅพผ?๏ฝง๏พT?่ŠŸ?xS?+๏พˆ?1๏พ•?๏ฝพ่•ŠYT๏ฝนๆ—จ๏ฝช๏พ’7c็›‚_)yOไฝต?\"๏พ˜Z?๏ฝป4๏ฝซๅถ?3 ๏ฝตๅ–‡?๏พ]ใ€๏พ๏ฝท้–‡๏พˆ๏ฝผ้‚‡^;p๏พŠ๏ฝซ?z,๏ฝค๏ฝซf่ด„5;๏พ‹ Hd๏พ•X๏ฝณ๏ฝก8g?O๏พƒๆบ้–‘?\0๏ฝฌ\"?^9l\"\"?;ex๏พ„l๏พ“๏ฝธc??E๏ฝฟ๏พ… u๏ฝป๏ฝฟ๏พ‹ๆฅ2I็ЁF%๏พ† s?c?=;VๅŸ๏ฝบGP??B?;t+็™ชFๅŠต?? q๏พ˜ฮบ็…\Z๏ฝพ?#?{-fwN๏พ›?7:๏พš๏ฝบ?o๏ผ›???)่™น?9๏พŠ๏ฝถNt๏พ›๏พ๏ฝง4Nๆฏ›๏พœ๏พ…j๏พ–?f ?<๏ฝค่ŒŽ่ญฒ๏ฝจ๏ฝฎๆฆ•4}OW?4๏ฝฃ%?;๏ฝฏ;๏ฝผ๏ฝฒ?๏พŽ~?๏พ—?qp5{=G๏ฝง?(? @๏ฝพ\Z*\'๏ฝฟ??๏ฝฒ}r+_๏ฝฝ\'๏ฝถ๏พ‡Ew๏ฝฏ๏ฝพ_้ทฏ/๏ฝฝ็ฏญ๏พ–aะป๏พŒH2๏ฝทC\"๏ฝฑ?;?๏ฝก๏ฝบ๏ฝซ็ธYi?$ใฉ่ถบ?่ช…-๏ฝญๅผ็ซš?F$๏ฝฑ๏พ›?=๏ฝฑ๏พz็ฏฉ๏พ„๏ฝญ&=ๅธ?๏ฝฅ๏พ‹f๏พ’\\ๆ•๏พƒ!>E.p๏พ™?๏ฝฝ๏ฝชZ๏พž๏พŸ๏ฝถ๏พ‹่ฉ†๏พ‹\0๏พ’็†•๏ฟฅv๏พ‡o|๏พ”um้–นb[5??zyๅฑž$p?็†ฌ}3V?๏ฝกR๏พX๏พ’?\\I?8๏ฝฝ๏ฝฏ?๏พ˜ ้ถซ๏พ‰?๏ฝฟ๏ฝญN?<๏พ-๏ฝบ{V๏ฝธf๏ฝธใ‚u@Z้ฅŒb\"R๏พ€๏พœๆ›ฐ??๏พ‡N? ๏ฝฉlU%๏ฝพgf่ฌ€ ไฟ˜?ๅบ„๏ฝฝq๏พ๏พ\\???\0??\0m*๏ฝฟg๏พw๏ฝฃ๏ฝญ?4้‹ธ4ๆ›ผ๏พ™๏พ’a$๏ฝญtX๏ฝณๆฒ™๏พ™H9๏พ๏พŽ\0Z๏ฝฉ้ฎ—f๏ฝป๏ฝฎi1?้คŒ๏ฝงZ๏ฝถ?X?\Z^๏พ‡\nyv??>๏พƒๅฃ“๏ฝพ็ถฑๆบถ\"ไป†๏ฝพc?9m??\0่‡“O\\V4??VOXๆ–ˆg{??C๏พ˜ๆฆฒ?็ฏ#่ข*/.้šช[Z_๏พ„ๅ“˜๏ฝด?๏ฝบ้ฑ†๏ฝฃ?#BdX็ฎช?3๏พ‰?๏พš๏ฝญ?D?๏พŽH๏พ่‰˜?๏ฝฉ๏ฝคq?๏ฝฅ๏ฝฆcBๅฎธๅ›ณๆค‹?๏พ›M๏ฝฆ๏พ™๏พž๏พ…,ะœrav\0?.๏พŸ?:๏พŽY%่ข‹๏ฝ-ๅฟ…ๆ“”KV6>Y\Z๏พqRJ๏ฝฏ9๏พˆ??k ๏พ€ๆ–ฝ?&ๆ›ฐ@ๆ‹‘๏ฝณ๏ฝนq?~๏ฝน๏ฝฎๅบš<?่ข—n่ญœuNs้ดฟ?่ป…t?๏ฝฒvm๏พˆ่œ€x้‰็ฅ๏พŸY๏พƒ๏ฝฎ?w๏ฝฃ๏ฝฉJๆฑ‚-๏พŒ+!U๏พ„A? ๏พ— ?๏ฝท?๏พ#๏พ‹๏พ˜็ฐก? #U?\r่‡ \'๏ฝธ๏ฝบ&็ชบ๏พ9\'n9>๏ฝผw๏ฝญ%ๅ—ทvๅดO๏ฝฒ๏ฝฝ๏ฝจZi?3x๏พš๏พ•๏พ”๏พš่—ค ? Dh=\nDๆพ?#๏พ’๏ฝธ3่ณๆ‰พ[7u)J?4๏ฝฅ()JJR?R็ฎฑN?๏พ‘ๆ–็–ฑ๏ฝท๏พ’๏พž 9?C ๏พŒ<๏ฝซ$r,๏ฝฉ๏ฝป๏ผทๆณ•pN9๏ฝซ?(ๆŒˆๅœˆ/๏พ•๏ฝธ๏ฝท$bt๏พ™๏พ???๏ฝฃๆ‹?๏ฝถ๏ฝทIL!๏ฝถ๏ฝบ๏ฝฌฯ†=๏ฝฟ#]?>??i?6๏ฝซg๏ฝฆ?;5=9๏ฝฎ๏พ•Ys๏ฝผ(_๏พ€๏ฝขU็จ—ๆฟ›@?๏ฝฌ๏ฝญ}Z?N๏พ—๏ฝขP#๏ฝนR๏ฝฎGeๅŽจ5>๏พ‡๏พWIO ?9a้–˜?๏ฝญN๏พ˜Ijๅ˜ถ๏พš.๏ฝงi๏พŠ\0?3JT$?๏ฝผ?่–ฉj๏พ—๏ฝช?ๆ€ฏt\r๏ฝฎ๏ฝญ\r?ๅญธC!\\๏ฝดlๅ–š๏ฝต๏พˆ่ฟฏ๏ฝฌ{?????๏พ™๏ฝจ๏ฝฎ๏พ’๏พgx๏ฝญๅซฆ;n็‰™9?๏พ?#?9๏พ‡๏ฝตbiWmo|%b+xๅจŸp?่ฒ๏ฝธ็ทป(?({ๆท๏พ•๏พŸ๏ฝจ[๏พ™Ewpf๏ฝผ็ธฎd้†?\0๏พ’๏พ„?+๏ฝก๏ฝฅ๏พ‘๏พ‹๏ฝฑ้บฉๅค›KT๏พ’๏ฝต]=4๏ฝจ๏พ•๏พ?v?๏ฝฆO๏ฝช??xๅ‰ฒ๏พ’,๏ฝฏ?x๏ฝญN๏พˆk :4BTrJ๏ฝข\r๏ฝป?.pF3ๅฝ™๏ฝจ?W๏ฝฑ(่€จq_๏ฝตX4K?N $2I D๏ฝฒ็—ž๏ฝก๏ฝณ?{s\\๏พ’๏พ…๏พ†?N?\"๏ฝบ?%?ๅ“ฎe$,r\0J($$c๏ฝฃl? ๏ฝท ,2J?๏พ„๏ฝฉๅˆป???๏พ–๏พ—}g๏ฝค๏ฝต ;a%๏ฝต๏ฝต๏ฝพ๏ฝต?๏ฝช๏ฝฏ๏ฝฒ๏ฝ“๏ฝช?8๏พ†y?Q?๏ฝง๏ฝงY๏ฝจๆ†>๏ฝกcqs็‘๏ฝฑ!?2LEq๏พŽ8๏ฝช๏พ‡%้ณงQ%๏พ‘๏พŸu;=N๏ฝท๏พ•u[๏ฝฏ๏พ๏ฝฑ/?;(27๏ผ™?้จ“?๏พ•r๏พ•/:g๏ฝฉ๏ฝบvhl\r?V4๏พŠ่ด? ๏พ†?่ผ… s๏พ†+G๏ฝด^?๏ฝฃ4?8}๏พŒqๆช่ˆ๏พ‡๏ฝฅlO?\r:Gw๏ฝง,?2I,N\".?? ?๏พ„่œ๏พ›๏พ‡๏ฝถEa?W่މ-้šฒ??G๏ฝจ?๏ฝฑc๏ฝซi๏พ—๏พ‘๏ฝฅ๏พ€+)1๏ฝฆ๏พœ่’Ÿ๏ฝฃa?๏ฝฝ^??}9u๏ฝง_๏พ๏ฝญ?yl๏ฝฑ๏ฝดQ๏ฝบ๏ฝฌ6?๏พ‹).?vๆค๏พ‰?๏ฝฃ?้คŠ๏พ“๏พ†{$X่ซ??;๏พ‘่Š™ๅƒฅF8๏ฝพ๏ฝชn๏ฝด๏ฝถ?!๏ฝปQ๏ฝต่‡“8VOF๏พˆ98>๏ฝตๆŠž๏ฝฏ๏ฝซ5?4๏พ‹?:+?\'y\0G@๏พ›๏พ–<๏ฝฑ*่ฉข๏ฝช>ๆขณ็”œ๏พ–-s๏ฝฃ?๏ฝงo๏ฝฌ?๏ฝฃ๏ฝถ๏พ“ไผM?4๏พ›๏พ…Yp๏พ„8Sใƒฒ9่‰จ๏พŸ๏พ‡6?KEๅฆ„&๏ฝผ๏พŒ๏ฝฏ๏ฝต๏พฮกๅตs๏พ‡๏พŸ๏พ–๏ฝถ๏พ๏พ€]+E๏พ•5๏ฝซ?#X๏ฝตๅ‘ˆ?Mv๏พ“ ๆ“‡็…•๏พ|v ๏พŠ๏ฝต^๏ฝซ๏ฝฉ๏พƒ4r๏ฝญ?f>\Z๏พ…cะญ๏พ…๏ฝธ?ๆจธd้—•7Wๅฎ‡๏ฝตik,6m?%?$v็„ผ๏ฝฎ๏ฝฃ?#๏ฝฑ?Zeๅกž็†น๏พ‹๏ฝญ๏ฝฏL๏พ›?T๏พƒ๏ฝข??Ec๏ฝง๏พ˜?๏พš?J8?V๏พ†L?;?&๏ฝซMg๏ฝง๏พ˜j้Š๏พš๏ฝฎ5 %vX่‹ฃ๏พšU?๏พ‡๏ฝฟ?C?\0?๏ฝต๏พ”ๆช„F,7๏พŽ๏ฝฒeK31๏พœๆš—!ๅถฝ่ญฌo๏ฝฎ๏ฝข{?0๏ฝฑX?$?ไผ๏พ†?l๏พˆ๏ฝปๆŠฑ;J+0x??_1๏ฝนU|68๏ฝฑ%๏ฝพa?่“ฟ้ป1s๏ฝทv1ๆถธ๏ฝฅa๏ฝณ?ๆš—s๏พi??+S๏พ’่Œƒ๏ฝงaๆจข?./๏ฝฎX|๏ฝฅ็ฆ??๏ฝค้œF? 3?8B๏ฝขv?\0IๅผŒ$๏ฝฝs?.๏ฝค้ปฏๆ‚mG@๏พ”n,๏ฟฅ๏พๆ›ฐ๏พ›F??ๅพŒ๏ฝฟc้ฉ€GJ๏ฝธ๏ฝถXu?1๏พ‹ๅถ8?๏พ†๏พ˜n\0+๏พ‡9?๏พ–|\\AM?7๏ฝฒ๏ฝป๏ฝธ๏ฝบ๏ฝธ๏ฝถ1๏พƒoQn?๏พ„gH?cๅธ‚?P?๏พ‹?*I๏ฝค??X|4~ๆ†ง๏ฝผ้™œ ~?๏ฝพX๏ฝถ๏พŸ่พปะ—?ๆท†??๏พ†+Z???U๏ฝตๆฎŠ๏พ–๏พš๏พš?๏ฝถ[7{ka๏พŒT?\"?}3ๆ–ฝ?๏ฝฑ๏พŠ?Q.๏พŒ?f-้œ€?+?๏ฝก1gๆญข๏ฝต้œธ0d?#?ั??*U?๏ฝด้ฉš? P%?๏พ›?:?๏ฝป;s%๏ฝผ1T้Š“5๏ฝฑ?/ๆœŸ\'JF๏พ“h\Zd้‡ฃlF๏ฝธไบŒ0? ้›‘๏พš๏ฝต่—ค๏ฝด?,\Z&$?\0v9?\r??\n2@}๏ฝช๏ฝฏ\Zๆญธtl>๏ฝจ?๏ฝซ??ๅ‹ต๏พ•๏พ็‹’ๅŠ?$ๆถ›?P๏พšRO๏ฝฅ? Z?,2๏พ‹ ?.#,?๏ฝฉR\n๏ฝถA็‡ผO๏ฝญS๏พ†s๏พ…sGup?#๏พ–๏ฝดX็ฌŠ$W๏ฝทdๅฒฌ๏พ๏พ๏ฝช5๏พŒ๏ฝฌbfiZ\\,Y$?=๏ฝฑ?๏ฝฏ๏ฝท\Z?+่‚…๏ฝฎ8๏พšcโˆ ๏ฝญp?>??๏พƒ้†ธไธธ๏ฝฌ๏ฝดi๏ฝต96๏ฝท?๏ฝฒ๏ฝถm๏พ„?\n ๅ”; ๏พ•.K9็‹กZ7l?6๏พœ;g๏ฝฟ๏ฝฝUF4๏พ•๏พ—๏พ‰๏พ—d๏ฝต๏ฝฏS? q๏พ‹u็ฐ“%๏ฝฎpO~k&๏พ‹๏ฝจ๏ฝค่‹ฅK๏พ›๏พ‡็  ๏พๆชŽC_4๏ฝฝ?V๏ฝผๅกฐ๏พžๅฅH??\n?$๏ฝด)\"๏ฝฒ็‡??Vb๏ฝค๏ฝค๏พš7้…–n๏ฝจๆฆ‘๏พ‡?ๅฃฐ[? n๏พ†๏พŒ?_๏พŸ?Ol๏พ–๏พˆ้ญ„๏ฝก๏ฝน๏ฝป๏ฝพ?$๏ฝทV%1็ญงๅฎ›?%r\0๏พœ็ฝ…r+๏พ\rๆจ›๏พWy?่‘ท62๏ฝค( \'o~\0๏พ‰?๏ฝฆ๏ฝด ]?ๆ ผ????&๏พ’๏พœ่˜—๏พ˜?>?y^?JZ?ๅซป๏ฝฆ?๏พ”๏พ–ๅฃ…Q,3hS[]@โ–ผ0๏พˆ|้ท™w๏ฝฑ็ณป?;๏ฝท๏ฝตP๏ฝฏ4m?Lkv๏ฝธ๏พ”?.??{vb?y๏พš๏พ„? ?=่…”่ฟ‘?jw๏ฝญu.?\r๏พŒ็”ฐj<๏ฝกv๏พŸ๏พ†ๅ†’?m9_๏พŽ๏ฝฐ5๏พž่›พH5๏ฝปi็ดฟ.็ซ“Pๅฌฌ@ๅ„•ws๏ฝด?>??๏พ™๏ฝฃ?้˜ปf?๏ฝฃ๏พ’็Š–Y-.๏พšB่ ‘๏ฝปH(=๏พs??๏ฝฃ๏พœj๏พ—f็ฒg๏ฝณ๏ฝฒๆ–K๏ฝท$ๆญธ๏พ?W๏ฝฅ๏ฝบ็އ?๏พ‰็“ฉ๏ฝง๏พ™๏พ€?)n๏พ‘๏พ†;ๆ…พ๏ผดๆ€™\rT?GL๏ฝฒ๏ฝด๏ฝฒ๏ฝท๏พ‘?I?x๏พ™๏ฝธ๏พ‹๏พ‡7๏ฝผ?\0z๏ฝป?่บC๏ฝคk;n่”ฆl?๏ฝซ๏ฝป๏ฝต๏ฝน?8๏พ“}๏ฝผ2I?่€ป?๏พˆ๏ฝก๏ฝญ?ๅธt?๏ฝญ๏ฝบC๏ฝซ๏ฝบVU๏พ๏พ๏ฝฟ?c?๏ฝฅt|้กง๏ฝฆ?&๏พ–็ŠฌH็ท’$(๏ฝฉ$?็พˆ๏พ‡\'=?n?๏ฝด6็‚ฌq๏พๅ •๏ฝจ\0g๏ฝตp?E๏พ”๏พŠ??๏พžๅ†–??๏พ?pB๏พ€;r==?s๏ฝณ๏พ?e๏ฝถ๏พ‰๏ฝถi?2M!!I\'?}\'?k๏ฝฃ๏ฝฏ๏ฝจ^็ตฒ๏ฝป?.cY๏ฝขrA>?L? ๏พ\r๏พŒS๏พ!๏พ*๏ฝฌQ๏ฝท?๏ฝง๏ฝฎ2I?&๏ฝน?&๏ฝข?a๏ฝค้ญŽ๏ฝน๏ฝญE&่™œ๏พ‡)็“Š๏พใƒฃ๏พ†}้„‚tiๅฃž๏พ๏พ“?;E๏ฝนๅปก|K???๏ฝช{g?W-N?R๏พ’n6๏พ›๏พ-???%? w่„ฃTe๏พ†ๅฒŒ๏พ™i\n๏ฝฆA็ญฐ;ไบ•8๏พ‡$?<O๏ฝฝB็ ๏ฝต{+่Šsr็ฒฝ2Zg๏พ›\"็‘ฏ?NGq??oRj๏พ–้€พ่››bHH??9;?8่ข๏พ–a๏ฝฝ?๏ฝก?+w?6\\??\0่ฟบ๏ฝน??๏ฝฝYL๏ฝท!๏ฝง๏ฝธm๏ฝฌ๏ฝฃzๆŠA8่ƒ„๏ฝต๏ฝชTCgM๏ฝฟ๏พŠM{5๏พœ๏พ‘ๆค‹็งป๏พœd้ฏจ๏ฝน่ฑR5่€—๏ฝฆh๏ฝถ๏พŠ?7?\0S?L\0+่“h U????\0๏ฝฝu๏พž๏พŽ็ฒขD_๏พ„๏พ๏พ†?;g๏พ”็ฎYz่‚ฑ๏ผฅ๏พ‰BH???๏ฝฅ็”จๅ’ ๏ฝธ?๏ฝญv้ฏก? ??๏ฝธ?Dๅปท๏ฝฑ๏พšะฏ๏ฝถ3?๏ฝน[:/\',๏พ๏ฝซE> ๏พˆ Wl๏ฝญ?t<ๆƒท๏พ้ค˜๏พ›d๏พ…Q%๏พ๏ฝฝ3u๏พ—?4N่ข–i?๏ฝดโˆฝ?7ไธช๏พŽd?๏พ˜โ—‹?T๏ฝซ๏พ…_๏ฝฐB๏ฝถ๏ฝฅ๏พ•๏ฝบ๏ฝง๏พ„;้˜๏ฝญ๏ฝด๏ฝดko?\0่‹‘Aๆผ•b;y\"n;W๏ฝตk?3๏ฝนW๏พ๏ฝผz๏ฝฅ+\"๏พ‚ๆซจ\0๏ฝฅ)@)JP\nR?ๆซจ??\0๏พ›่ก?\0z|,๏ฝต?h็ชƒt๏พ็ฐ—๏พŽY?๏ฝด๏พ„G\"๏ฝช? ๏พŸ็‰พ-๏พ™cl๏พˆ>v้—•E?\r?๏พˆt? ??G8???(๏ฝง??4?)๏ฝซ๏ฝฃ๏ฝจ*๏พŠF ?๏ฝฟ95M?๏ฝท๏พ„ๆ‹˜๏ฝฃ๏ฝฎ๏ฝฏ๏ฝฃ๏ฝบ๏ฝบ๏พ‘?๏พƒ?5๏พš%ๅ›ฝdๅทฆ?็›ƒ%rpr2qๅฅš>่‘ฃๆฒ6s่ฟฏ๏ฝซ3?2Y?)??๏พž+?๏ฝงๆ˜\\Gn๏พ‚I\0&5#?#๏พš๏ฝญ๏พ—6๏ฝฝAh๏ฝบ๏ฝพๆง“?.W?ๅŒป%~่€จ๏พœ๏ฝฅS$i ๏ฝบI@้ปฅ๏พž??\0ๅผ๏ฝจๅˆธ๏พ–๏ฝป8๏ฝชๆ™’V??%@*๏พ‡๏พ็ซฟใ‚ท๏พ–,,๏ฝฎ ๏ฝถ๏ฝป?.?8 q?๏พ•็คŽ๏ฝขI๏พ\',๏พ๏พƒc9;ๅด›?Z่—บ๏ฝช|ๆ••3[๏ฝฌ่ฌ€๏ฝช๏พัˆ%y?w?e?q??G๏พ˜Bl\Z?d?mโ€ฅ?็ˆR9aโ€ฒๆ–ฝf??!๏พ–๏พ—I=ๆดžS#D๏ฝณx%?89\'ๆฑ~่ˆž๏ฝช๏พ˜C&๏ฝฉ$๏พš H๏พ–๏พ€็ชฏ๏พš๏พ‘?2J?๏ฝฎ5;๏พ่ด“6H-I๏ฝธx ๏ฝฒ60๏ฝค1๏พ€้†ช๏พ–t่ถ…J?๏ฝญO?๏ฝดZ|?๏ฝค?4?\\?3 8 ?\'ๅฅจ๏ฝป๏พ”e๏พƒ๏พ…s??%!Gwa?=?8โ™€๏พ‚๏พ•dvuq๏ฝป\0\07่‚“\\๏ฝด่›ฏ็คซ{๏ฝฃ m$g8๏พ‡pH๏พ†i๏พ‚?6tj๏ฝผ่ฉฉp็ฆฟ๏พ›๏พŠ้‡›T๏ฝทH?๏พ–?7?\0-?--๏ฝฅugI:HW๏ฝฑ ?>๏ฝน?^x็ช–่ตฐd? ๏พ‡่ฟฅๅฃฐ๏ฝต้ค…๏ฝก๏ฝต๏ฝด๏ฝธๆŒบ๏พŒw๏พ… ็ทฌ๏พŽ๏พŸr๏ฝฅVQMS%3c๏ฝญ็™‚{๏ฝฝ๏พ›๏พ†๏พ•่€จ5]้‹ฉ๏พ–๏พ–?-๏ฝณๆˆไปฃ_๏พ‚?Rq๏พ†;๏พ•?็‹ฝ-<๏พœ้ฉ€Ch4ๅŠo7;๏พ—$่ƒž?\0๏ฝฒv๏พ†?่พฎ+DOc๏ฝจ?\Z}็’ฝy๏ฝง?\0?[๏ฝณ๏ฝกa?vy?ๅขซ๏พ’?W๏พ“๏พ๏ฝด๏ฝผh๏พŒ[็ซฆF?#,=?8๏พ๏พŸ?rx๏ฝค๏พ”ๆ–ค}\Zๅฑฎ๏ฝบ]?>ไบซ?i๏พ›๏พ€?๏พ—q?\Z2๏ฝนr?๏พ๏พq้Œปj?]8t๏พ‹?๏พž1๏พ‹qz๏พ–?E/่‹…? c๏ฝธP8>ไฝปl?๏ฝฑ?O๏ฝง๏ฝตy?7_๏พŸ-๏พ”๏ฝญn?8b๏พœ}๏พˆ?3ๆˆŒ\n๏ฝฐ?A้ฎƒ๏ฝบ๏ฝท}๏พŒ;??๏พŽ9๏พC๏พ›๏พ˜^๏พž\\๏ฝด๏ฝถ๏ฝถ๏ฝฃ??lv\\?่ฒฎ๏ฝถOaWH?!<6}่‹บ? ๏ฝป?๏ฝท?A]*]Q๏ฝค\0??f๏ฝฎ:VใƒŠ๏ฝค๏พq\'X๏พš]G[q2๏พ„eB๏ฝป?ไฝ†^๏พŸ๏ฝจ??,๏ฝฝ&๏ฝบ??75?ๅฐค4ๅทŒ่šŒ?\'?๏พƒ?8?Zๅณญ๏ฝข๏พ.+?d๏พ“๏พƒ๏พ;0V? K๏ฝฟ๏ฝจ8?๏พ•?ๆบฒโ€๏ฝฉ&่ฌ๏ฝฆ๏ฝดD4๏พ’๏พŽ๏ฝฎ??Y๏ฝธz๏ฝฝY๏ฝพ |H๏ฝด?\Z๏พšo L็™˜y๏ฝฑ#๏ฝถ๏พ–*3๏ฝท๏พ”?ๅฐ‘G????๏ฝฟ๏ฝธ๏ฝป๏ฝฝ๏พ•๏ฝฎ?ๅŽ–G็›ป,v?}0?=๏พŽ=?\'๏พ๏พŽ๏ฝซDๅ›ณ;m๏ฝฉO๏ฝญ๏พ๏ฝง[ใ€ˆv๏ฝคG๏ฝบi๏พ”???\0๏ฝถ๏พ€9่€™TwRi๏พ‘A๏ฝจ๏พœKm~๏ฝบ?) G๏ฝปo\"L?l\r่จŒ?j๏ฝผ๏ฝฒ๏พœ ๏ฝผ?NC3V้ฎ—ๅ–ฌ???N้ง‘Rg๏ฝบ๏ฝต๏พ“๏พ€?Z5่‹œ๏พ›9่””=๏ฝณ๏พ…]๏พ…๏ฝงb๏พŠ๏พƒ๏พš๏พ๏ฝฌ๏พ‹๏ฝฑ2?\\??t?>5็ฐ€q\Z?vTppO}G้คฎ7้ฌฒ?kๅŸŸ๏ฝธA๏ฝถ๏พ…i๏ฝฑ๏ฝค v็ดฌ?ไฝ}s๏พFG๏พ’ๅค›๏พ˜=?l๏ฝฑ๏ฝทcๅฐ‹๏ฝธ?J๏ฝซr๏พƒ๏พ“ๅพŒไธ”I่–ฆF้บฅ>??d๏ฝณM๏ฝฃ๏ฝฅ?๏พ—๏ฝท?๏ฝบ$๏พ“๏ฝฃf-o\"4Hb|๏ฝค๏ฝจ๏พ?๏ฝกl!? ๏ฝพ๏ฝดๆฝ…ๆ‡ฃi< \\?.|๏ฝธ๏พ‰๏พ๏พ‡๏ฝจ๏ฝจๆ ก๏พ—B๏ฝท๏พ“็ฌž๏พ‚?่ทซ๏พ˜\"??\n?|๏พ‡w่…ฎ๏พ–๏ฝฎ?gc๏ฝค๏พ‹mrๅฆจ?\"?b๏พ\nI\Z็ฆŠๅคง3?๏ฝปV| ?F่ชๆŸง่งœ๏พŒ{๏ฝณ่Š๏ฝณ๏พ๏พ†๏ผ\"๏ฝซv? ๏พ‹๏ฝพ๏ฝฎ๏ฝท๏ฝฃ(2g*H#p๏พ?;?๏พ๏พŸ๏ฝผ@ัˆ \0a๏ฝฐ๏พ˜?~?U๏ฝณ+Y๏ฝปๆ› d? Kt๏พ๏พใ€•้ฃด#๏ฝท=๏ฝพ๏ฝต)๏พ’zu่ฃ”?็–ฅo6๏พ’G?0้€ฎ๏ฝธ ๏พs๏พ†Nq๏พ›??5๏พ™?,๏ฝฎl??]?qm\0๏ฝฆ0??s?=๏ฝซ๏ฝก5?๏พŽ๏พ?[๏พ™๏ฝข๏ฝทy่ฆ‹?;?#?9\Z๏ฝฟ๏พ›tg๏พŽ๏พ้จทo๏ฝฉ>%ul๏ฝฐ\\?Iๅพ‡Y--็งฃ??\0zs๏พR๏ฝพ!t9?\rJ?K?๏ฝฉ\"![*c<ๅฝญd?๏ฝฆ}??s๏พ–-3๏พŸ้–Š^ไบถ?? uJD\n\0๏ฝฏ๏ฝธ??;่“ดQu๏พˆu)^}B???yๅ“ฎ?๏ฝชๅ›ฝ๏พ™๏พ?01\\?ๅŠน๏พž?Ou๏ฝฒ๏ฝนc๏ฝฅ๏พž้ท? ๏พ˜D๏ฝกdไน๏พ’}>๏ฝผq^ๆปฒa๏พ‘? ๏ฝค๏พ€๏ฝฒ?3?v?Vๅ‚ณ็ถ™้ฉš?่’ฟzWๅ‡๏พ•๏ฝฎ !๏ฝช*gn\0c๏พ๏พ—๏พ?^I๏ฝฆj)๏ฝจ|๏พ๏พŸ?&! ่ก€๏พ‡๏ฝท,9๏ฝฉ่‰€?\0ul๏พ™R=๏ฝบ?Mๆคจm?1๏พ…9๏ฝถๆณๆญŒ?็“ฃ??๏พ?^u?i๏พš๏ฝฎ๏ฝง-?]j!๏พ˜,hj?9f๏พŸ\'ๅขซ\Z๏ฝฏUj็•ฅ่ฟฐ\\m๏พ‰?๏ฝพ่ต?๏พJ?J้พœU๏ฝงN?๏ฝดq?่จŒ\02HR=?่—นๆฒผ็ญบ่–€๏ฝน7๏พ‘-๏พ–]K๏ฝจa?ma3rU?;๏ฝท?>??*?ๆดถ๏ฝฟ๏พ’ๅชš๏พ•๏ฝฎ?๏ฝทlE\'9l๏ฝท??๏พ‹J้ˆฉ?๏พ•i๏ฝฎ?2[ZFr๏พ›?\0๏พ–๏ฝฅtK{?้€ƒ๏พœM?๏ฝฃ\n๏ฝฏ?pA?=s?๏ฝฏG๏พ›o~๏พ™Dๆตนm??๏พ?๏พ›?623๏ฝฃ?6?๏พ™ ๏พš๏ฝต๏พYZ๏พ„๏พš๏ฝฅ๏ฝช๏พƒ๏ฝบW็ฑณ?\0r@?๏พ‘๏พ›๏ฝญ๏ฝฑ๏ฝฉMa๏ฝข?่–ฎ&?\ZK/\r?!%๏ฝถ๏ฝฎ๏พ—$่Š๏ฝต\r๏ฝฆๅ†ซq๏พ”Zmใ’็‹—T(r๏พ‘ใฝF~๏ฝปrk๏พ‡็‡ƒtY๏ฝฅ๏พ‘j้ฅ‹ๆ‚ณ๏พ‹๏ฝป{ๆ†”๏พonAiU6่ณƒ?ๆณ™?R~ๅˆฅ?๏ฝด๏ฝบ๏พ”\'๏ฝณ๏ฝบ๏พ’๏ฝฅin็ชƒ*๏ฝ„?๏พv่ฎ’๏ฝบๅฆพ-4๏พ‹_่พบ๏พƒ้คŒP$fV}?๏พc?-3B๏ฝธ\n?๏ฝฐ4๏พ‡x,๏ฝธbf?F*๏พ‹ZE๏ฝชๆ‚ฆ๏ฝฌ๏ฝฎ,็จพ=-๏ฝคๅ’ผR? ๏พ‡}๏พ„p?g๏ฝท&๏ฝน๏พ…๏ฝก|๏ฝฌH\'ๆœง?cๅฒธNๅทฝ\\?\0๏พ”๏พ†ๆ ด๏พšH2๏พŠ?%๏พƒ?,O??\0๏ฝฝBu=?๏พ‘้‰พ๏พ„๏ฝช?H๏ฝข<\0;~๏ฝฟJ๏พ•EV๏ฝบ๏พš?๏พ“n๏พๆ”ชyc๏พ† #p๏ฝคpy??็ญฌi๏พ‘H๏พž,0็š†๏พ‡??๏พƒ๏พŽN?=??*๏พ—o๏ฝฃOqt๏พ’]๏ฝช็ตŽ?1ๅ†?n๏พŸ๏พž๏ฝณๅฎนf๏พŠ-?ๆผ•%?7๏ฝฟ๏พ›ๆญ“YZ๏ฝฒ?๏ฝธ?6ๆณ•BๆˆŒy?\0ๅšŠ๏ฝฟ?-่ทจ2? ๏ฝถPw\'?\n๏พ˜๏ฝบๆผซ v๏ฝกLjN08,s?=+Yu๏ฝช?7?y?qๆŸ”Z๏ฝฒTCD ๏พ’<๏พŽ7๏ฝจ?V?S)\Z?*๏ฝธ8??;่‚ช๏พ˜?$็”ท[:&8๏ฝจ?F]??gJ๏พƒvX?95๏ฝต?c๏ฝพ?๏ฝถ?i๏ฝช\\di๏พ:SRๆ€Žใต+?\0?7B#a?*๏ฝฅf๏พ‰๏พ–?๏พ๏พ‡็‡๏พ‚?๏ฝค๏ฝค๏ฝปK๏พ‹ๆฑฝw๏ฝน?\n??๏ฝท?๏พŠ m๏ฝฒ\0$M]๏ฝฉJ็ช–5๏ฝฅ()JJR?R็ฎฑ๏ฝฅ()J^c?๏ฝบ?%๏ฝฆ๏พ‘?่ถŠzI+c๏ฝฉs?๏ฝค??,ๆทก+?O่–ฏ@J?u^[[^๏พ™๏พgyo๏พ๏ฝด?SC*I?YOH ?็บ›?้‡Œ\Z๏ฝตG?u(?๏ฝตyHF;?=?G??j[๏ฝซ4+S1?Eๆทกw1๏ฝฃ0๏พ†็ฌ„?q?{๏พ–๏ฝธ๏พ—4-C็‡๏พ„}S๏ฝฃ๏ฝฏ๏ฝฎV0wF๏พ™=๏พ‡๏พŸๆดฝ๏ฝฌ;๏พ„๏ฝถๆทž๏ฝผ่ฟฆ?๏พžๆณ•fR{T็‘œ?-gEๅฝœ้ถซ?\'?7๏ฝข็”ฃ๏ฝพ๏พ€s๏พ‡๏พ’๏ฝข๏ฝคC ?๏ฝถ๏พŸ?\0?๏ฝด่น™๏พ—a๏พ”t๏ฝข?I๏ฝบ)e?๏ฝทT๏พ—VEa๏พ•ไธน๏ฝฎ?3๏ฝง๏พ่€ฝ??I#\\p้ณง็‡ผ?fๅธซ?๏ฝข\n๏พƒC๏ฝณ๏ฝฝ๏พ?\0x$๏ฝท2๏พ๏พ’?ๆญด??๏ฝถN?F๏พ?็ฏ๏ฝด๏พ#T๏พ“5K-wOqp๏ฝนๆœฌk? u>~๏พ๏พˆ?โ˜…?๏ฝงd&๏ฝฒ๏พŸ42?2๏พ›r3?้‘š้‘ gI?+?3J:m๏ฝผ๏ฝณ[H&๏พƒ๏ฝจa??๏พ—ไพƒ?/[%?jW๏ฝถ๏ฝฒLnm๏ฝขๅถ‹๏พ•๏พŽ๏พ…??๏พ”T๏ฝฎโ–ฒ๏พ€๏พSqk?%ยขO?? 7๏ฝง<X1๏พœ๏พ๏พŽๅกฒ?๏ฝผ๏พŒD๏พ’๏ฝฏH๏ฝฃv๏พ‘๏พ†pq??;\r็Ž„xG่ณŠ๏ฝฏl๏ฝฎ0๏ฝท่ƒŽ?g๏พƒ๏ฝก*7โ€ฒn่‰˜?๏ฝฌ๏ฝง๏ฝฅH๏ฝฒ$t W๏ฝด๏ฝฟ$๏พž๏พ‡go(้พ[8?๏ฝฑๆฟบ?้‚ฑ/๏พ”n?[่ˆ˜0/๏ฝด9Q๏พŽ๏พ™ๆ–ˆRn?8??\0๏ฝฟZ๏พ”๏พšๆš„?? \ZY๏พž? )\\1\n2I?\'>๏พ•d?-Q,๏ฝข??.4๏พ“๏พŒ7$่‰ฒrv?y๏พไบค?,ๅฌ๏พ•K๏ฝฅpz?9?ๅ‹พc๏ฝทๅทฝๆน›ใƒ‘$l็‰พ็€‹๏พ“๏ฝตl?\0?=Wk?Diๅ–™]่ƒธ|\Z?๏ฝต?SQ๏พ–่ขด๏พž๏พ9,๏พ’ๆ˜ bLโ”ณb๏พ„1ๆ†ซ+๏พ๏ฝณ่นˆ&?4?๏ฝก๏พ–.๏ฝกๆ’ค???!๏ผฒ\"๏ฝฌg?6?9?๏ฝตS๏ฝพ|/๏ฝฟ??-?๏ฝฃE,{D@]L๏พ๏พœ๏ฝน็™ช?่จˆ๏ฝญฯ‡1๏พˆ๏ฝท77zะฅw๏ฝฉc%๏ฝฟ๏พ๏พ†0&P๏พŸ๏พƒDE๏พ\0.?็ธฒ2\rk่†ŠI}๏ฝธ2\"๏ฝฝ๏ฝฒ๏พ๏พ—ๅ—ค๏พƒ๏ฝฟ?K๏ฝฆ๏พq่ฒD?๏พ‡4๏พ„d่ข—*v๏ฝฑ ๏ฝญๅ˜ฑ๏พ•+๏ฝญ?๏พ‹๏ฝง?๏ฝผ?:๏ฝญ๏พ?๏ฝนv|F๏พ„๏พ‰๏ฝฟw๏ฝง\0๏ฝฐ็’ข่†ณ=๏ฝฎ๏ฝบ\'???iksV๏พ‹ๅบ |๏พŠ๏พ93?๏ฝซ7\0 ๏ฝฏaๆธซ9?<๏พq๏ฝจ\\-๏ฝฒ๏พmeJ??ๅธญ็—ž๏ฝกP/๏พ•้šด?๏ฝด้งฎๅ›๏ฝบ๏ฝพ๏พ“๏ฝญ??๏พ…n๏พ|๏พ˜๏พš๏ฝค?-F|?tJFO๏พƒ๏ฝญ?M๏ฝพ๏พ”5?๏พ-7Q๏ฝฑC๏ฝบ)%?๏ฝธW?.๏ฝฃ?m?ใƒก] :B?-b?๏ฝณ๏พ”๏ฝพf๏พ’ \\๏ฝธๅทฅx$$\r๏ฝฌ๏ฝฏๆผ•PHa้ณง\rJ??๏ฝฝ๏ฝฝๆƒ…๏ฝทE๏ฝถ่‘‰ๆฑๆ•…\\?8n;??*้†บ๏พ‘้ซซ๏ฝต๏พ”๏ฝบu็ž ???L@?@็€˜๏พ๏ฝฟ?l่ทŒ๏ฝธ๏ฝพ๏พ‹๏ฝฃ๏พ?\0๏ฝญ?3Q๏ฝฟๅพน?$็ทฉ$?;i๏พ—~่ณฝcP๏ฝง$ๆฑ ๏พ€g็—ด๏พ๏ฝข?๏ฝงๆŸณ/?f๏พ??=1?๏ฝป็ฌ‘๏ฝฝMu๏พ“p[\rn๏พŒ?\Z]?!๏พž=๏ฝข๏ฝฃ๏พƒ.๏พœ่˜ฟ?? ?๏พ”ๅ›‚๏พ‚-b๏ฝก๏ฝจ๏พ๏พš๏พ…ev[dovRhๆ†?S๏ฝฝy?8?f้ท?*?]F hu a๏ฝทw(?\\\0r;?๏พ’;9?=?0>๏ฝค\n๏พœR|็šท๏ฝฎ็พน๏พ‘o?R๏พ˜๏ฝพ?la็…ค๏พƒnR;{๏พŸ๏ฝธ๏ฝซ??๏ฝซ]?#R้ถคn๏พ›Gxd๏พšl๏ฝฐ $8#WๅพŒๆ‚„๏พŒ๏พ–๏พ๏พˆ๏พ†ๅฎนx๏ฝณFYt?ym$๏ฝถze๏พ„??๏ฝป๏พ„๏ฝป?๏พŽI?๏ฝฉ\rK?:๏ฝงM้ฌฎ>๏ฝฅ๏พ”t?ๅ‡…W๏พ่ฒฉ๏ฝฌ๏พŒ ???๏ฝข๏ฝฝA๏พ’:oK|+ฮถๅฐบ๏พŸY4krY๏ฝคw,x^๏พ‘็ข็พˆ5A?\rC๏พ”e๏ฝตใ‚‰M๏ฝน้ต†;๏ฝซ?\"๏ฝญ๏พœ๏ฝฅ็ค‘p 0A๏พ€\0p#็“ฆ?๏ฝฅ๏ฝฅ??ๅ‰‡t๏ฝธnnoE๏ฝฎๅ†ถ?9Pp[๏พœ}~๏ฝพ?๏ฝซ[๏พk๏ฝฉ๏พœY๏พ2๏พœ๏ฝผR?๏พ›็™–8๏พŠๆซบ^ๅฎ?ๆ ฉ~่งœ๏พš๏ฝฆๅผพ !?5YU๏ฝณ?s๏พ›ๆซŸ๏พ†??\'๏ฝญ?.๏ฝฅgsj่–ฌv^RX๏ฝขO ้/๏ฝจ<็ญตy0?8?K๏พ๏ฝฎ?=K?,็บŽi๏ฝถ็ซฅ8๏พ‹1๏พ‡๏ฝฆ??Mt๏ฝฉs๏ฝฎ๏พ›้งข๏พ“?๏พˆ?๏พ‡๏ฝตd๏พ™?\0??ๆฅซ๏ฝผ?4m็˜ข๏พ๏พ‡Rt?๏ฝข??็ฑ€๏ฝคๅผต๏ฝพ้…ณ๏พ˜๏ฝชib๏พ…I๏พ‰็€?๏ฝฉ}7SCuw5๏ฝฑ๏ฝฐไธฑ็ฒ—_9|;๏ฝฌ1?ๅพƒ j๏พŽ^K}tMz๏พ–:l๏พžj๏ฝฒ๏พ›๏พš๏พ›๏พ›X^๏พ„?ๅทดGi]x 1็‡—๏ผฒๅฝ–U๏ฝณ๏ฝฃ5k=๏พ…? Q?๏ฝดq้นธ๏ฝถpT?S]s๏พ”ๅœœ๏ฝถ๏พ—?็ฒ—o๏ฝคA๏ฝฅ?Mf\0\0?8็†ฌ[h่‹™}๏พŽEOH๏พ‘$๏พ?๏ฝฝ๏ฝป๏ฝทๆฟƒ๏ฝฎe๏พ‹(\' ?3่ฑš~u{rไธˆF๏ฝฏF๏พ…?+ๆฎ๏ฝปNYไพฏF\n?<G๏ฝก๏พ†2}j+G๏พ“?{๏ฝง่ซฆ๏พ–y๏พ…๏ฝฑ!๏พ•๏พŽ\ZQ้ข่€จ?>๏พ‹?๏พ—๏พš๏พžๆŠ‘๏ฝฅKi-๏พš๏พไธฒ้šนW๏พ—ๅ‘‘\'?=???=ๆ“˜๏ฝฝ#ou,?$Fr๏ฝฎ๏ฝซ?8<\"9?#๏พ—5ใƒ\"๏พœ?Si๏ฝบ???_]๏ฝด๏พ€\\๏ฝฒFLๆš–9b[\0r??๏ฝฆ๏พŸ๏พkz๏พ‹๏ฝคq๏พ‰o$่ฉฎ๏ฝฎ02๏ฝฃh?\0J?๏พ—Z]๏พŽ๏ฝญqsyk*๏พƒmm๏พg ๏พŽQ ?๏พ†๏พž๏พ˜๏พ‡๏ฝฉ็พžei๏พ–;c๏พ‘๏พŽb๏ฝฐๅซ\"๏ฝจ????๏พ‰๏พ‰&๏ฝผๅฉฟI๏พ‹่‹ป๏ฝชEsN๏ฝทe??eS,ไฟŠ]]NC๏ฝฎNs่‹”ๆธฃf๏ฝฌ๏พš็ดข?๏ฝฆo?- ?#๏พ\03?o?็š€๏พ™่’œ้ป™๏พˆYp๏พŽ27??๏พJ:^๏พs2๏พ‰+๏พ…่ŠŸๆ‡ฆ=?๏ฝธ๏ฝซF$๏ฝข>้บ‘?็ฑ๏ฝผ5ๅต?/\'v0=๏ฝฟ๏พ›?\rOไผŽ๏พ‰SQๆก‘8em็ฝซ๏ฝป=*ไพฎ๏พ™?0่…บ?>A?=๏ฝฒ+๏ฝฎ?/)|๏พšv?f๏ฝตHvF?่ฒซ/๏พ‹\"๏ฝขE*๏ผ•?๏พ”?Cโ—†z๏พƒ?dๅ–ซ?๏ฝพU<\0?z๏ฝฝH๏พ–&๏พ?;็ญ๏ฝณ??\"Z๏พ›๏พŒ?6}]?๏ฝท๏พ’๏ฝฎA๏พƒR๏พ”-๏พŽ?6๏ฝขnn0\0๏ฝญ9๏พ”๏ฝบ็ฒง้ฝ ]ฮต6๏พ”A?ๆŒ‚๏พ”q๏พŸgd๏พŒ๏พ‘???g๏พ›?๏พ†๏พ‰bM\nIๆ‹ตk??๏ฝฏ๏ฝฎ}๏ฝซ๏ฝฆg?๏ฝฐ๏ฝข้ก?3๏พ‹r~๏พ•?5?1?7ๅธ‹็ŒŸ๏พ›mQ ??๏ฝฝ๏พ”๏ฝถ8uYX\0้šช๏ฝจ27 ็ธ??c๏ฝพ??ๅ…ฌๅŸ”๏พ‘ๆธค]8้ฌจ\\๏พ‰ๅฝทI๏ฝท@}๏พ‹๏ฝฎ?๏พ†๏พŸJ? ๏ฝฎl๏พ’?\0 ๏ฝผP๏ฝฅ)X๏ฝฅ()JJR?R็ฎฑ๏ฝฅ()JJR???\0?๏พrk?Y้ฌฉ+้ปจ4ZG?(?๏ฝญ\\๏ฝจ?8?>s?๏ฝขN9๏พˆ?C?่Ž่Ÿ†@๏พs?๏ฝข??\0๏พš็—บ|&??XoI?^๏พ’GKI๏พ‰b๏พ–๏ฝฅ๏ฝณๅ‡7!l๏ฝนbๅญค๏พ–?ๆ‹้…Š]3 ?h๏ฝฟ[XYuOJ๏พ‰w\nๅ‚ท๏ฝถ??1๏ฝป๏พˆy$qๅพŒ?๏ฝญM๏ฝซi่ฆ๏พ’๏พ†?๏พ™h๏ฝคS่ˆŒ๏ฝพ?#?๏พ‡็•งR??๏พƒ? vๅค˜ๅฐพqW๏ฝฎ๏ฝง๏พ‘,L7๏พ–๏ฝฒ๏ฝน\Z=?่žซ๏ฝฉ?\0้ คT>?$z่‘ซ๏ฝฟ?๏ฝซ๏พ“9Z่‹ก?๏พœVv๏ฝป??้ƒข!๏ฝง]๏พ‰๏ฝฃi?1\'?3?FA๏ฝพ7??๏พŸ?:ๆŒqd?3)็›ก๏พƒ่ฎ็ทฉEG?Z?๏พ’็ซ’?1eki-๏พ?7๏ฝถ่ผOc!^๏พƒ๏พ“๏พ›? \r๏พ‡??\'?9๏ฝฒT?7้…ฃๆฑ•?8๏พ–๏ฝด๏พ˜4๏พ™ๆ ฝ?๏ฝญ๏พ๏พ‹)๏พ›็ซญๆงฝ\\๏พ‚F0O๏ฝซK?^uRjWZๆฒป๏ฝฉH?ๆˆฟx๏พŠ็ ‚๏ฝชๆญŸ;้ฃฎ?๏ฝฝK๏พ‰?4\rๆฒ™ ๏ฝซ๏พ๏พ†Qๆฝ…(sๅ็ญด?$?-Zu่ก‚Uj(๏ฝบ๏ฝต?๏ฝผH7๏ฝท-\'?cO้™ฌ่‡ญ??EๆถŒ#๏พi?้ปI๏ฝป9๏พƒ1H>Xq๏ฝปi๏พ†y?3๏ฝฃ๏ฝบ;R๏ฝน:ใ‚ข๏ฝบ๏พž?ๆฑš1F?๏พœ$\r๏พ›8่ก†^?๏พ•m๏ฝฏ๏ฝฎa๏ฝด๏ฝณ๏พ–?ZmB 5๏พœn#+?๏ฝฐW\'่ฃ9็‡ป๏พ˜<่ฑ•๏พˆ็ญตH๏ฝฒ5u๏ฝถ?$้ตˆV๏ฝถ1๏ฝคB็€@๏พ’8ๅ็นฝ๏ฝพk็ณธ๏ฝงj_๏ฝฝog๏พ็™‡?๏พ†p๏พ‚$eS?Xๅคง\'?\rm๏ฝพ?i๏ฝฉk๏ฝฐDo?*๏พŽโ”=๏พ…๏พ‰?ๆฑ ๏พŠ?* ?0=j๏พ›g๏พ“ ๏พ‘b?็ฝฐ?Rๆœฑ#v?\Z6่‚ฉ๏พ„๏พ€ w?f๏ฝณๅต๏ฝคJF?๏ฝญ็ž ?.๏พ“๏ฝจ.? ๏พ—๏ฝต๏พ™q็Šข๏พƒ\'๏พ‰ๆ‡ฝ้‘ท้ณฐ9๏พ€๏ฝฝ|???:tๅ–ฎ้˜ป7l๏พ€O๏ฝฃ:G?\r๏ฝฅๆ‹ถ%T่ปŸI๏พ†*N.?5{๏ฝซK๏ฝญi็ฒซY๏พ„w?;I]-็–ตC็™ฐpG}๏ฝญๆ‡Š?/J้‘ฟ็ฐพ?๏ฝป\Z๏ฝถ่ˆ‰?๏ฝณ\ZW๏พŽ;d0๏พŸ๏ฝฐ๏ฝจr่™Žh๏พ†?๏ฝฌ?5๏ฝจ?๏พƒ{uk3*N๏พ„๏ฝป๏ฝฃ๏พƒ้ซทx๏ฝญ๏ฝณ?๏ฝชt๏ฝฝS@]2 ?Jmไน—Sv?K้†ชq๏พˆ8<้ก›w?้ค๏พ?^๏พœOC?~ๆ…ง่„ฏ๏พ”6ไธ˜qg๏ฝจ๏พ€E๏พ„?๏ฝธe่„L๏พ”๏พ๏พ‡ๅพ๏ฝก๏พŠๅ‘ท^\r9?9้‡ฃ? ?*[ \0\0่–จ๏พ‹็นง;p1??๏ฝฐkO???!๏ฝฐD่”ตP๏ฝฌ๏ฝฌCd/ 3?3?;๏ฝฅz๏ฝคz็จ€๏ฝถ๏ฝฝn?๏พ•๏ฝง๏ฝณๅผฉ_S?ๆฅ”B.ๆŸ˜B&vC$?(W๏พ‰??O๏ฝญ?ๆฏฌ4็œŸ๏ฝฝ๏พ…๏พ™?5๏พž?ๆชŽ?9<*v๏ฝฎๆชฌ้ฏค๏ฝกๅปดqwp๏ฝพJ๏พƒ|l๏ฝฎ๏พ…?,Xๆ”ถ๏ฝฃ?\'?o๏ฝฒ,๏ฝผ?71G๏ฝง๏พ}y๏ฝฆ\\[๏พƒ็™˜ๅ •?)<+(a?8?๏พ‡aU ๏พŽ๏ฝฐY$้ง•qC็“ฉ๏พˆ^b3?่”ญG๏ฝพ@? z๏พ‡_๏พ•ma๏ฝฐ๏พ•่ฌŒ ๆฑฒ๏พ(?\\?9๏พŽ=๏พ@?่Ÿ„่ฎ–๏ฝทW,V?1@?๏พŠ๏พ™~H?0=๏ฝฑ้ฃฎ๏ฝผqU๏ฝถG#}XkFK+๏พ‚๏พ—็”จ๏พŠa้›จB๏ฝกA92H๏พ>?๏ฝญk?7๏ฝง?5 ๏ฝฝ[]y?cw๏ฝฏะฒg?W?o(๏ฝฐ๏พ๏ฝฝO้ดซ๏ฝณ?๏พ—๏ฝทBk[ๆˆžoS7้…๏ฝฐ w?๏ฝน?r]๏ฝต๏ฝจ่Žž๏พ‘nLๆปฒ?!๏พ๏ฝถ%Pp๏พ™?w๏พ‰่ฎ’๏ฝฆ๏พ’?&๏พ”OuK>7?Iv??๏ฝซ๏พ?&?.)?ใฟ๏ฝฒBHm๏พๆก‘f๏พ ?\0)๏พŽ\0็‘ฐ้ถฒs_m็ฅ [W๏ฝธ๏ฝบ็พŠ3aTq?{้‡ต๏ฝบ-?\0?D๏พŠ!R๏ฝฅ๏ฝถๅ…8??k๏ฝญ.c6๏ฝข๏พžIBpS?๏ฝฐ๏ฝฌ?.\'?4Hๆ—‹ใ˜W๏พ‹ๆฏซ\n?tๅ‡‹๏พˆGoAX๏พ“๏พœ้ฐ’j?2B?.\0๏ฝท๏ฝฐ๏ฝฌkๆ‹‰p\"?่Žข่†“๏พ’fG๏ฝด?K๏พ†8z?M๏พ„9\0๏ฝบ่ณบ\'๏พ–๏ฝฑ/uHX้‚ตxc?\'q.6ใ‚ฑ๏ฝบ๏พ‡Z?๏พ€?#่•—w\0ๅ“‰=? G๏พž๏ฝช๏พ•SN๏ฝท๏พˆ*ๆง็ฉด๏พ•?{๏พ”f?/๏พ็€fp๏พŸ?1_>\"kO๏ฝช\\+๏พ‡$f๏พœ?.๏พ–๏พ‰?๏ฝฉ๏ฝฒg<ๆ‚๏ฝฑ็ญˆuๆˆŒW๏พ‰T,๏พž๏ฝฝ?8่ญฑj้บช]?*๏ฝฝ๏ฝพ๏ฝดGC?+-ou}^๏พ‹E๏พ’ๆฝดๅท’๏พ›โ”จ๏ฝท?I]ใŒ๏ผน$k๏ฝถ?q\n๏พ†}zK??ww๏ฝซ๏พƒ?Vไฝ›knfใ‚ฉใ€Š๏ฝบw*๏พ‘I3๏พ›\0g@9%๏ฝทๅคu\'.*๏พ๏ฝฃ๏พ’>i๏พŸ ?๏พš?้†u(v๏ฝธ๏ฝฝ๏ฝบG๏พŒN๏พ€๏ฝน?*๏ฝจ๏พ‘FrrM๏พž้†—?R็ฎฑ๏ฝฅ()JJR?R็ฎฑ๏ฝฅ()JJR?U7?\'๏พƒ๏พ\'็ชˆC๏พœt๏พŽ๏ฝซ4๏ฝถ๏ฝง๏พ„[?;๏ฝธ?-m:?๏พ‚?aๅƒน?f\0ใƒข.T๏ฝฉN๏ฝถ?๏ฝตf๏ฝบ๏พ‡Ku%?k?Y้ฝฒ|๏ฝฆ่ซ–?UC8 ?85?/??\Z๏ฝพ?\'Oj{.!d-l๏พ??๏ฝซ??R? N๏ฝท้ฃซY.๏ฝบใ‚ฉ?๏ฝธ๏ฝตๆ‹ท{๏ฝป@Y๏ฝถ๏พ†๏ฝฝๆฑบ๏พŒ๏พŒ๏ฝฐfbk๏พ}๏พ•3๏พ€ๅขฎ็ˆ›#?ๆทž๏พŸ??????8ๅชX?\"q๏พ‡?+๏พ‘๏ฝฐI๏ฝฆ|M้œ๏ฝถ?,W๏พ?1I??\0่ ข?iN๏ฝญ้ด‰?*้Œตt๏พƒ+?0๏พ™๏พ88๏พ?2;็ฏ†_?/๏พ†_๏ฝฉ๏พŠ>๏พ‘Y?*่ |๏ฝฌ0x่†ฐ8็ทปe2&๏พ“?,่š‹่ฟท๏พŠ?F๏ฝตs?ๅฌ‰๏ฝธo๏พ็ฒฝ๏พŽ๏พ•๏พ’)v$๏พ„nB๏ฝก?๏พ—p~๏ฝฃ๏พ’๏ฝบๅฟ๏ฝฉ?>k?v?6๏พˆd;?>่‚“\\|U2?FHใƒ๏พš๏ฝง7๏ฝก๏พš?โ”ณ่ฑช)๏พš^9??๏พ‘z๏ฝฌ๏พ–ๅš†๏พœ?*๏ฝฌ๏ฝจ??[๏พƒ๏พˆ ็‡—้ทน๏พŽj%S๏พš๏พ“%h๏ฝฐ๏พ…๏พ•้ต†๏พ„M.้ฆ—Vt& ่Œธ??z๏พŽ๏พ๏ฝต๏พ›๏ฝฝb?6xg็ ”?f๏พ’็Œ–็ Œaๆ’ฅ$๏ฝถ?Olz๏พ•gG๏พ–๏ฝฌzๅฒ‘๏ฝค7๏ฝฎt?2?l๏ฝฏ๏พ† \'๏พ‹?\'\0~F๏ฝปๅ‹ตZk๏พ‰6็”ฐo|?42O!?5๏พˆ๏พ‰+๏ฝป\06=yๆจฉ๏ฝบ้ซ”l๏พ›?๏ฝฏi็ถ‰ๆบทmbๆ‰‹#๏ฝปM{+\0่ผŒ ๏ฝฑ?\0๏พœ76N ??=Q๏ฝช]/O|๏พ”w?jๅ—ท ๏ฝจ$?J?ๆ˜ต๏ฝถq๏ฝท-้ฃŸ?๏ฝฎ๏ฝจ?๏ฝฅ๏ฝณ๏พc๏พ๏ฝต+;็ฏฅ\Z๏พŠ&h}0้ฝŽ ?z๏ฝฎI๏พ–:๏พ„๏พŽ$ๅฃฏ๏พšo E???N๏พ„?k5?6?eๅฐ:๏พ—๏ฝฎ็ฎš๏ฝดๅ—„IV7v๏พ™uk2่‰z {~้Œจ?/ๆ–ผๅ ™YA๏ฝฌ]<๏ฝทๆฉ&๏พ†๏ฝพ\"? ๏ฝธ?๏พ˜?\0๏ฝฝj+[!souv??๏พ˜-๏พ‹๏ฝถI8? s่ˆ˜?\0\nzJ๏พ•z}๏ฝตK๏พ‰~^IO??ln่Ÿ†\0๏พ‡>?+\\๏ฝธ?D&๏พ›&๏ฝฎzๆบ‚?๏พ™๏พ’๏พœ๏พ›3?uๆก1๏ฝบ๏ฝฑl๏ฝท็›—s๏พ๏ฝฎ9S๏พ“๏ฝฏ>๏พž๏ฝญ๏พŒๆŠ˜jๅ’ฏ๏พŒ7\r=๏ฝฎ้—x?$๏ฝนo?\0qๅฝก\'๏ฝฝ[W๏ฝกzZ\rj?็ถ[3I๏ฝจH ๏พ‹๏พ›๏พŒF??๏ฝฝC้‡Œ:f]ic๏ฝฌ?-่ปป?4l๏ฝจ๏ฝฏ?G๏ฝฆ๏พž็’ข็‹ฌk(n?%๏พ™๏ฝฐ?\'็ชฉz๏ฝฎ๏ฝณๆก‘1?U? x็Œช8;\0%@Z๏ฝป๏พ\r[๏ฝฒ?)\"!a\Z็‰€C๏ฝป?1โ—‡rO\'๏พ–๏ฝด5็ดบ?๏ฝท ?K๏ฝช๏ฝฌ๏พ‘G๏ฝพ๏พ’,b2|?l?่ฐบๆˆฒ๏พ—%c๏พ“๏ฝฌc๏ฝฟ]A็ธฒ๏ฝฅ๏ฝด๏ฝถ?& ็”ณ็€้”?๏พๆ‡บ\'/๏พ€๏ฝฒ้ผ๏ฝฎ้ญ?็ณถ??;DO๏พ๏ฝฑ้ซข้ฝ‹tV8V<\0s๏ฝธ้€ตฮ‘Z๏พœ??5๏พD?C๏ฝฃbๅŽฆ๏ฝน็ฌฆ๏ฝถโ–ผ???ๅขธ=๏ฝฅAi๏ฝช๏พw}yws๏ฝด๏ฝจ\"๏ผ“??๏พ)?xQ? ๏ฝญ๏ฝก?I{c?๏พ‰z๏พ’O+Q?ๆš9่€ฟcๆ…3^็ญ‘?-B๏พ—่žณ๏ฝผ.ๆšฎ็‰‡!Yๅฏง#ๅŽ ๅจ‘qๅก”?6?>???๏ฝต??๏ฝฅ๏ฝง๏พ™๏พ‹็™ช๏ฝง๏ฝน Sssu็ˆผx??\0 ๏ฝฒ0๏พ˜ไนพ?้Œ†7๏ฝท๏ฝฆj๏พ—๏ฝซkRjๆ‰พe๏ฝฆIi๏ฝฅn๏ฝฌ?\"?่€๏พ†๏พ˜?wl๏พ€9dsW๏ฝง?;MkX๏ฝท้ถ‰ๆฏ›?$๏พ—(๏ฝง? \"๏พ?็“ท๏พœX้‚ฏ1?๏ฝฏ,๏พŽ4่†ฐ่พผ|ๅฑน5{[{?\0่“‰๏ฝบm>??-ไป†)C?\"โˆจ\\?๏พš๏ฝพA๏พ’๏พš๏พŠ๏ฝฝ๏ฝฉๆฆ‘x๏พ‰๏พš๏พ„๏พ™9๏พŽ0;ๆ†ซ?{็ฎ™?Iiz๏ฝฃR้ฎ—๏พ„p๏พ? ๅƒ‰๏พŽ่ฆฝ8lv+๏พ‰=?๏พY๏ฝฌ? ?:๏พœw๏พœ๏ฝจ??%๏พž?๏พœ?๏พ‡๏ฝถ1๏พš๏ฝซ/)๏พ—?8l๏พ’Z?M๏พœi?๏ฝญ2Z๏ฝคq๏พ‡็‡นๅ‰”?%?D>๏ฝตjๆ‹w,??;? ~_1๏ฝฉf 62๏พ‡?>ๆšฎ๏พŸๅ™บI3M๏ฝณ.๏พŸQT?6\0๏พ‡็ฐก๏พ–?4%๏ฝณ๏ฝคVvๅฉ๏ฝคZ๏พ$*@๏พ;Y๏ฝน็“๏ฝฅd๏ฝผๅ˜ดE๏ฝธe้พ ็•ทt?๏ฝจX๏พƒ4p@[็ฒ•ๆ’ฉ??ๅฃฌ}๏ฝช๏ฝง๏ฝด??=ๅ“ญ~&fXw๏พ˜๏ฝฌ๏พ‡๏พ“??\0f๏ฝฝOf๏ฝบ,๏พ—๏ฝข๏พ†?j ๅฐ‰;้นธ๏พœz2?๏ฝธ?1้บๆ˜๏พ‰%่ก†๏พ…๏พ?๏พ˜Tc??๏พ“๏ฝฝh๏ฝผ๏ฝฆ?4U๏พ\Z๏พtN๏ฝฝๆฎชmw4/๏พ‚๏พ‰๏พŒ๏ฝปๅณชl๏พ€?+?BK๏ฝญ?ww=๏พš๏พšใ‚๏ฝฃ๏ฝฐ\n๏ฝพ??๏พšO๏ฝช๏พ‰E$๏ฝฐE!๏ฝณ?3?ๅฒV๏พ’๏พ‘!๏ฝถ็ฏ  Y?gqยถd๏พ–o;ๆฃบ*็‡ผ่ฎƒ7ic๏พ“ๆ›พ XTn???S๏พœ็œ‹{8&X?๏พ•$LfBs๏ฟฅJ๏พ…u;?9๏ฝฌ?๏ฝจ๏พ›ๆจธ๏พ„็”ฌๆ ๏ฝต%่ซœ๏ฝซkb๏พœ็ฎก๏ฝบๅงซx\0Wt๏ฝฏ?$๏พ–ๆฌก๏ฝช?7PY?๏ผˆ%?{0?\0๏พˆ๏พ‡้ปœ\0w$?\0?\0๏ฝฉ5?-๏ฝฟ\0?O??2h๏ฝฏu%ๆคi๏พŒ้ถธ๏ฝข่ข’ ๏พ€lL?๏พ‰๏พ€\'๏ฝฐ๏พœ๏พ˜m๏ฝปO้ขฏE) 1๏ฝคQF๏ฝกQ@UP0\0๏ฝฐB??๏พŸ็–Š๏พƒ๏ฝซ~ๅ“ฎ๏ฝกyy$๏พwp??w\n๏พO\nQGl?&๏ฝถp่“6n?\nR่•—\"ๆซจ\0๏ฝฅ)@)JP\nR?ๆซจ\0๏ฝฅ)@)JP\nR?ๆซจ\0๏ฝฏ\Z~๏พ•๏ฝฟ็คชk๏พ™~#t๏ฝขxZ๏พ๏พˆ\Z๏ฝฅใ‹๏พ…ๆ…ฅ%?ๅˆชN6๏ฝณ\r๏ฝนV=่ช‰$D?Uๆ—ฉ ๏ฝฌ2?5๏ฝฆ,๏ฝฒ๏พ…5(?(๏ฝฉ*gร—??๏ฝฉ?m?๏พ‡๏พ“็ฏญm๏ฝตKๆฟก!%9^๏พไธžYๆ„ˆ>๏ฝขaๅฐค๏พ?>\Z?๏พ<{?๏พœ?kil๏ฝข\"oc2๏พŒ๏พ’<๏พ’๏พ‰๏พ?\npๅ‘ฐ?ๆ‹›v[Zๅฝฑๅ‚gj๏พŠๆปด๏ฝผmby๏พNy๏พ…}?๏พ?8]๏พƒmh? ?่ผธ๏ฝฝ๏พ•4m:?~?๏ฝฑ))ef\rๆฑบ๏พˆ๏พ๏พœ?>๏พ‡ๆ†ฌKEๆฅš?9๏ฝญ๏ฝฏ^๏พ‰๏ฝฆ? ?๏พl?๏พŸ4้จซt๏ฝฏ๏พžqG๏ฝจ4) wy็ถฏ??NH??gY๏พœ|๏พœ-4๏พ–[๏พƒ6eeๅ‰ *0{7็ฑ”[่ข—-c๏ฝฉ&๏พžW #3?A๏พ$p ?f\\t๏พŸN๏พ๏พ“๏ฝฐ๏พž้ซฑC๏ฝพ?\Zm2?๏พ„\r๏ฝธ*่‰จ้ฏ”้†บ๏พš๏ฝซ๏ฝท๏ฝฑG๏พ…c%?\'ไฝ†?๏พ•?๏พ‘๏ฝถ็ตฆq็ฃฝq่ฆฌp๏ฝง๏พ˜?8๏ฝท๏ฝป%\"๏ฝผๆฅชgQไบœ#๏ฝท*r๏พ—๏พž๏ฝฏ]๏พ–Xๅ“„๏ฝจ๏ฝง๏ฝฑ๏ฝต๏พ“่ฝฃ๏พ–+๏พ—?๏ฝณ??W$?{?.ๆ“บๅต[โ€ณ??$่™•X?\0๏พ8๏พ‡5้ดŽi่ฟฝ๏ฝญM๏ฝงZ๏พp?%1๏พ†่จ€s๏พ๏ฝฉ8FZ}ๅ–‹^๏ฝต๏ฝฒ๏ฝป๏ฝฒd่ก—?%R่ฒช๏พ๏พ’)๏พŽ?๏พŠ๏ฝถI9  \Z๏ฝฎ๏พž๏พž6๏ฝข๏ฝบ~็ท Z๏พ‡?I?&$V๏พ€\0e@่‹œ~?7๏ฝกu>๏ฝฑ๏พ‘??.ๆŒŒ?๏พ‰??^{๏พ”๏พ‡L?,z๏ฝงJi๏พ–๏ฝฑ4z%?\ZU๏พ‹mK?๏พ™๏พˆA?\0y๏พ‰=๏ฝณQ๏พš๏ฝป?>๏ฝซ?\rCYๅฆฒๆฎตPOๆฟฌ[???5??๏ฝธ๏พๅ‹ณqx๏ฝบๆ”ต๏ฝฑ๏พ„๏ฝข?)?\n๏ฝป๏พ?๏พ†x๏พ†๏พ๏พ‡{f๏ฝบl4่™œ๏ฝณd๏ฝฐ๏ฝปๆŽก๏ฝซW๏ฝฅ๏ฝพ๏พ˜่™ฑnl!p๏พ??๏ฝซ7MKx-^U๏พ‰-?:?)๏พ‡ q๏พ›้…Œ๏พ†๏ฝน.ๅขƒ)๏พ‰๏ฝงu;@๏พ“h๏พšP๏ฝฑTๅ…ˆ!ๅฏ›๏ฝน็‘ฐ?/a?๏ฝฉ?,u๏ฝน??/๏ฝคin~]๏พ‡?*?ๅกž!Xv๏พ๏ฝฆ*่ƒš? ?i\n๏ฝป??\0w?ๆฅ“&ใฟB๏ฝด?(#๏ฝณ/?๏พ๏ฝป?9Iๅนฃ#้ฉ›ๆฅ ๏พ›ๆทฎR๏พ›๏พ“!๏ฝฃ\n็ถต๏ฝพไฝ?้จN ๏พž?x?G#๏พž๏ฝณ๏ฝบ{๏ฝฉ๏ฝด๏ฝป?r \'??๏พ„?D go? {H|7?๏พ˜?๏ฝกpxV??๏ฝฎๆทซ๏ฝฌ?Y๏ฝฃ๏ฝฒS? ~q๏พƒc๏พœ?๏ฝฑ็ฆณ\Z3่Žซvo ?)#?๏ฝธ-๏พ?๏พ‘Tๆคก้…Œ]N๏พŽ?Vi๏ฝธ๏พ‡?k?ๅŸƒ๏ฝฒ้€n?tB?\Z๏ฝน๏พŠ g\'\"?๏ฝฆB\"9๏ฝฃg?๏ฝซ?;D_B๏ฝฒ?<๏ฝผ๏ฝฌ\r๏พ“?c๏พ$็œธ\0B๏พž๏พ„๏ฝฎ่’๏พ”๏ฝผ\ZMๆคš๏ฝค๏พ•bใ‚$%๏ฝฌ?๏ฝป๏ฝธ๏พˆ๏พš?๏ฝฒy็ž๏ฝฅ?@๏พ‘u๏ฝฅ๏ฝป\Z?๏ฝถ๏ฝคo๏ฝท?$$3rN?ๆ–ฝc?๏ฝจ?}ๆขฆMใ‚ฌ[(Z{~b?#๏พ‹๏ฝฑ?f๏พœ?๏ฝฏ๏ฝถj๏ฝฎV?Gh\Za???๏พ•๏พ›๏ฝซt๏ฝด๏ฝฐj6๏ฝฆ๏ฝถ{a<็ซฏ่Œ‰ๅท,๏ฝง๏ฝฑQ๏พœ ่ˆ–Y??๏ฝฑX๏พ๏พ๏ฝฏ[๏พ‰R?9d?$x ๏พ‡ Fใ่ฅƒโ™ช5YJ?d๏ฝข๏ฝป๏ฝญ?่ ?\"?\"?,โ€ปR7๏ฝฉ?n3ๆŽŒx๏ฝฌy๏ฝญu)\"๏ฝธ๏ฝพ้œ€๏ฝฎZ\r๏ฝนu,๏พ๏พŽ็ด†?๏พ“5y๏พ•๏ฝฆ?-=๏พ†๏ฝฃ๏ฝฉM.?H็›กx๏พŸ๏ฝนAe?!Y? ;g้ฃฎ๏ฝญh\Zn๏ฝน?/?๏ฝฅ๏ฝท?Z@!ๅˆƒ![??;ๅ€d๏พš๏ฝถ๏พ+๏พ—?๏พœ๏พƒ๏พ—a๏พ˜๏พ?\0\0\"๏พ‡?ๆชŽ v&๏ฝฐ4๏พˆ%k?/?,๏ฝข?9?!?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ',0.5808563,'q',5,7,'1942-01-20 10:45:14.0'), +(1979,'xwv',' uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\nMariaDB hereby grants you permission to use this License็ชถๅ†ฑ text to license\nyour works, and to refer to it using the trademark ็ชถๅปusiness Source License็ชถ?,\nas long as you comply with the Covenants of Licensor below.\n\nCovenants of Licensor\n\nIn consgeration of the right to use this License็ชถๅ†ฑ text and the ็ชถๅปusiness\nSource License็ชถ? name and trademark, Licensor covenants to MariaDB, and to all\nother recipients of the licensed work to be provged by Licensor:\n\n1. To specify as the Change License the GPL Version 2.0 or any later version,\n or a license that is compatible with GPL Version 2.0 or a later version,\n where ็ชถๅฝกompatible็ชถ? means that software provged under the Change License can\n be included in a program with software provged under GPL Version 2.0 or a\n later version. Licensor may specify additional Change Licenses without\n limitation.\n\n2. To either: (a) specify an additional grant of rights to use that does not\n impose any additional restriction on the right granted in this License, as\n the Additional Use Grant; or (b) insert the text ็ชถๅปธone็ชถ?.\n\n3. To specify a Change Date.\n\n4. Not to modify this License in any other way.\nLicense text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.\n็ชถๅปusiness Source License็ชถ? is a trademark of MariaDB Corporation Ab.\n\nParameters\n\nLicensor: MariaDB Corporation Ab\nLicensed Work: MariaDB MaxScale (TM) v.2.3.20\n The Licensed Work is (c) 2020 MariaDB Corporation Ab\nAdditional Use Grant: You may use the Licensed Work when your application\n uses the Licensed Work with a total of less than three\n server instances for any purpose.\n\nChange Date: 2024-06-02\n\nChange License: Version 2 or later of the GNU General Public License as\n published by the Free Software Foundation.\n\nFor information about alternative licensing arrangements for the Software,\nplease visit: https://mariadb.com/products/mariadb-enterprise\n\nNotice\n\nThe Business Source License (this document, or the ็ชถๅปฐicense็ชถ?) is not an Open\nSource license. However, the Licensed Work will eventually be made available\nunder an Open Source License, as stated in this License.\n\nFor more information on the use of the Business Source License for MariaDB\nproducts, please visit the MariaDB Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-mariadb.\n\nFor more information on the use of the Business Source License generally,\nplease visit the Adopting and Developing Business Source License FAQ at\nhttps://mariadb.com/bsl-faq-adopting.\n\n-----------------------------------------------------------------------------\n\nBusiness Source License 1.1\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make non-production use of the Licensed Work. The\nLicensor may make an Additional Use Grant, above, permitting limited\nproduction use.\n\nEffective on the Change Date, or the fourth anniversary of the first publicly\navailable distribution of a specific version of the Licensed Work under this\nLicense, whichever comes first, the Licensor hereby grants you rights under\nthe terms of the Change License, and the rights granted in the paragraph\nabove terminate.\n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must purchase a\ncommercial license from the Licensor, its affiliated entities, or authorized\nresellers, or you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work and the Change Date may vary\nfor each version of the Licensed Work released by Licensor.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provged that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVgED ON\nAN ็ชถๅปฃS IS็ชถ? BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHA',0.9881897,'axwv',4,4,'1987-07-30 00:26:51.0'), +(1985,'hm','?ไธ™๏พ›^H๏ฝฆ?w9Ljq๏ฝค?๏ฝช๏ฝฎ&E1๏พ”\'l๏ฝฃ?๏ฝดY;f๏ฝฅrๅŸ’1Vๅฎถ๏ฝฆ[mๆฉ?UeV5;cyT๏ฝฎ#๏พ“,6๏ฝซ๏ฝฌe๏ฝฝ๏ฝฑA?๏ฝถ?๏ฝฆ&็ท‹2ๅ›บ๏ฝฑUG่ถณ่–—๏พ?๏พ…w๏พ…s๏พž๏ฝปb๏ฝช$๏พ—7#?.๏พ‘๏พ“๏ฝถ5๏ฝท?๏ฝญT๏พ›./๏ฝต๏ฝถ_\Zc?5๏พš๏ฝนๅบท?๏พ‡?5๏พœ่žฝ๏ฝฎ๏พ‡h๏พ‡@qU2\rh1๏พ€m?>ๆ…ท็ช˜dๅ‹ข?Cๆบ๏พ˜c๏พˆ\0W๏พ‹|!T?;?#๏พƒ!๏พŸ๏พˆv๏พ€๏ฝซ๏ฝฉAQๆ•ฃ$๏พ”ๅ†?2๏ฝฌlh ๏พœ?๏ฝบ??ๅŽ๏ฝถ๏พ‡่œ’๏ฝญ%๏ฝฆI?1???/U\rX}๏ฝฅ??๏พ•๏พƒ๏พH๏พ’๏พ‰๏ฝป๏ฝฑ๏ฝฉ8๏พˆ่˜š? \"๏ฝปm?๏ฝช๏ฝณ๏พ€?,\Z?๏ฝฒๆฉฟ(1*?๏พˆ?๏ฝบeb๏พ‘๏พ€d}\'&ๅฃ˜y9๏ฝฆ ๏ฝด?้ก•7๏พ‡๏พˆ?\'?๏พŸY?ใ‚“\0่€Œ;Zi?P?p๏พ›Iๆ–œ้ŠทRๅ‡ฆๆบ-S??๏ฝฆZ43?}๏พ™\\๏ฝฅa?๏ฝธ|ๆงžA้ญ‚๏ฝจ๏ฝฆ+k่‡บ๏ฝฌ้šฃr=P๏ฝผ๏พ€\'๏ฝง??7????q๏พ“?๏ฝปf๏พ๏ฝทvOๅ„•x?o4?<ๅš๏ฝฎ๏ฝฝ๏ฝด็›ธ๏ฝฐ๏ฝฆt;๏พ›;?b้™h๏พCL$๏ฝฝ๏ฝถ[๏ฝฃ๏พ?-่ชคf$1๏พ>้ˆ\\%๏พ‡ๅˆ€๏ฝฏ้‘ฝq๏ฝขX?๏ฝบะ›๏ฝฐ๏พŠ@?7P๏พ‰๏พ€Znๅขพ๏พ†๏ฝญqs\'5๏ฝฆ๏พŠv๏ฝฆ#๏ฝซY๏พ…f๏พ‰y๏ฝก๏พŠd็ฃ??๏พ•?\\\\GmๆขถH+?\0(๏พ๏พ›?๏พœz๏พ‘Z๏ฝฏ??Nq๏พ–6?uk:D?? ้š™๏ฝฃ้š”=?\0็‰ดV้‹๏พ‹ %x&ะฑ๏พœ\n๏พž?Iu ?=[?:\r<๏พ†๏ฝฐๅฐ้ฎฎDn24๏พ•๏ฝญpv๏ฝฑ$2๏พŸN??๏ฝจ?๏พ›\0?\nwlEo๏พž๏พ„ไน‹?]๏พœ๏พ‡ๅŸŽ??5?ๅฃฎse ๏พ‘;K๏ฝชPๆšฆ๏ฝฟ๏พš^ ๏ฝฏ๏พ„?๏พ‰\r๏พ–๏ฝผ?g๏ฝค?๏ฝดeU๏ฝป??F@๏พ˜!G&7๏พ”?๏ฝท๏ฝน็›ฒ็—ฉ๏พŠ?44๏ฝจ๏พ€๏พ”,pkX๏พœ,\\?่ฑ๏ฝด๏พ‰?:๏ฝกๅ’ฌ#๏พŒ่พฐ ้ ‘UH?:???\Zๅ™ด๏พ—?๏พ˜๏ฝฐc๏ฝฑc๏พ—?C๏พ†(A๏พ†?$๏พ”?Vๅท“็ณŽ้—˜้\"๏พŒ๏พ€r๏ฝจ??๏ฝฃ+5๏ฝด?\0,K๏ฝจ@๏พ—+\"๏ฝช??X?4sHZ๏ฝฌ)้‰›๏ฝฆ ?4D๏ฝง?๏ฝฆ$c๏ฝชs๏ฝจ๏ฝญiN?U!๏พ’?51?\n?๏ฝก?4๏ฝญ๏ฝปK๏พ™-๏พœ2rไฝฏ๏ฝฑ๏พ›\Z^ๆ“˜k๏พ(๏ฝฑm?o๏ฝฒk๏ฝฟl่ปCpJ???/GA้งญ?๏ฝฟNt็˜?gYa_?๏ฝนz๏พž?๏พœ<8\r\ri๏ฝพJ2๏ฝฃ๏ฝฒ๏ฝทๆ‹ฎ:็Šข็—•?\"ๆฟƒ็ฐ“VHๆข ่€}ๆงจ็ฎ•๏ฝขH็นฐ๏ฝฅpๅฒณ๏พš\n๏ฝฉ,๏ฝจ๏พ‹p๏พ‡p๏พ•?็ฃš\'AJ E่šฐ5}้ชผkvT๏ฝฒpV?\Z_Z5^l๏พ‘ๅ—น๏ฝฆ?\0k,?๏พ?$ๅˆ‡3 ๅ—๏พ—qAๅกš๏ฝฐ็•ชs่ฆ๏พ๏พ‰i t$zgK๏พ’๏พ’?+s๏ฝจ๏พ?๏พ‰P+๏ฝพS?4o๏ฝฝๅฏงk๏ฝจ๏พ„็ฅ“c้ŽฌkใƒŽ?๏ฝด้šˆ/@Ea?๏ฝผ๏ฝฌbV?\"}^๏พžBDN๏ฝฎ{๏ฝน]IO?\'๏ฝพ?ๆ„›็ฌ„? mL๏ฝฆy๏ฝข?๏พ‡r๏ฝผๆฅณ_๏ฝซ๏พœ๏ฝด็นP:W\n๏ฝด?\015?4.ๆˆ› ?๏พ˜่ท๏พ™U?9็™œ\'ๆ„†14Zt??7ๆดช3?l>๏ฝฅ=๏พƒ้‰พ;?yQๆ—บ๏พ‹#:?ๅฟƒk=2่พผyh6๏ฝฉ\Z๏ฝคใผ6Hx๏พ—๏ฝฐ๏ฝฎ้ข๏ฝญ7.Zw4F4h?\rZ่…น\'??m๏ฝทๅ‡๏ฝฎmๆ\n๏ฝป???\0ๆข\"๏พ†๏ฝค๏พ—%๏พœ?๏ฝ”?\0v?b๏ฝถ๏ฝง-Q??Wl\'้žไผŠVV$??+่ฟ‚๏พ‚๏ฝตN?๏ฝผ2Hkjfkw๏พ˜๏ฝด\n๏ฝฒ?,x???p๏พ๏ฝญMX?\\J;y๏พ‚?$๏พ“T๏พ„lE@๏พ›.T?,.๏ฝฅ@@๏พ›\r?4\'๏ฝฝs%๏พ€?y๏พ˜ ๏ฝฎjๅ”พ๏ฝญ\"๏พ‡Zr๏พ˜๏ฝปh๏พ๏ฝฅ๏พŸ๏ฝข๏พ๏พ\Z?;๏พ™,!๏ฝถ๏ฝฝ?(?Kx?๏ฝฅ?้ฝฃ๏พŸ๏พœrๅธธFE~?+H\rz๏พ˜$?#lB๏ฝฏzl๏พ˜[\n?๏ฝก๏พ‰๏ฝซk??-^?I๏พ‚Y๏ฝกfๅฆŠ6่ƒ™}๏พ˜ฮฅU๏ฝฆ่–ฉ?-}?้‡Ž\'7๏พƒSh#?*??g.W[๏พ„iๅ”พ๏พ…P),F๏พa=๏ฝค่‰คF?-U๏ฝธ?๏พ”m??ๅ–จ๏ฝฏ๏ฝช?J๏ฝฑ?$\'ๅ“‚E?;v??็…–๏ฝฉ ?๏ฝถ?\0\"r?๏พ‡$๏ฝป๏พ’3?NU๏ฝข?#m๏พTๆบd๏พˆH๏ฝข้–ฃ8๏พ‘?a\'๏ฝป?ๆ ช\'R๏พ›๏พ–??ND??J~๏ฝฒ๏ฝง๏ฝฑM๏ฝณkๅญ็ฌˆ๏ฝฉ?.S+๏พ™O๏พ—\\!mi?2?# _\r๏ฝตM๏พˆ>้‹ฉaK?\r?๏ฝด๏พ‰๏พ?$2,๏พŠใƒฏ4tNw,๏พ—5ๆฌฃ5ๅฐ ?๏ฝน????\0\r๏ฝ—e?๏พ”๏พ‚๏ฝน๏พŸ? ็ฟก๏พ.?Y0f้ˆU?-ไฟ‚๏พ’๏ฝฒ๏ฝธ4๏พ›q็ฃ‹??[$^X๏พ’V็™ผiM๏พŠ4J+?Z๏พ”#๏ฝบ?๏พ”pๆตท?@?xs๏ฝป1?๏ฝด๏พ“๏ฝฏL๏ฝขB็พฉH?+๏ฝฅL?7?kF\\?A6?F:?็ฌณ็งฉs?%Z???๏พ˜็…–5X็ฅ–^?\Z๏ฝง\"ๅ“ๅฏขๆงŒฮ™๏พŸโ‰ซ๏ฝบ?\nh|้ฏข๏ฝนๆฅ=H?๏ฝธ?v(?P|๏พ!?\0็‰พTM0๏ฝฟ[*๏พ–๏พ‚ %ๅƒ\"=ๅ‡พ๏ฝท?._้ฆผๅ˜›?J๏ฝฉ๏พ›๏พMโ”ฌ]?8๏ฝป\0?1V3๏ฝญ้ถ๏พš่ตงV~G?\'K?้ฏ–๏ฝฏ๏ฝฆX๏ฝญ๏พ–?(}๏พ˜*8๏ฝธ๏ฝปK ๏พ™๏ฝน๏ฝพๅ คU6้คž๏พ€+S้ซ”?6?xWๅธ™?5#\Z๏ฝตQ๏พ•G?-๏พ—?4qne???๏ฝถv๏พ‹?/๏พ˜??๏พ”? u%้’F๏พ›?/S? #ๅฌ?_?\n๏พ˜๏ฝฐ?๏พœH๏พŠๅฟป๏พ™S?[??/่‚ฉโŒ’๏พ€็—•่›ฌ๏ฝซ*?b)??\0\Z็‹ k\"๏พ™๏ฝป๏ฝฐ๏พ›็–‡\"?๏ฝน๏พ็ชˆ๏ฝบu๏พ†?)๏ฝท๏ฝธB็„ผ5?\n๏ฝฉ๏พ†Z}bj๏พš๏พ€ v?I๏ฝง๏พ…??\0๏พ€่ฅพMๅขป\rv-z๏ฝปa?๏ฝค43 (๏ฝฃ?=๏ฝด!้‡ถ~G??\0\"๏พ–E???^Z๏ฝตๅ‚‘9+๏พŒยฌ๏ฝข?7?\"@๏ฝญ%๏พŒ7๏ฝฎ\Z_๏พž%๏พ‚)1?๏พ‚%_?/?๏พ‰ ๏ฝฆ๏ฝฅ1JrM๏พl็“ข-I=T?๏ฝญTV๏ฝฃ๏ฝฐ?lN๏ฝค๏ฝก๏พŸ๏ฝธ๏พ›?? ๏ฝกe(ๆ—ฉdC?$rS???\0๏พŽ?\'็ค’*๏ฝง^๏ฝฃ?=Ui๏พ˜๏ฝน{dGWV ??-๏ฝธ่ฅ ?W?W๏พ™F๏พ„u5?.?|?๏พœ๏พ˜u[ๆฅณCzQ?ๅ™จ๏พŠ๏ฝฃ็—‡?๏พ‡.I๏พ–?๏พƒ๏พ—????๏พ†๏พ˜X๏พ„๏พ”้ฎ๏พ‡ไฟค<ๆค??\0:M๏ฝงh-j๏พ“็ขพB๏ฝงz๏พ…๏พ›?็„ฆ? ๏พŒ?G๏ฝขYK๏ฝง๏พŒ๏ฝฎ๏พ–?p๏ฝฆ๏ฝค่ฃพ๏ฝฏ/?ๆก€B8๏ฝฏ\n้‡˜[%>\\๏พ•Y๏ฝฎ!?3 . ่Œฑ๏ฝบ๏ฝฏ$??\0๏พ™zๅ„‰๏ฝฑ? โ”=[๏พ‹z๏ฝญ๏พ‡?<๏ฝฝ4ๅฉe๏ฝผ?Qๅœ‰๏ฝง๏ฝฅ?๏ฝฐ?๏พŒ๏พ—๏พŒ?c่นดๅ‰žใ…?ๅŽฉ?๏พ‹I๏ฝผ็ŽฒH?๏ฝต-6j๏พ‡%๏พ—๏ฝจ๏ฝฑ?๏ฝซๆˆš๏ฝผ๏ฝฟ๏พ–f\\,ไผๆœ€๏ฝฒN๏ฝฒF=R๏ฝฆ๏พ‚?#WI๏ฝธ๏พ—????๏ฝญๅŠฉ?๏พ‘fๅฏ‚ng*๏พŠ๏ฝฅ+้ต‘๏ฝฏ??>้ ค๏พ›?&๏พ•<๏ฝฏ๏ฝฉ่ฝ†%ๅผŠ0?\"?\0็‰’?>v๏ฝก๏พ 3;๏พZ๏พ”\"=้Œต๏ฝท็ธซz0?V๏พŸ็„ฆ?W -๏ฝถ๏ฝฟ๏พ”5๏ฝฝEdjVi#A๏พ๏ฝฅU?๏พ›็น–\Z๏พŽ๏ฝง\r่ ‘๏พž]e.m}7?๏พ‘๏ฝก๏ฝซ๏ฝฒ?]่–บ่ฆณE[็ฉ‚b้˜œๆ†ฌ?\n็Œ\\๏ฝฏๅฐป*?๏พๅŒ•?\"?1?๏พ‹^v๏ฝณ\ZV๏ฝซ.ๆ…?4\0RA?r?\0+ๅฅ”T?z>?5?๏ฝฃ)ๅ†%Y;6๏พŠ๏พœ๏ฝท๏พ=y๏พ—Q้ฌฑ๏พ•d๏พ”.\0\r:๏ฝซ|?g๏ฝง?-๏พƒ?1?&?Zๅพˆ ๏ฝฝ?๏ฝท๏พ“?/fKx้››็ ฅ?6e533๏พ‹)zๆฐ‘\"p็†Š9???7???๏ฝขF๏ฝฉ\n?๏ฝฌ๏พ†?| ๆธˆ$?\0W%ๆ›š?-๏ฝฑ๏พ“$??0๏ฝฉgA,ใ—็ฒข๏ฝฃ??\0๏ฝฐlWC๏พ–?๏พ‹๏พ›??่ช‚๏ฝซ?@๏ฝจ_?๏พ๏พ™?\Z?$oไป?C๏พˆ๏ฝฉ@(V๏ฝชI๏พๅกฒ๏ฝบ้ฐ“๏ฝต๏ฝคๆฅญ่˜šnc๏ฝฒ่ฉ”่†\r๏พ‚ๅ„˜๏พŠไฝ•๏พšๆฝŸๆˆธS?>!ๅนกๆฆ”๏พ—C็‰ง๏ฝฌk?/N?๏ฝฑJ๏พG|^?!V?G_๏ฝก๏ฝฑ^&?(l}๏ฝฑB7Kๆจ›๏พš่˜ฐ๏ฝผF?5๏ฝญU[?\'?l3๏พ•๏ฝผ๏พ…?๏ฝฆๆฎ๏ฝผ\"U๏พ˜??k?่œšEp๏ผญ๏ฝฆ๏พ™>ไป๏พ™i? ๏ฝจ๏พˆ8๏พ1UE๏พ๏พ‚/%i8?\0๏พ†\\%๏พ•/E๏พœ?D๏พ„๏พ‚๏ฝป ;mๅกฉๅฅEB%*ฮฒ^ๆบŸo?:๏ฝง็ฒt?Y๏พ€?\0\0?+\'rๆ•ฒ๏พ™(้ฐ„่Œฑ๏พ‹~v๏ฝน?ๆ—Œ๏ฝญ๏ฝคj๏พŸ\\R๏ฝฌ?๏ฝญ*?๏พ—๏พˆ๏พ‚F?\0 ๏พ‘EN๏พš้–ผ๏พš๏ฝญ๏พŒ?9๏ฝญ\0?(&? ๏พŒj?%๏พ‘#^wEๆถ๏พŒๆฅshW๏พ‹?a๏ฝฐ=๏พ†๏พ‹;ๅ†Œ%$?ๆฝด@C7่ซ?+๏ฝซ?้–€๏ฝฅE$;S?๏ฝญ๏พ‚ๅ†Š\\๏ฝฃ?=R้งญ๏ฝฏ$xj\"-E่‹ก???ๅฃœ๏พŽKNdD_็ถœ๏ฝปN็ดŠL๏ฝฐS๏ฝซm ๅฎด c๏พ“^๏พŸ๏พ๏ฝจ2?\"5็‡ฟ\nQG?P6๏ฝฆ9 47๏พ„ๅพจ๏พ†k๏ฝพ๏พ˜1>๏ฝฏ้—?\'่—ฅ?๏พ\Z๏พ„๏ฝฑ?๏ฝข?,U!๏ฝด??,ๅ”ฏS?M8\08??7/๏พ™๏พ€Rz?\Z๏ฝฉ?+ZๆžP:w๏พŒ๏พŒF๏พ•๏พˆ?๏ฝช1๏พ„en\"ใƒƒM}๏ฝฑ?*?9?\'&๏พŸ)๏พ›๏พŸ5O\\H่›Ž๏ฝฅkF?่œฉ๏ฝถ๏พ™ ?qN;eV๏ฝข๏ฝน๏พ“่œ†๏ฝจX<1T๏พŽ?2๏พ8๏ฝฅ๏ฝพ๏ฝง|๏ฝชeๆ…Š๏ฝนZE4๏ฝฝ1๏พŽi๏ฝถ\"๏พ†๏ฝธ๏ฝช?๏พŠ๏พ†ไธ”ๅ‡ต๏พ…Wc?๏พŽ๏ฝธ็ฉขU๏พŒk?\\Uxoq๏พŸq?ไบˆ๏ฝซ?:็ณปUr๏ฝฐ*๏ฝจ9๏ฝซ?/๏ฝดr้œ€๏ฝณaWRๅฑ†I?/๏พ— ?x๏พ๏พ๏พ–&ๆก‘ ๏พ”t๏ฝญ*n?$๏ฝญ v๏ฝฆh๏ฝถ#Y,๏ฝทSpๅทŒ2A\'?๏ฝฟ๏พŒ๏พ™Z๏พ†๏ฝฅ๏ฝฏ<๏พ—๏ฝฒ?๏พ‘bๅณ\0\0qV?\0c?<๏ฝฟ๏ฝงB?๏ฝท?\"X๏พ“rYโ‰ซ?๏พˆ๏พˆ๏พˆ???$w\r๏ฝ†็ง˜??/\Z;๏พŸ๏ฝฌ$๏พ’๏พŠ>%U#?๏พŠ??๏ฝฌ้\Z,?\'+๏พ—q๏พ‹u๏พ‚๏พ๏พ„a?h?๏ฝฒ๏ฝกS\\x้ฉƒ?,๏ฝง?\"??)??4๏พ&]L๏พˆ#?๏ฝฏ&\'๏ฝฐ๏ฝจ\\$?E?;b๏พ‹0y?๏ฝง?๏ฝฝJ๏พ„X\\๏ฝฝ๏ฝฒ๏ฝธๆตด๏ฝง%้‘ต6;็จ—่ขNQ?็ฝ ?!๏ฝณ#TnH๏ฝฅw๏พ›๏พ›๏พ‡La?W๏ฝจ๏ฝฆg4๏พŠ&ไพ†p*?๏พ็ˆจ๏พœ{? c๏พƒS๏ฝฆVr7๏พŠF \Z\n๏พ–๏ฝผ๏ฝป?\0๏ฝซ็ง‘?๏ฝซ๏พ?Qๅจ˜โ”ฏ2?\"$E}้ฉช??๏พ”๏ฝฎ\r๏พ’๏ฝŽ่ฑ๏ฝฟ?๏ฝธ๏พ’๏ฝธ?FF?7๏พ•od^ๅฒ”Ib๏พ„๏ผนๆค’๏พ‡%Zoๅš๏ฝปr?0h่’ŸW4?pi๏ฝฑ๏พŠ$de็ฒ‚๏ฝคH?่ตฑ9ๆ‹ŠE่ˆ˜๏ฝพะฏ๏ฝชๅฐŽ5?๏ฝญ๏พzLฯ†v?2๏พ—๏ฝถ\n๏ฝธ? ?1๏พ„\n^#v?G?k๏ฝซ๏ฝป!c!?*๏ฝฏ0M;????Z+R\"๏ฝฑๆœWrๅ†ต๏ฝฟ่ณฝ)๏พ„๏พ—๏ฝง?xOdๆŸฉ๏พ—่ขฎ/ZK??*๏ฝคxa๏ฝฟๅช็ถข? ?\'0ๅ‡ฉDOu?๏ฝตๆฎ–๏พ•๏พŸ\Z2G๏ฝฎ้บ7i?๏ฝฟ?๏พj?y๏ฝฝG\"f4Pv็ฅ•๏พ˜9?่ขฑ๏ฝงg/๏พ—o๏พ“๏พ็ท’!๏พŠๅฏขd๏พ‹z??๏พ—>๏ฝฏ๏พƒๅฝฐ$๏ฝญ?o?$๏ฝบ๏ฝฟ่ง€๏ฝฑ๏ฝซY๏พ‹!oO๏พ”ๆฃŸ๏พƒ๏พ‘Pๅ‚_?๏ฝน๏พ„๏พ— yw๏ฝฒs,?๏พ“SM๏พ—?๏ฝฌ๏พ‚Et๏ฝซ๏ฝฅk๏พ†๏ฝพ.๏ฝฝ๏ฝฐ{๏ฝฉ ?๏พ๏ฝฏP?pO$๏พŸ๏พ5๏พ„?,๏พŒV็–‰X๏พ…>/๏ฝตๆœUๆฉก?=๏พŒ?<๏ฝฑJ๏พWzๅ”ฎ1?\r3๏พ…๏ฝณ?f?<ๆ•ฌF??-gi๏พ—-#๏ฝฌA\"nJy้š›?็‹’/y๏ฝขy%H l๏ฝต๏ฝฅW๏ฝท?<็ถฑๆ˜ฟ๏ฝฟ?๏พƒH?%่ก™>/๏พš??\0๏พž่ˆŽe:?\0ๆƒ†|๏ฝฃ#\":๏ฝดไธƒ?๏ฝก?>๏พG?,๏ฝน?๏พ–๏ฝญ$๏พ“๏พŽhไฝ)?Fol?-๏ฝน}m[๏พ•?\'๏พ‚?#F?๏พ…\Z?26่ฉž๏ฝฌ?i?9ๅ€ฌๆ™???5?๏ฝฏ\0๏พ‰?lใฉv๏ฝซ2?*TZ่น‰๏ฝฒ?;?/๏ฝฎๆขๆขถZ๏พˆ$9&4๏พŒ๏ฝด๏ฝป[O-๏พ˜๏ฝฒ๏ฝข(P*๏พ„๏พ’๏ฝฟๆœญ5??*<6@๏ฝญEWyๆฃ‰Uๅฃฅ.\'jE%j๏ฝต๏ฝง?>?\0Jๅงช?๏พ… ๏ฝข๏ฝฑ๏พˆ ?o#๏ฝบ๏พŠDr]๏ฝฟw??jU๏ฝท:่ฟบ?u๏ฝช๏พ›ๅ’ŒFWZu\r?๏พ‰๏พŽW๏ฝขX๏พ…,๏พ‘๏ฝฝ๏พš๏ฝฐ?๏พ?4๏พŽ?/ๆ“ฝ?\0+๏พ„๏ฝถ?Y:?้ฏข(๏พ”F?่จ–?um๏ฝค๏พ‡ ๏พšไฟ„๏พ’*๏พ‡๏พ†ๆถŽๆŸฌ๏พ–?๏พ•5 ๏ฝฆ\'?3?j่Œต๏พๆ ฒๅตถ๏ฝฐ-๏ฝซ\n\"ๆžฉI๏พˆ๏ฝท๏ฝฆa?9๏พJ๏ฝตv$?๏ฝฌ?(?็Œซ๏พž๏พA๏พ’4?๏ฝฑโˆฝ?(็”•}nc?$??\r?๏พm?๏พ‹้–ข?H๏พ๏ฝฉ*J?๏พŒ~oไฝ™๏ฝต๏ฝท๏ฝด๏ฝฑ,J?\0ra_ๅ‡บ?่ฆWๆจถU}NR??#๏ผฅ๏ฝผ}๏พ•๏ฝผ๏พ?๏ฝฅyๆดฒๅ ‹๏ฝค3IB ใƒป??ๆกŸ?๏ฝญCโ†’Ko\nsZ\0VAJ*z.??$ๆŸ†๏พ˜Sjd?๏ฝท\"?่ฑขๆค๏พ™?P๏ฝพ๏พ“๏ฝง[?๏ฝนf?\0S\0้™ฌGๅฐบY๏ฝต ๏พ’J?๏ฝปๅบš+?๏พ‹<๏ฝท่ผŒo๏พ’n 9M๏ฝฎ??\0็žฅ?่Ž–๏ฝซ ๆŒฟ6*A\Zq2๏พ™๏พ’๏ฝฏ?Tx?ๅฉ๏ฝท!A@๏พ„?ๆ–ฝg<๏พ”l๏ฝค๏พ“.๏ฝฅ๏ฝณๅน”๏พ„?\Z?#LK๏พž๏ฝคRๅคฌๆ ฝ\\๏พŠx?FX๏พ…๏พ‹๏ฝฑ๏ฝจ๏พ๏พ\\?๏พf๏พ„X0#?#?=?s๏พ€?qe?ๆ˜ฏJ\Z๏พƒ๏ฝฎ8??๏พ็ญฑ๏พ”@๏ฝฌๆ›„ๆ…จ๏ฝฆ\"F+o๏ฝฎ?*|p๏พŠ}8๏พƒ2*G? ๏ฝซe๏ฝซJๆข็ฌ„้ƒz็ช–๏ฝพ[}?๏ฝถ??:?\rRk y ้ฐฏ?๏ฝชu๏พ› ็นป๏ฝทA๏พ“?\nๆ…จ๏พ™[f้Š–๏พŽ$Al๏พƒl^๏พŸ็•ซOO ? ?2๏ฝฎ?๏ฝค3H?5F_*้ˆŽM๏ฝฅ๏ฝฅ๏พ‡?1๏พ(๏ฝจ้ฉค้„ญ๏พ„?-N? ? 8??.ๆšˆ็ฎ†(r?+\\U๏ฝบ๏พ“๏ฝฆ=c&3&๏พ”}??\"ๆމ?#n๏พ˜๏ฝช?5?=r๏พˆ#zlr๏พ€-ใ‚๏พˆ๏พŒ1?็‡ƒ?B๏ฝนaL??;e๏ฝก็พฃ;็ซ‡?>.๏ฝน+Bๅˆ‡ๅฝ—$่ฎ?้ -๏ฝจ๏ฝฉ๏พ…Lๆ“ฒ5;u๏พ?;ัŠc๏พ๏ฝธ-Q?>?.๏ฝตp-?cๆ“ง๏พŠ๏ฝถ>P๏พ“๏ฝฆK๏พ’p ?๏ฝฏ??6??๏ฝฝwๆ —๏พ„ๅฝซ?F๏พ๏พŠ๏พ?5&<็ z๏พš๏พ‰.l็•”๏ฝก ้œnw๏พ z๏ฝข๏พžHgm็นฝ้€ธ]๏ฝจ?0๏พ\nQA\n?)F๏พ›้œช๏ฝฏ70 ๆ =๏ฝฒ?+4[D๏ฝญo?,๏ฝญ&}๏ฝจ๏ฝฟ8๏ฝญ๏ฝฉH๏พ›p่ด–ๆŽดๆณ? ๏ฝกE้žDA&๏ฝผๆต„eW#?d๏พZ๏พƒkQ-๏พ‚~?n[๏พ‚็‘œ)Z\\i๏พš๏พŒP๏พŒBG*?,๏ฝงb๏ฝฟi๏ฝฟ?9a=๏พ‡tๆƒ‡ๆฏ˜๏พ‹?๏พŽๅ•๏พœQob+้ค˜??9๏ฝฏ๏พšO๏ฝตๆˆฆ^๏ฝพ๏พ“#}\n่ฎ-๏ฝฎ๏ฝช๏ฝฝ~]?+d๏พž?Vๅฅ˜?Q๏พŒ6_๏พ ?kๅผ•๏ฝธ๏ฝฐ?\0+่Šณt?<๏พšy?๏ฝฎ?+?ๅญ›??\0๏ฝณ?1๏ฝญ๏ฝฉQ3๏พ™2๏ฝฅ๏พœ\nHP๏พ„? ?๏พŽ๏ฝผ๏ฝฐๅ‡l@<๏พ‡๏พ…)?๏ฝงq\"E๏ฝงH?,6้ปถG?? ๆ„‰??๏ฝค??>?Zw]ใ???็ฆZ๏ฝนๆœดC๏พŒ๏พ‡ๅฒจnk?่Žชit๏ฝธ๏พ‘t๏ฝพ?\'y?VA๏ฝบๆ‰ฟ?๏พ‹็œฅEๆฟ&๏ฝบw%:ๅฉฆ)v๏ฝฉ๏พŽ8ๅธ™?ueh๏ฝตๅญ›่€—็นงH๏พˆ๏พœๆ—™่ˆ‡?๏พ…?9%V๏ฝฅ๏ฝซ๏ฝก็ฆฎ|,~๏พ—??^]ๅปบ๏ฝญ?2้ง…x??่ก’KyS #?๏พ†?\r๏ฝฎWPh๏พš๏ฝซ\"?๏พ–L?็–Š2๏ฝฝ๏ฝปๅป“็ฑ–๏พ…~๏พ—|่œjwnb๏พˆ\n?O?u็ซฏ{f่”€Q\n)?๏ฝฆ?๏ฝฏmๆฎ๏พŸ๏พ˜๏พ\n๏พŸ๏ฝฝ๏พœ๏พˆM@?8๏พ”m$๏ฝฑ๏ฝผh๏ฝฎ[?o๏ฝฟ๏พŸๆ€’๏ฝซ?ไฟ‘๏ฝฑ๏พ‚?*Oๆ‚”๏พˆ??3๏ฝป?4u59?^๏ฝฟ๏ฝฌ=?E\"?\nz๏พ“๏ฝพF% =๏พ’๏ฝชๆฐค?>้ฌป?S๏พ\n๏พ—q^๏ฝฟ?m.b๏พ—K\'p๏ฝค?9v3??็ตO๏ฝน5ๆซบ}:@ใƒปx2๏พ“๏ฝถE๏ฝฏeY%yx๏ฝฉ$??{*๏พŠL๏พŽ*๏พ๏พ— ๏ฝฆ๏ฝทr๏ฝฎ้‚ฏog!A๏พ„๏พ…\n S๏ฝท>?50sXHQ?|@jv๏ฝฎ้ก?b๏พƒ??่ฆ‹&๏ฝธ,(?4?1ยขd?? ๏พ‡8๏ฝก๏พ†่ฝ„๏ฝฑT๏พ–v?๏พŸ้บญ๏ฝฟ?#?๏พ™๏ฝพ๏พ–้†‡,SaC?(๏ฝช? ๏พ‰wB,u๏พŸ{๏ฝธ่Š๏พœ็จท๏พ๏พ‚๏ฝซ?\0bN@j่˜ฏๅฝกG๏ฝน>,q?๏พ‹1๏ฝฐ?๏พŠ่€˜๏ฝท๏พˆ?)๏พ›.Vm?๏ฝฎ7๏ฝฎ!\\๏ฝค๏ฝณ(๏ฝฎ๏พƒ?ๆกˆU?3Sๅทป?๏พ˜๏พ™\0C๏ฝถ>c/?LNB oๆ…ฃ๏พ‹๏พƒ15๏พŠๅ€†?[S็ญ,ๆ•ฌ_P๏พ˜?\Zv๏พ†้œœไบ…|๏ฝฉๆธ‡[้™ฐJ5+๏ฝท?$,p๏พ…Z#(๏ฝฎ(Mw=q2k๏ฝถE-๏ฝฒ๏ฝฉ\\๏ฝฆ๏พ›(!S=Xa๏ฝผๅฃŒ)๏พŽ&?z๏พ€i๏พ—๏ฝฒB๏ฝฟb๏ฝค๏ฝฏ??ux้ฎฎ๏ฝธ๏ฝซ๏ฝป๏พQ๏พ˜๏ฝฑ{็‰˜U?๏พšๆ‹ฏ๏พ‚YM?๏พ•?K๏ฝค๏พ…I๏ฝฏยฌ?๏พŸ31n๏ฝฝ๏ฝฐ๏พ–?q๏ฝธ?๏พ†็ฎ๏พ”ๅŽณ๏พŸ๏ฝฎ0\r?ๆงจ๏ฝซ๏ฝบt๏พŒZ๏ฝปT&๏พ˜๏พ–ๆŒqU2?-N?๏ฝกM๏ฝฑไน˜\\o Yๅ™ชๅผƒ ๏ฝฐ๏ฝป๏พ—๏ฝฌU๏ฝฉ๏พ&?6๏พŠg]๏ฝซ?ๆข*๏ฝด๏พ†๏ฝก๏พŒ๏พ›?1Ws๏พ‹๏ฝฏ?$E1๏พ๏ฝฉๆถฏw๏ฝฆn5้ฉฉA๏พ‡?5๏พ›.*F7็ฒ›๏พ๏พŽ(X\Z็•„?่žป๏พ‡๏พ„\Z็งฃ??ๅฝฆ*๏ฝค๏พŠNa|~็ธนQO<๏ฝช S๏พ˜??H๏ฝต\"?ๆฆฒ๏ฝฌ๏ฝนaI?:et๏พ‹่…ŸP\ZW๏ฝฎ*๏พ๏พŠ๏พŠ้ซฎ\\?๏พ—ๅ–‰๏พŠ?;๏พ“\r๏ฝท๏พ\\?\0๏ฝจF\Z?็Šง๏พŠ๏พ€๏พ€?U;็๏ฝจ๏พ•Q?Yๆจ‚๏พˆ็ช’A้‘›ๅŠ6๏พ“ๅฝ—๏ฝถ\'่จ?๏พ’?1s๏พ„?1็•™๏ฝพt๏ฝญH่ฌ>๏พ€?LS ?G3๏พŒ๏ฝฎ?$๏ฝฑ}b๏พ•8๏พ„?)๏ฝพ*็œ J~๏ฝง๏พŸ\"๏ฝต๏ฝฃ7๏ฝช๏พ”๏พš๏ฝน[$๏ฝฎ?)/?w8&้ƒŽ>? 0.๏พ‡๏พŸ?๏ฝญ>๏พ‰9๏พœJzd^?I(K๏พŠ 7&๏ฝข๏ฝต๏พ‰F2<้ฃŸ@M\Ze?)?n A๏ฝญ~ๅ€ฆyzm;?!\n๏ฝซ*?9๏พ…๏พ„๏พ†y\ZB)๏พˆ๏พ–?&๏พ’?๏ฝฅIS?๏พ—O๏ฝง.8๏พ1{I?๏ฝฝ๏พˆ๏ฝง{d_T?h3ๅ‡ต?\n5GA???,.็–‹๏ฝญ๏พ€?๏ฝพ9?ๅจถR& v?๏พŠ?7L?G๏พ‹VWๆ–ฅ>?#M$@4ๆ ผ๏ฝฐ=i?๏ฝฎF?j็ฎดBK)\nkN-O??๏พ‡<็‰ฒcb๏ฝง๏พ˜่ฒ‚ๅฎ…$g?j~y?\"y๏พ‚๏พ–ๆฐ“๏ฝจF?8%t๏ฝป๏พ‡๏ฝท7k???}๏ฝฌ๏พŸ\'?ๅฉ๏พ–็ฟป๏ฝต*?+?)=๏พ‰่ฒ‚๏พˆ?,(๏พๅŸŽ๏พžU๏พ”๏ฝต็ธŠH\"๏ฝต#๏ฝฟ๏พ„๏ฝน#+}๏ฝค๏พž\r3U\0 ้ญ5๏ฝณ๏พ”n?t๏พ†?๏พ?๏ฝฆ\Z๏พšyๆ™ข?ๅฉ€๏ฝฃ๏ฝข1๏ฝซ๏ฝธ๏ฝฏ๏ฝฟ?9 0็‡ญ ๏พ”??๏พ†๏ฝฝ@9 ๏ฝฒ๏พ’g๏ฝปib?>fๆฒณz?q่ฑˆ6$??- $6F4๏ฝฝb/๏พ๏ฝผ๏ฝณ\0?๏ฝฅd๏ฝญT็†„)๏ฝคๆŽˆ๏พž(Xz-๏พˆS?ๆก‘ๅ–ถR๏ฝช๏พ„๏พ”W5๏พ™Fไผ???๏พ„@๏พ‹G&(?;๏ฝญ0Q๏พ”?L3๏พ•๏ฝผ๏ฝญu๏ฝค[๏ฝญ๏พ”๏พŒๆœˆE8ๅฅŽ๏พ‚X่šฏR@?y?๏พ‹๏ฝซ!๏ฝง๏พŒC๏พ„?๏พ›qC๏พ‹๏ฝฎ๏พ…{rN๏พ‰o?\n=???๏ฝฅ!๏ฝทๆฆ”ๆกทv๏พƒ๏ฝญo๏พˆ?๏พ‘?-QF??h?9\04W? )๏พ“ใ‚žๅธš49R๏พš๏พ‹eu*๏พˆh๏พ‚?&๏ฝฌ@๏พƒ๏พ?nๆ˜๏พƒ? NDๅ•—&๏ฝฒGot#|่ ๏ฝทๅฌฌ๏ฝฟ$4?,s๏ฝฉN๏พ•^g?5๏ฝฅr๏ฝฉB๏พ‹1\'๏ฝฉi7*๏พ‹J็›ปmๆƒถC๏พ—]aๆŸ?๏พ˜๏ฝฏ๏ฝธโŠƒGL๏ฝฎQ ๏ฝคFIZ้ˆŽ2)?(๏พ”q๏พ‡4้‘‘๏ฝฎE+-\"U=paM?๏พ˜\\ F|0u๏ฝด?๏พ–*?5ๅดข๏พŒะท ๏พŽ?:?2ๆžข?T็ญ‘5C7}?๏ฝฏAmoU็พน~๏ฝผ้ซ1-S๏ฝฅ0๏ฝฃY๏พ๏ฝฃ๏ฝน?๏พ‡๏พ†{?ๆฌพ๏ฝฃTu\0E๏พƒ๏พƒ้ด’๏พ’iๅฅด๏ฝฑ?#|๏ฝช๏พ˜\\๏พ™๏พœ4r-X๏ฝป?Sg%๏พ‡๏พ…ๅ„”๏ฝข)๏ฝฌ?๏ฝฟ๏พ‡๏พ๏พž๏ฝน0๏พ“?๏พ“?l%P๏ฝฆ:๏ฝต๏พ‹GP๏พ•#่‰‡bo๏ฝถT\0๏พ’๏ฝธๆŠ‘?ๆŽc๏ฝฎ*๏พ˜๏ฝฟ๏พ‘?๏ฝตe?s๏พ—R๏ฝฆc๏พ“79G๏พƒj8?0๏ฝซๆจ‚k๏ฝฑ๏พŸ|ke๏พ…*๏พ‹๏พ“lk-(k๏พ—\Z๏ฝง,ใ‚ซ?8ๅฝฌๅถข?็–‘๏ฝน@o?*u?๏ฝซๆ†ๅˆ๏พŽ๏ฝฆ๏ฝธ๏พ€?i\0\r๏ฝณeๆคฝ?ไบ‚ๆซš๏ฝฃ็•ข๏พ˜U๏พ„v๏พ่—ๆฃบ๏ฝพWL๏ฝพ๏พ™T๏พ€๏ฝญ?่ณšๅฎŒ?ๆดป๏พ‰?A?ๆกœ๏พ…๏ฝฝ?R็บ’hz็ญฑC๏ฝฆP๏พŸ6X?U#ๅ€ฃๆ’๏พๆค?L๏พ•?้ต?4๏พ„?๏ฝงc๏ฝ’Dๆ…ŒๅฏฉE5\'?#ใ€‘ๆ“บ๏พ๏พ„๏ฝช&็ฒขngg?๏ฝผi?\05u?9W}๏ฝพ๏ฝฟ?<๏พ๏พ“??\0(<0%@\n\Z่ซซU๏พ‘ๅฏ?Y๏ฝค๏พ€(\0~P&๏ฝฝ6๏พŠnๅ›˜P?\"๏ฝธU๏พ‘?๏พš๏พŽx๏พ“๏พ„?H็นž๏พ‘Sp|2็ถฏ??+???๏พž?๏พ“๏ฝถ ้œ€!]็ญ็ดซ๏พ‚๏ฝฟk8S๏พŠๆฆ๏พ•๏พ†|j๏พ•}๏ฝฅ๏พ€็”ฅๅƒ‚-:a๏พ•?7t?่˜Š๏พ‰?๏พ™?\0โˆง?6?๏ฝฎ๏ฝก๏ฝ๏พ›lๆ’ƒBg๏ฝง??๏พŒ๏ฝก๏ฝขz้ฎฎ๏พ”9&?\n}๏ฟฃ๏พŸ J๏ฝญ๏ฝต?%?\\|๏พ—? ??zv๏พŠ๏พ‰๏ฝฒ๏พ‰ๅ–ง?๏พ›็‘ ?2W?่ฉ”๏พƒ๏พ5[eu?q\'?9๏ฝธ๏ฝถๅฟ˜๏ฝคh?\ni?V\n๏พ‘่ฟบ$h\\๏พ’?\0๏ฝฏ๏ฝฑ๏พ‚y!;๏ฝฝ )<???$o,๏ฝฆV5,??๏พ๏พ”๏ฝญ |?$\Z๏ผพ่ทซ?@b๏พ†๏พ?#็ณดๆฝฎ๏พ๏พ›q?+\Z?๏ฝจ\n๏ฝข?\n?8m๏ฝซ๏ฝฃp๏ฝข??(7P |๏พ‡|!P?.H? ?Z?๏ฝฅ|\0?่ผฟ?H๏พ๏ฝฉL=?8V๏พDB๏ฝฌ็“ฃ?๏พ‚N๏พŠ๏ฝง๏ฝฅM๏พ…็ด€๏พt?1ๅ•พ๏ฝฅ๏พ๏พ•่ˆช? ?z9=>K๏พ’?u่ฟซ Cxt๏พŒ๏ฝต?)๏พ’๏ฝง๏พš๏พŠ%็ณŠ?็™’0R๏พ—p\r;??\"็ญ]j:\Zt๏พ˜?$๏ฝด็™–?k?\0o๏ฝฝ?\nau็’ข?!๏พ‰็–ซ้ฌจ๏พ›~ _ \'๏พžop๏ฝฝ?#ๅกžnV๏พ๏พ™๏ฝณf๏พ…\\7๏พ‡ไฝ‡๏พ†ใ‚ญyๅผ”ไบ‚ๆŸฉ๏พ™๏ฝฑWf๏พ?vl๏พ™๏ฝฑWf๏พ?vl๏พ™๏ฝฑWf๏พ?_?๏พ„HFๅ‡Q?Ut๏ฝช?่œฅO\\๏ฝต๏ฝฅw๏พ…V่ฒฎ๏ฝฝ;c1U๏พ‘??ๆœZ ๅ‚\\R๏ฝท6)้ฑš๏ฝฆ(k6l๏พ˜๏ฝซ๏ฝณf๏พๆฃบ6l๏พ˜๏ฝซ?๏พ”??X4้ซŸ?\\\\ๆฅฎ๏พœ๏พ™๏ฝฑWf๏พ?M?$๏ฝน?็จ”h๏ฝถ?๏พ€p๏พœ๏ฝผ๏พ“*k?๏พ•๏พr4n๏พ•K6l๏พ™%DCh?ๅพผ๏ฝถ/๏พš๏พW๏พ‚๏พœo่“‰๏ฝจไธ‹b๏ฝฉi4๏พŠ๏พ‹cS\\๏ฝฌU๏พ™๏ฝฉ\\๏พ˜๏ฝฝ๏ฝฐ๏ฝจqU??็ฌŠ\\๏พˆW๏ฝฎ\0Unl๏พ™๏ฝฐ๏ฝซ๏ฝณf๏พๆฃบ6l๏พ˜๏ฝซ๏ฝฑ๏พŠ๏พœq๏ฝน๏ฝฑUFไผ๏ฝฆ\'?6*?๏ฝณb๏ฝฎ๏พ๏พ“53b๏ฝญ่ชฐVl๏พ˜๏ฝซ๏ฝฑxQ[๏ฝฎ!?่ขˆ*?\\๏พ…ๆญŒ1U?๏ฝฆTq?1็†™d๏พƒ?Bi?็ฟ†็ฒ—??6=?X\n,d๏พ๏พ‡?62\0๏ฝก๏ฝฎ?x\0?5J็ฏคW๏พ˜้ถด?๏ฝก?๏ฝถFdrh:Pa๏พ‹๏พ‘p?0๏พ’=74?๏พ“๏ฝผ๏ฝป๏ฝฎG๏ฝคyv?๏พ›?\0??๏ฝข๏ฝญ๏พƒ??^\r4s n\'?zๆฒข?{s๏ฝฆ?ๆŸต?3?5๏พœ๏พŠ??๏ฝฆ๏ฝญ#??\0^o?9็ฉ€๏ฝถ๏ฝฝ๏พŠ?#?\0๏ฝฒ๏ฝพ๏ฝฅ;?(๏พ…้ป๏ฝฑQ,??\0๏ฝน้™œ:?;๏พ˜Dๆ‰˜P+??\0+?็Œด\ni?๏พp?4๏ฝบ้ฃŸcA๏ฝบ๏ฝฏ??\0?๏พ”๏พŽ๏ฝป๏ฝฅ๏พ“-่ฌซ๏ฝฉ๏ฝฅP??ๆปฒๆฎ‹๏พŒ๏พ™๏ฝถ๏พ˜?๏ฝน้–พs!๏ฝซ๏ฝฌ๏ฝฑ?)๏ฝฐ๏พŸ?? <๏พ“fโ€˜๏ฝต๏ฝซ9๏ฝทๅฟฟ๏พ‰๏ฝช๏ฝฑ?\"2๏ฝซ2?่ฏ??\0c?/,๏พž?-1๏ฝง\0I??)Ok?;\rhTP65?Mr๏ฝก4?1๏พš๏ฝป??\02IZ!๏ฝก๏พš?W๏ฝฑ๏ฝน\']?QๅƒŠ?j็•‹๏พŸ?็‰ด๏พ“NAp๏พ‚\rไฝ†?๏พ‚mN๏พ‘็‹ƒq^PH??7๏พ‡๏พ‰๏พ•?$zR\n\ZSj?ไนพ%ๆ•?๏พ๏พˆ๏ฝผ๏พš๏พ‹S?Y๏พ„๏ฝฃๆฎคN?\0??+ไพ‘๏ฝธ? ๏พ‚Y๏ฝกะฎ)j?H)???\0๏พ…X๏พŸ?#ไฟพ:็žฅ1๏พไธผA๏พ˜4?\0??้‡ผ[?1ๆžฉN(a๏พ—???\0ๆธŠ๏พŽๅดZ๏ฝฝ? ๏พ’?ๆนฏ๏ฝฟ๏ฝฐ๏ฝถ๏ฝต๏ฝธ๏ฝถ๏ฝฒ,๏ฝญ P?่…ฎ=do่œด_๏พ|9Ei๏พ€7\0ๆ”ท๏ฝฑ?๏ฝฒF๏ฝธ?/@H?20 vP?๏พ;Z? ๏ฝนxใ‚ฅ๏ฝง้–‹๏ฝฟ?่œ‰๏ฝช๏ฝฌๆ‡Š~๏ฝฏ๏ฝค7๏พšc?-j}้งญ?๏ฝฝ+๏ฝฟB?$๏ฝธ\n๏พž้ดˆ%?!๏ฝฃ\0@<่“‘๏พ€?\0๏ฝท?2bD?_aRMLj?๏พŠๆฎ:?-Hjw V,๏ฝญ _???๏ฝฒ?๏พ็›ด?K<:๏พŒ็›ด๏ฝฉ๏พ…?z๏พ9๏ฝฉๆƒ“#๏พ‡$QC๏พ‰KๅŽปT๏พšๅฟธ?ๅค‰#() ๅญต?ๆง็ฉฟ๏พ??๏พ‰=๏ฝผm\Z๏พ„๏ฝต%๏พ‹??\0\nๅฎ4๏ฝข?๏พƒ(Q *๏ฝตJn(>๏พƒ๏ฝซๆŸฏ๏ฝฟ๏ฝนๆก6ใ‚ฉo๏พŸ๏พ๏พ†๏ฝทJO๏พ†?????\0,m๏พ๏พ›?s่Ÿ‡๏พ\n๏พ˜๏พ˜j.็ฏ‰ๆ‚I5CW็ซฐ่‘บ?Q๏พ‰๏ฝฐK๏ฝฝๆฟถ๏ฝช๏ฝฒ๏พž๏พœU็ฝฎH๏พD๏พ‘๏พ‡๏ฝซ#|_?8?;??๏ฝป๏ฝน๏ฝซ1x๏ฝฏUE๏ฝผk๏พ•\\*?\0y?๏ฝง๏ฝญr!R5่ฃ…[๏ฝฑ๏ฝก??NH๏ฝผ?๏พ‰q2๏พœ๏ฝด$q||zr#?Yl๏ฝจD๏พ„s๏ฝฆE่ –?ๆฌง่ฟ่ป›๏ฝฒ#]?๏พŸ\n๏ฝผ?๏ฝจ๏พŠ๏ฝฑ้ดƒf?ๆ˜Ÿ@O?๏ฝซ็ซฏ๏พ6[]๏พŽ-?ki๏พ–H๏พ•?6\n[????Y๏ฝณ??๏ฝฆj?๏พ‘L๏พ”W็ง๏พ“้ฃพ๏ฝฅl๏ฝฎ)e๏ฝฆๆl็“ฎ็ด$\'้ฝ‹!๏ฝขdT?๏ฝด??๏พ–L๏พๆทน? T้‚„๏พŽ๏พ–\n?1?\Z@w๏ฝก?&๏พ‚๏พ—ๅฃฅ๏ฝขa๏พ๏ฝฝR?๏ฝญ~/?๏ฝซๅ„ผG\r๏พ@้Ÿตโˆง๏ฝฎYCv%K๏ฝฆ??*?๏พ—้š•.๏พ€\\8B๏พ‘@๏พ›๏พ›?,ๆฆ‚๏พ่’ก๏พ๏พ’๏พˆkSใŸVๅฆน๏พH\0}aโ—‡&ๆญฏ?็—‡\0๏ฝฏ$๏พŠ ?-T๏ฝดL๏พ‹!M:?๏ฝณ้ชธjf41pๆ‡พ?๏พ“ =M๏ฝท๏พ‹F๏ฝฉ๏ฝจ?็ขŒej๏ฝท,J๏ฝช?๏พ”88๏พžW๏ฝข้‘‘๏ฝฎ>Z?w8a๏ฝก้ถฏjRIm๏ฝฌlQๆƒถ?/?๏ฝง%๏พˆ#ๅƒต๏พ€็ช—ๆฅฎ๏ฝฃ@??๏พ‡K?่œ‘ไฝ†๏พHx?)Z๏พ—๏ฝพ&๏พƒ*๏ฝค๏พ›็จท1C๏ฝถ0๏พ“๏ฝป๏ฝต1ๅนก;๏ฝก๏พ‹c๏ฝถ๏พ˜Ubๆšƒz D\nc๏พ†8ๅ„Ww๏พŠ๏ฝฆๅบธ๏พŒ]2*๏พ–l๏ฝผ๏พ€b๏ฝญ่กฒ-็กฒ๏ฝก?๏พ˜E๏พ— ๏พŒๆขLh๏พBi?.5P็บƒc๏พ‡ ๏พž๏พ†9๏ฝง?G?N{๏พ“ๆฟฌ~๏ฝง่œ?&15?๏พ•๏ฝท\nXs๏ฝก?}๏ฝผ\0่‡ช๏ฝข็™‚\ZI๏พŠ\\+)\0)??_??2Z78๏ฝซJๆทณ๏ฝธ\Z:S?oใ›๏พŸ?๏ฝฃ่†ŠW๏พ‹๏พš[[It?B้ ท?$๏พ&๏ฝฅ>๏พ“7๏พ€๏ฝน๏พ‹+?๏ฝฃ๏พ„) ๏พ’k?dkๅกฒ๏พ•่ˆL/+๏พ?๏ฝฑ?=q?็ทค??๏พ›A?r๏พˆ็ทฉ? (@?็‹‚\nๅด–?๏พ?wU๏ฝฌ(}?๏พ‡6?๏ฝตp+?8?u๏ฝฆ]p๏ฝซ|๏ฝฑ?:๏ฝน๏ฝ–4P?๏พ—TS่ฏ็ถŸ48๏ฝฃ๏พŠ?1?0NๅฒŒ\rBoD๏ฝธBU?\'๏ฝฅTr??๏พ‹๏ฝญT?8?W๏ฝธ}??|c๏ฝจ๏พ€๏พ’GC?*่‡‘M?๏พ๏พ›๏ฝญ2้ฑ‡_๏พ‰w๏พ„๏พ‰๏ฝฎ4๏พ—(\Z่จ“๏ฝน[C\\Cไบ‚\"๏ฝฃ>๏พ˜๏พ’๏พ•8็€ฒ๏ฝด๏ฝทCๅžช?๏พ’0*๏พ’p~็ด ?๏พŒv\\๏ฝธ๏ฝฌ็ฝช๏ฝถ๏ฝฆhvๆ›‡\\๏ฝฉ?T?Lๆœˆ๏พ‰vo๏ฝฉ)??yJ@Y\rjG? -?/๏ฝผ๏พ2๏พ›Y?๏ฝฆ่œฟJ{็จ๏พ“่กฒ?๏พ…?2๏พ”K่‘กJ?๏พ๏ฝตMw๏ฝง??*1S_ ็ถ^g1้ด’?๏ฝฆ3๏พ„?\'?9dT๏ฝตpI6่ปข?SPp๏ฝก ๏พ†?Yb๏ฝบๅŽš็ƒŸ??๏พ–B<๏ฝฟ???f?>W ่‘ฉ??๏พ‰๏พ€?\0ๆ••]8ๅœœฮ—NBQ&๏พ‡Dใ‚ญๆ“ฌ๏พ—?7?*? ?=๏พ†D?I่…ฆ9?๏พŸ\'?๏ผฎ็“ขL๏ฝน7ๆบ=\r)๏พŸlejp๏ฝกya๏พƒn๏ฝธ??X๏ฝฅ6๏พ„ๅ€ŸUS๏ฝต|qๆฎ€๏ฝฆ[H๏พŒ? ?็€‰gn๏ฝธP๏ฝด๏ฝถ?\"๏ฝนbF?\r๏ฝบ็ƒ5๏พ‡\r๏ฝถ๏พ€U๏ฝถ$?๏พŽ)๏พˆLๅฝ๏พ™je?6ไฟ,๏ฝงUlw่•ญ๏พ“?๏พ€??\"@้ด†่’I?\n๏พ“#4?2=UD่ฅ๏พ›๏ฝฝr?\0็”ผๅฑ†๏พœ1d็บŒ?: UD๏ฝฏ||S4f?๏พ่žฝ๏ฝฎ4้ˆŽE?Dๆซ›B้ซช๏พ“?-u2๏ฝฃใƒŽ?0๏ฝป๏ฝฃ๏พƒ*?(ๆข›Hๅขƒ๏พ“.๏พ„W๏พŸ๏พ‡?่ˆœ\0?1?๏ฝผr>9R?ๆe?eG?๏พƒ8n>๏ฝต@\0Pl้นฟI๏พƒ๏ฝซHU๏ฝญ๏พ‰๏ฝฏ๏พ‡B\0?๏ฝฒ๏พ„c้ …๏พ„?๏ฝฅ_E:M?๏พ๏พ—W?!?้ซ‘=)ld?๏พš๏ฝปq๏พƒKๆŠป7๏ฝชๅ ‚๏ฝฎ๏พŽ\"F๏พƒ?*w?\ru,b่ฑนU?,8?๏ฝถ^Jv๏ฝง?\0๏ฝฝ\"#๏ฝฐ?๏ฝถๆฝ›Tc๏ฝน9Q2?#๏พ‰R?$๏ฝง\"๏ฝฃf~๏พŸ?๏พ†็ข†่ฝคj??P๏พˆG?๏ฝฏ๏ฝง?\"ONDS^$๏พๅ€Ÿ๏ฝฝ?๏ฝต๏ฝช#F๏ฝค & ?{S็ญด?(J๏พ–๏พ‡u_1[I๏ฝช๏พ›๏พh?\"๏ฝข?๏พŸ?่ขHO๏ฝซ๏พˆ๏พš?\r๏พ‚r็ขŽๆฝŸ?๏พๆ‚ต F่ช˜K(ๆŽz๏ผ›๏ฝพ?\0?t? W?JJ๏ฝฒy?9y<5Mๅ‰ƒ๏พ๏ฝฎ5 ๏พ›๏พ™y,็ข•1$*ๅ—ฝ๏พž็ฉถ๏พ’k๏ฝบu?๏พ‡?,?๏พŒ\rC??_i๏ฝชiZx๏ฝปi?2๏พŽ๏ฝฒ๏ฝซ?\0๏ฝตo๏ฝต๏พ‡\0h/???A<7๏พž๏ฝฟ?H๏พ‘้†ตๅฌฐ>I?ๅœป?z๏พšx๏พ’e$o\n}๏ฝฉ?๏พ‰๏พ‚?]่ณ๏พ”๏พŒz๏ฝช๏ฝฌ?็ฏTt??>?}*?\0?4z?๏พ›๏พ๏พž๏ฝซ๏ฝท?๏ฝพ้€/?๏พ™้ฃŸ๏ฝฐJ๏ฝผAๆ’ƒI??\0็€พ???่ซบ๏พ‹๏ฝถ?:u?+na?q]??F\rๅชš๏ฝผ๏พ–5w๏ฝฒ?\n๏พ‚๏พœ๏พž&็ฏฉ??๏พ‹๏ฝณ๏พ›๏ฝข&?่ค“k1C@?S่œฟ3๏พ›yq่บฐ่ช‚๏ฝฎ๏พŠ๏ฝผK๏ฝธ๏ฝฉ?\0d๏พ™Y?6Xใ€œ?๏ฝผ๏พ€?้ฆ˜็ฐA๏ฝซ๏ฝฐ]๏ฝพ๏พ’๏ฝฎ!๏ฝฅy็ฆๅฎฎ?B?}๏ฝฅ๏ฝฎG?๏พN็—‚ๅC=%๏ฝญ?๏พ™a?\0๏พ”l[N\\+๏ฝธ๏ฝง๏ฝงฮถ?\0?0๏พ™?๏พ™?ๅ—…,/๏ฝค_NๆŸQG้‡ˆC il๏พ„้ฎฎ*4้€นM๏ฝท๏ฝฒใ‚จ๏พŽ๏ฝซ๏พ•??\0๏พ˜๏ฝถF#๏พ’ๅ–Šr๏พŠyๅ†ถ๏พ‚๏ฝฟ?J๏ฝญ i*?\"\\j๏ฝบ\\7K?-?๏พ?๏พ‹\"?๏ฝฅ๏พ’?็พ?,๏ฝฑGg?้ฌฎ\'.็ธ…+ๅง“4?6๏ฝจ๏ฝซl6 ?;d๏ฝนH๏พ™1?๏ฝผๆ‹‚ไปฒ??\n๏ฝต\'?:<0๏พ†?1๏พˆ๏พœh??4EENnI!๏พ‡๏พ„6Z็ฅ๏พ‡,LWไธฑP?^?w๏พ?F๏ฝฏI?๏พ‘๏ฝบ\nๅขŸ???<โŠฅ#๏พ…๏พ’ๅฒ”r1v๏ฝฏ|sT็ตฃ?5๏พ๏พ‹li\nj๏พ‡.Oไบฅ*๏พ“| V?W.๏ฝง?8?0๏ฝจ๏ฝฆ8?๏ฝฃ๏ฝฐ๏ฝซv๏พ„๏พ‹q?\'pv8?๏พ†?๏ฝฌ\nๅผ–๏ฝต\ZMz่คj๏ฝฟLR๏ฝซ๏พˆ๏พ’ๅƒ‰bf๏ฝง|?๏พ˜๏ฝก{\Zf็จ˜ๆ…Ÿ8๏ฝฅ?*S*๏ฝฒ??j๏ฝธ?)๏พ่‚˜?T๏ฝฉๅ›ˆ๏พ‹&๏ฝน๏ฝซ\\*็‘๏พ๏พ‚q๏ฝผ๏ฝฐ๏ฝกX? ๏พŒ\Z๏ฝฃ\Zv๏พ€๏ฝซ๏ฝซ?+๏ฝฎ?1V?๏ฝฎ๏พ™@Sqๆฝ…^L๏ฝฑ\'๏พšๆ›นๅพ๏พ€R๏ฝฑ๏พ™I?2๏ฝกN/q๏ฝฃXi\"1 k?r๏ฝธk\nๆ„ฌ;่››็ฃp??!Q?1๏พˆ?๏พ‡\0W๏ฝฎX๏พ•๏พŒv๏พ‡u๏พ๏พƒ๏พƒ๏ฝฉ๏ฝฒ?8็ญต{eR๏ฝธ๏ฝช๏พ…?ๅทฎ๏พ†๏พ…S}?*๏ฝธ=F๏พ˜ๆ‹ z็ฑŒ?1&๏พŸ๏ฝฎR8๏พ“?8๏พ€w๏พ‚?็žญb๏ฝฌ6๏พ†?๏พ“๏ฝฌใƒฎ?&ๅ‡ฐ ็ฏณ?j๏ฝฐ@GLc!8(ๅฅจ#็ตถ๏ฝฎiAz|r๏พ‚?)๏ฝฃ็˜‰็ทฌZ๏ฝซๆ–Z๏พŸ๏ฝธ้ซฏ?6?๏ฝนๆฐด็ƒฑ\0??\0g f#๏ฝน4๏ฝป? R๏พQ?๏พ#.??t*OA็นž?8?mvPX@๏ฝฏ.ๅ‰k๏พ›3๏พ‹]๏ฝฑ\"?\0~L๏ฝช??1๏ฝฆ0M3๏ฝฎ,+Z๏ฝฏ้›…?๏พš้ก•่†ฟ[?1?#๏ฝก๏พŸๆ‰‹๏ฝฅW๏ฝชๆฑ๏ฝนE?ๆƒฐ?;??q๏ฝฌ๏พ•5๏พ…=OM๏พŸ?hC\Zk?>?!ๆฒ–?๏ฝธ๏พž?S*ๆ–‘Vๆ‹ฎiๅ™๏พ8+F๏พœ?\"?1Uๆ–}๏ฝฑ๏ฝผ็ฌ ๏ฝญ๏ฝฑ?๏ฝธZ^e?๏พ”T็พจ?๏ฝฎ*๏ฝผ๏พ— l๏ฝตๅด•๏พ‚\'<Q?่คช๏พˆ?5๏ฝถma้จ-!ee๏ฝฌ็•‘>?๏ฝจ??P๏ฝฒ?$\n|;dh\Z็ฝ ??.\"้Ÿฟ๏พ”$๏ฝฟ\n$?้Š‘Jb๏ฝคc๏พ‰ใƒผ.cๅˆฅ๏พ–?0ๆ„ผ๏พ—\r*๏ฝจ>|r?ๅ‹‰[๏พ†๏ฝง0?;็ธฒ?sใ€‡่ทก๏ฝซJf F็ทฒ๏ฝฒ?3|;b๏ฝซjkS?#๏พŸ๏ฝฎj็”„๏ฝท๏ฝฉ๏พ‹,?+๏ฝค๏พb๏ฝฒ๏พ“?\nๆพ†๏พO่ ‘๏ฝถ?๏ฝฝๆ™DfB๏ฝช|,๏ผSๆI๏ฝฟ๏พ’?i็ซก็ ŒK8่ตคไธ”<9;?๏พ€็ บ๏พˆ๏พ’๏ฝฅ)?,๏ฝผc+๏พœๅคช$ๅ‚˜๏พ—+ๆชข่›ปM<๏ฝนw?B&= \0~Y๏พ›๏ฝน๏พ†?)?๏พ๏ฝฑHba\"?๏ฝฃ%\Z/?.-d็ธ’๏พœ็ถœ?H๏ฝธe?๏ฝฝ๏พ่‹บT๏ฝฌ๏ฝค3๏ฝถ?OqcๅตฌU้‹’?Sqๅ–‹o๏พใ‚Œ๏พžH็‰ฉ๏พ‚)็˜ฐa1U?\'\"RJ๏พ†<๏ฝบ ๏ฝฅ;?8?๏พŽ?๏พ๏ฝฆ๏พ๏พ๏ฝบD๏พ›o๏พ“.๏พ˜0Aๆฏ’๏ฝน.๏พ™,?? ?%๏ฝค๏พ€\0๏พ†โŠƒ?+4/ Q๏พ…2็ธฃ๏ฝฟ?0๏พœS๏ฝข$\r=?J๏ฝถ๏พ‡็ถข๏พ—๏ฝถ๏ฝก\ZFjOol?2j๏ฝณO๏พ„๏พ„ๆฒพ9?r๏พŽๆŸ”้™ข)?. ?ๅ‹—?๏ฝด็Šฏ๏ฝป?(???ๅ™ช\nIใƒ’?,\0T๏ฝฉ่ชฟ๏ฝธt?x๏พƒ\"ใ‚ญ.๏ฝพ๏ฝผๅ‹บy?๏พ›\n๏พ†๏ฝฒ?N๏พ„?Y=๏ฝผ?JA?๏ฝคuj็•‹8\Z๏พŽ๏ฝฒ|k๏ฝฝG\\๏พ„๏พ–ๆ•K๏ฝฎt?9]๏ฝฆ๏ฝธJ??๏พ“๏พŠ?๏ฝฝ๏ฝฒ?๏พŸ??๏ฝป+!S๏ฝฑ๏ฝฆG? ?่•ญS~๏ฝง๏ฝฆJ2 ๏พ˜A?OGๅง™?๏ฝธ\'?็މ?๏พ› Ou๏ฝฅh๏พ•??:?๏ฝคV๏พ—*?Zๅผฑj?๏ฝช๏พƒso?๏พœ๏ฝซ๏พ“๏ฝฏ:๏ฝฎd 5l}๏พˆ;?๏ฝฉN๏พ‘๏พ”๏พ”๏พœcm๏ฝฏf๏ฝฒR๏พ๏พŠ7?8?1n๏ฝฆ๏ฝธ๏พŒๆซŸ,QOv?\n๏พŠy5z?e๏ฝซ๏พ‰๏ฝณ๏พ˜q$?aH๏พ‡ใ‚ฎ๏พ†F๏ผฎ8}$๏พ†๏พ๏พ‚?๏พ’๏ฝด8็ฃ๏พˆ\\็‚บ็ฃ”๏พ‚?$F่Ž…j:o้ก๏ฝฅ#๏ฝฏJๆช๏พ‘[\r๏ฝผK(่‰Ÿ\r๏พ€?Z?(ๅ€นQ๏พ‹๏พœc?l๏พ”$๏ฝญ(๏ฝญk๏พ›+๏ฝฆ=O็Œถ\Z๏ฝฝ๏ฝฒ*๏พ”u๏ฝฏ?ๆ“80l๏ฝฆ๏พŸ^?#๏พ„็ฒฅ๏ฝง๏พš?s๏พŒJ?\0ๅฏ’๏ฝง๏พ›p๏ฝด?ๅž“\n+?1Y?๏พ–๏พ‘[,j๏ฝพๆŠ‚!Z๏ฝฑ?๏พใ€๏ฝง\\่“‹n๏พ›\r?l|rไฝฐ%้ตž~๏พ˜?0๏ฝช?4๏พŠ$็ท๏ฝณ7\\P?่ญฏc@*Nj?ฮฉ๏พ‡๏ฝตM๏ฝจz็ด•่คถ๏พŸViM?๏ฝกDbๆœ๏ฝธ?LUzๅ˜ด่ขฎ|๏ฝฐNE.9c๏ฝฎc?0*?๏ฝง|c\Zf5)๏ฝฑU๏ฝง5+?-F*๏พ•{eSz็ดต๏พ…[๏พ๏พ›*๏ฝนU๏พ…]Jๅฟ–8ๅ—ฝ๏ฝฆc#2?\'aR>ๆ„†๏ฝกi๏ฝฝj+ไปr๏ฝฏ๏ฝถ)uo? |ใƒ\rGCQ๏พ‹๏ฝฉ5?๏พœ๏พŠV?kM๏ฝฉๅงฆb?๏พ“่ณ๏ฝปc\0๏พV1๏พ„๏พ’?๏พž%#???(xay่ณ‚๏ฝซ?)็€ฌQ๏ฝถ8๏ฝผ๏ฝฌไฝ“Z๏พœ? ?v๏พ€๏พ‡็ตฑ๏พN\\?ใ‚ถ?2๏ฝฝ&\n\\nS?Vๆฌฝ?R?16?-๏พ’_R๏ฝฅ??U+$WzQ๏พ‡KrpT{Qใƒ“๏พ€?\n\Zๆฃ˜j๏พ”5๏พ„๏ฝช๏ฝด?/๏ฝฆๆฅ• ZW๏พƒ๏พ–?2??๏พ€E?๏ฝฏZ?๏พ–๏ฝฎ\0๏ฝซ๏พ˜t ๏พ–๏ฝฟ?e๏ฝจ๏พœf=1W?$f็ซญ๏ฝถ๏พ‹@v?\\@b๏ฝฉt้…ณli๏พ‡๏ฝฝ๏พ’๏พ–??%๏ฝป๏ฝฒx๏พ>๏พ“?a??๏พ‡#R?\r|*z7?ๅถ๏ฝฝ๏ฝพ? B๏ฝด?ใƒ.= w?ๅ‚ณ้–‰P็ ด๏ฝณ??T~gๆ™‹o๏พ—่‘Ž8ๆฒก8่ช…~C%๏พ‘ ๏ฝถๆ“ฝ\\?B๏ฝฃ?8q??๏พŒ๏พŠ25๏ฝฆM๏พŠERhi?\0๏พ‰ ๏ฝฎ๏ฝช๏พ”\'\"R}j^E{n~?็”ž?xๅฎ•Z๏พ‚?&\nw๏พ‹ๅˆ„t๏พ…T๏ฝณf๏พๆฃบๅบง๏พ—?5?*?7U๏พ€?๏ฝฑๅŒˆ๏ฝฅvl๏พ™๏ฝฑWf๏พ?vl๏พ™๏ฝฑWf๏พ?vl๏พ™๏ฝฑUX๏พ”i๏พ™๏ฝณ+q๏พ†๏ฝฑ๏ฝฉ๏พ…U?6๏พ„๏ฝณf๏พ…]ๅ›—*๏พ…่Œฑ?๏ฝบ?F?๏พ‡?๏ฝฅJ3f๏พ?ๆœช๏ฝนX?48๏ฝช\"(๏พ˜o๏พ›?)N?\\\0)?\rMraๅ‹G?\"๏พ€้šŠ๏พˆ๏ฝฒ?I\r?Eฮ”๏พŒ?8??&6#๏ฝฒ8??Mz}๏พ™#m๏ฝก=7?28{?? 9:2๏พƒ๏พ•e๏ฝด-\"๏พŠ? ?๏ฝง่˜“<๏ฝณ๏ฝฏ?:5๏ฝบ๏ฝด๏พ“le๏ฝซ๏ฝฏ% ๏ฝญ๏พ“็ถฃ??i๏พˆOๅฅ?5#}l๏ฝผhm$p\r*Jๆ–?\0๏พ‰ไนฑ๏ฝฆ??๏ฝฏ?็ฒ?๏พ‹A\'%?\0?12ๅฒพ๏พœ่˜‚้™๏ฝถ?ๅฃซ?\Z๏พ.?๏ฝฉ๏ฝช๏ฝฆ ๏ฝผo๏ฝซ๏พšI31?่ฏPmU?\0+??๏ฝฌ?$M8F?\0๏ฝก V๏ฝง๏พ™?๏พ—??๏ฝปๅ ™J๏ฝจKIu8Uๅฎ€๏พŸo?o๏ฝณk๏พ‰๏ฝต]T]\\๏พ›๏พ‡k?3I4ๆทก๏พ€๏ฝท??\0?#๏พŽ๏พ…่‘ฎ้ ทๆ›–\0?}?@?=่‡ง?RC?\n??\0?๏พ‘?/๏ฝต?๏ฝด{A็Žณv?]ๅฏฐNcm??wะข๏ฝฝ1S๏ฝฝ9๏ฝถ?[\Z๏ฝดaGE๏ฝฏ๏พ?(๏พ™[$๏ฝฃT็ณพI้ฌ†๏ฝซ?\'~?\0่—บๅผ—~ๅฏง๏ฝง๏ฝจ๏ฝฆkๆกŸ4T4-\"๏พ”?_?็šฐ J-z็›ธ๏ฝช๏ฝฐzaF๏ฝค๏ฝฑ๏พ…u\r๏พ‰๏ฝฐ๏ฝคๅทฎ??่ด–6n?๏พ๏ฝง5cAN 7?8๏ฝช ?H ๏ฝปN) ๏ฝฑr,๏พ๏ฝช๏พ†>๏ฝซY๏พ„ๅ””็™Œ๏พ๏ฝจ?+็ฏฉg๏พ”๏พ?\Zg๏พ•l?\Z5ePk๏ฝท5t??็ฌŠe?\0_\n๏ฝฟ15d๏ฝณ๏พ’?๏ฝฐ๏พ็ฝซ๏พ’4#๏ฝจcV??๏ฝช?\n๏พ๏ฝฏ,?่Ž ๏พ–่ฆฆ]ๅฃฅ.f๏ฝฒpOC?y๏พŒๆคฅ?๏พˆๆˆš[??Px๏พ›??w?ๅ๏พ•่—ชA๏ฝต7ๅปฐ๏ฝทไพƒ0?B๏พ‰so?\0๏พ‡|๏ฝน่’Ÿ๏พ’5ๅฑ‘+๏ฝจ?)๏พ–I!๏พ›๏พ“?๏ฝผ?๏พ˜e๏ฝขT$dmo\\๏ฝด?ๅฐ…้šท๏ฝฎB๏ฝฐ?=8??\'๏พ?=\r๏พŠ่ถX( ???\0ะ๏พˆ๏ฝง? H็ญ‹๏พˆB๏พ†๏ฝถ๏ฝจt๏ฝก่–‡m?๏พ?$wI$6?ๆฒ“D#ๆฝŸ?๏พƒ?๏ฝฒ? ~ๆœ›W?\'๏พ‹็จพ๏ฝญFF?\0?Ft๏พ‹?>)็ต?๏พ€ใ‚ฝๅŠ*xๆ˜œC??jx่‘ทE่ซทiZ?(r%/?๏ฝผU/๏ฝก\"๏พ“t๏ฝฝ*๏พ†๏พŠ[๏ฝซ??9\"OR๏พ„?Go๏พŠ๏ฝถๅทก๏ฝข๏พ‹๏พ‚o??\0Kv??๏พ•๏พๅ„บ?ๆดฒ๏ฝฑ?n4?#๏ฝฑ-?$? ๏ฝฏ๏ฝฐ?่‰จ๏พŸ่ขˆ๏พ‰?cUhu8ๅŸ?๏พ†?่–จ๏พŽA?๏ฝพs??๏ฝต๏ฝนz?๏พ4)๏พž๏พ‚่‡ๅตฌ0๏พŽ??>๏ฝน?;?๏พ”้–ขw6p๏พœ*3๏ฝฐๅฃฏ?\0่Ÿl???#?>? ๏พ:๏ฝฆ~F๏พ–X็›–S;:D๏ฝฑ๏พ‰๏ฝน๏พŠ๏ฝฎ??\'ๆฅฏๆฎ๏พ†้ž๏ฝซ?=\Z่—พ๏พ‘๏พšKั‹hๆˆก\n{ๅฟ่‚“?q๏พŽd๏ฝฟQum0Gๅธญ? ?๏ฝธ??qV็Š * P[Z๏พ„?็•M\Z๏ฝฏ ?2่“ฟ{้ฃฎ๏พ…๏พ‹e u๏ฝท๏พ„^?๏พ—lๆ ‚[๏พƒ๏ฝงๅ…?-๏พ„yf๏พ?r?:ๅฅฎ?3x-\"ๅ”ณt?;u๏พ๏พŽ๏พž๏ฝซ\Z5?๏พ–f๏ฝถ๏ฝด){&๏พœDU@\'๏ฝธ๏พ€9๏พ€๏พ‰๏พ๏พ–๏ฝท^?r4KXu8T]G๏ฝต๏ฝท@?b๏พœ๏ฝป4E?M๏พ+็šƒ๏พš?๏ฝถ1aๅฌ‹๏พf9$๏ฝท๏พ—??g๏ฝคE ๅนตp?ๅŽ˜\n่ชฟ๏ฝต้…Œfr๏ฝฟๆ…ถ๏พ’๏ฝฐu๏ฝฝb๏พ‡MVๆฒธI0?๏ฝผ.๏ฝฆF ็’ข&๏ฝดZE?\rๅธฅไบ›???Pi-} ๏พ‡ hF๏พ“?=^Jh??%๏พ๏ฝญ๏ฝค๏ฝขI1่Žvๆ–น?๏ฝบZ๏ฝผ??1?#ๅผƒl??็ชฎ๏ฝง๏ฝฏ\"๏ฝฝ๏ฝท๏พ”w๏พ+yF๏พ‹;?Tj๏ฝค*๏ฝบ๏ฝฝ้จจ#๏ฝธ1ๅพจ\rn_?ve๏พ’๏พ—W๏ฝถใ‚Š๏พˆ๏พŸ๏พ€N๏ฝถ?\'๏พ“๏พŸ??๏ฝฉ๏ฝง้–ข็–ธ?D๏พ–?๏พ‚ๅผพ)8S้ <่€™ๅก‘OB้„nๅŠพ๏ฝฃ๏ฝต่ช˜๏พ“ฮทo๏พœ๏พ?8้‚ฏ~??T?๏ฝง.m๏ฝฆdX.J้ฃœ?<๏ฝญ?๏ฝฉ๏ฝซๅน•๏พ–๏ฝฒi๏ฝบI๏พ’?ๆป‰^M๏พ’B๏พ’.n๏พŽ3๏ฝท {๏พ–u?๏พ›K๏ฝจ[้ฝฌ?\r๏ฝฝ๏ฝจ้ ƒ)ZEa๏พˆb๏ฝน๏พ€๏พŽ}8็ฏ}ไปฐๆถธ๏ฝจ??e๏ฝธ๏ฝธ๏ฝฒ๏ฝณ๏พ•LSA๏ฝฑ?ๅกž่Œจๆชฃ?5 ๏ฝฆ?๏ฝซifไบก๏พ…๏พŒ\n\nbAฮง?\0.}๏ฝซ\'๏ฝฌzๅฎˆ๏ฝฉ-,๏พ–+h๏พ’;x?$??๏ฝฝ+N2r๏พ˜M$E้–Šๆฐ”3%๏พ๏พƒ??&b|๏พŸ~?[๏ฝฅ?๏ฝช?V๏พ›๏ฝตO$?๏พš๏ฝฉO๏ฝบy#?bdrBๅ…ƒ๏พ€๏พŽ๏ฝญv่–ฌi๏พ’E๏ฝง๏พ„[?\0m;๏ฝผ3???;้ฆด๏พš๏ฝผ?\06ๅนธ๏ฝฆ๏พq๏ฝป,๏พšF?ๅฟฐq#*ๆกง?๏พŽ>???-k่’ŸฮทLF๏พv?7? ?=kๅกน?6๏พŸ?\'ๅ“‚?? }}~?๏ฝจ๏พ่Š?9e\n?(\0๏พ-?%?\Z?:\r๏พˆ่จ€้ซฏ๏พŽ2?๏ฝฝjn๏พš??้ถU๏พ€๏พƒBๆฟฎ?s?๏ฝฉl๏พ‹$M\0\n1 #\0?}๏ฝซไพฏ๏ฝท? ๏พ†๏พ‘๏ฝฑl,๏พ‘๏ฝฎr}๏พˆ๏พ#??D๏พ“6๏ฝกm$๏ฝฑY๏พž๏พƒ J๏พ‚๏พŠ +? ่พบ7้ถธKmlWj?6wz\rb๏พž๏พ…p๏พ’๏พ…,๏พ–?c1๏พ‹ ๏พœs๏พ›=ๅฏก๏ฝถ~๏ฝฝ๏ฝซ l๏ฝตkw[๏ฝฅๅญฆCA O๏พ—๏ฝทc?c่พฟ๏ฝฅ\"ะ 9?\0๏ฝท?ไนพ?๏ฝช)hR[u-๏ฝด๏พ€๏ฝฑ??ๆกพ7๏ฝญC c๏พ„ไพฟeRๅฐ?ๆจ”ๆˆˆ#?b?%?\0Nnๅดฉ?\0ไฟ˜zๆˆŒ?1]8?-?Q?๏พž+๏ฝถN?8๏ฝฏ๏ฝกF2๏ฝน?]E,๏พŒ๏พ‘n6?๏ฝป๏พ•ๅ†ฒ๏ฝฃ๏พ%?s?ไฝž๏ฝฒ่šถ?็ž๏ฝฌP๏พ€Ll๏ฝฎ8?้…ฒ\Ze็ฏณ็ดUbxc๏ฝดๆตฃ๏ฝก๏ฝฎ๏ฝต}๏ฝญ๏พ†C)?>๏ฝต?๏พi(?>S?๏ฝฎ๏ฝจ?P๏ฝฌ2๏พ€c?๏ฝขl?o\n่˜ฐ\0q??๏ฝคQ#yNๆพA?\0P?\0z๏พ†ไฟณ๏ฝทl/?ๅคฅ๏พ“๏พ™๏พp8S?๏พžใ€Ž??_?-๏ฝบๆ—บๅค‚L?6๏ฝด๏พ”๏ฝญ?+๏ฝพH?่‡˜r๏ฝฒ๏ฝซ?v? M~้€ฃ,S๏พ‚้ผŽ\"K?e# ?;ใƒ€ๆฒŒๆข๏พ>๏ฝค?\0Z??\0??=๏ฝญ๏ฝฏ%?๏ฝซ๏พŠ๏พ†9๏พŒ้™ฝ+ๆ–›๏ฝต๏พ€/4๏ฝกT?๏พ’\0๏พ่–—K(๏ฝฎO#?x๏ฝฟG๏ฝฑiJW!qJR?R็ฎฑ๏ฝฅ()JJR?R็ฎฑ๏ฝฅ()JN?๏พ•๏ฝฟ?\Zt$ ๏ฝก๏พ‹\Zu๏ฝฑ)ใ‚ฐg?8?Y๏ฝฐAV๏พš\n๏ฝจ?NW?[5?m๏ฝฝ๏ฝธQ็„ผj๏พ‰?๏ฝฎo๏ฝพ)?๏ฝฝ้ฝถ๏ฝตX?|๏ฝฎ?๏พ€๏ฝฆ+Tf(๏พ”๏ฝฑ,๏พŒI\'? \0&?\n๏ฝฐ?.|.#_c?๏พ{?\0N?๏พ‡?9sN๏พ? ?๏ฝซ,้Š€๏พ็ฎช๏พˆ=๏ฝณ?๏พ,?ๆŸฏ๏ฝผB๏พๅทฝ\'\n\0??\0J๏พ€\\๏ฝท3๏ฝฑ?(?9๏พ†>?๏ฝฐ?3๏พAๆก?๏ฝถ๏พŒ?๏ฝฏQ๏ฝช10?๏ฝถๅ“ฎ\'๏ฝถ?2?3P=Ns๏พ‰=???kc???enm่ฒฐ๏พœ้Žฎx๏พ‹่“๏ฝพ=๏พ๏พ˜TwI้คะœ%๏พ?+n้ฆ™๏ฝผzๅ—=jWS๏พ–็ฑ็ฏถ๏พ๏พŠ๏พ‘eT(\"!ๆƒน้„™๏พž๏ฝน๏ฝฒ๏พ‰๏พ‰?๏ฝขไบ€??2H?๏พ˜?8๏พš๏พŽs๏พ‰๏พ˜?^??^?้ฏฒn๏พŠ !T{?j\r๏ฝบ??\0๏ฝจo๏พŠ๏พŸo๏ฝฉ๏ฝฟj? r>+?๏พ”๏ฝฃ๏ฝน่ฆ†k้™Ÿ๏ฝถๆ–๏ฝฑl?้‰‰U?ๅŠ?+>๏ฝฏmp$y#H?&;D?4ๅถ8ๆบ\\4๏พ™่ฒŠ๏พ”๏พ…ๆขฆg๏พŒw?}y&?z#๏พœ๏พŠ็€ฌJ๏ฝค๏พŽ_๏ฝธ??๏ฝฑM๏พ‰๏ฝธ/o4?ไธฆa??*?๏ฝฒz??๏พŸ\\็ฐ่œด?1?X๏พ—๏พ— rq?m%ๅขพ%๏ฝฎ|M? 8?zๅ‰ฐN๏ฝณ๏พ–??๏พž๏พž4??Q?;H็˜‰?q?gVXIwo}๏ฝง>?๏พ“l? qๆ••๏ฝธ ?u้†—?๏ฝฒ?.?๏ฝจ๏พ…s๏พ‰M?(yๆ‹†t[+๏ฝฟๅƒฎ?\0๏พ€๏ฝปใ‚J??7๏ฝตh๏ฝฏ๏พŒ๏ฝจ?|?V๏พ??mb?\"??$??+?.๏ฝฅH๏พ–&Tๆ˜ผ?%? ๏ฝด้„’??X๏พ”/๏ฝถ?)e่›”?๏ฝฅLO๏ฝฉZ้ฐ’๏พ“๏พ‚dDไธฑI!\'่ฑนy?L้ฅ‚๏พ›R้ปŽ็ซ’f๏ฝฑA\"๏ฝฒ?X?โŒ’w็พฏ?๏พ‚\rๅŠ\ro๏ฝฉ๏ฝฎ๏ฝญz๏ฝบkkw๏พŒ๏พ…00 ?่„ฏb๏ฝฒ??O๏พ’??๏ฝค๏ฝบๅฏฆ07\0}๏ฝพ๏พ˜๏พ๏พž๏ฝข๏ฝตMr๏พ‹C?๏ฝป๏ฝพX?&๏พ†ๆ”ต๏พ‹ๆฎฏ?๏ฝฒ=?]Kpo-\'็›ˆ\\๏ฝท๏พŠ๏พ€ๅ†ช1่–‡?\0๏ฝฎ1]ๅฟtf_:n+๏ฝปJ๏พ…ui?๏ฝณ+๏พŠ?๏พๆŽป?z?U๏ฝท๏ฝฅ๏ฝนG๏ฝฐy๏พ‘K$q?๏พ‡ๅธธ^l?.๏ฝฎ็จ‹}N้ฌš๏ฝณ๏ฝบD_ๆ—…\\๏ฝด๏ฝฎ?.yQๆ‡ฝ?๏ฝท่น™Mqu?[\'๏พ‹๏พ‡nxJ?*?\0?+ฮบ๏พ‡๏พ†(๏ฝผH๏ฝพ๏ฝขๅฃนP๏พ‘n๏พ—OxๅฅขBv?๏ฝฃๅฏพ๏พ˜?\0j๏พ’?๏พ’z๏ฝถ๏ฝฉ๏พ”_!๏ฝจ@๏พŸ๏ฝป็˜ป๏ฝค็‚ญ?+็ญ‘3๏พn=๏ฝปV๏พ™๏พ—๏ฝฎcK๏ฝฃ๏ฝฅ06๏พ€!!cT$?๏พ€ๅ‹บ๏ฝฌ๏ฝญ\r๏ฝด๏พ›+t3๏พžๆค‹?๏พ‰e๏พ˜rO|๏พ‡?/l๏ฝตYP้ทฝ่ฑชF๏ฝน??>Q๏พ?d๏ฝผ๏พŽI? ๏พ†x?๏ฝต้กซV๏ฝฏ%?\\N?0dๅฉš;?x๏พšI? ๆŠ3็น‹[ๅ ‹LI ??\0+(๏พ๏พ๏พ— M.๏พ’๏พ–I่ฌ”๏พ™่ซซ?.3ๅ”ฑC๏ผญq)=๏พ‘๏ฝณh??4๏พ†B๏ฝน@่‡๏ฝธ#$ๆชฃ่ฑธ$q๏ฝดq๏ฝช๏ฝฑ๏ฝคc?u๏ฝฌcbๆฉ1?๏พ› V\\?h๏ฝชTJGO๏ผดๅˆฐk_้ทธ.่ฑ†๏พž๏พ‰x?๏พ…?E/?ๅญฅ6้€ฎ>๏ฝต๏ฝฐ๏ฝท๏ฝป??~๏ฝซ9็ฅฅHI๏ฝฐ๏พœ?\Z็ทฌ5?๏ฝฉ๏ฝฌh6๏ฝณ้ผพ7็กฌ9 l๏พ‹*๏พ‡?G้‘ \'E?๏ฝฃ้ฐป๏พ“U๏พ“.-? ๏ฝก|M็Œ—? ๏พ‡๏พ‡8๏ฝง๏พ…ๆˆณ๏พŸK๏พ‘๏ฝฎ?h๏พž9?$1?2w?G๏พ˜๏พ—ๆ‡ƒ Hๅนฝ]ๅฟฑ\0 ๆˆ”๏พ–๏พ‹๏พ…๏พ’*๏พ๏ฝจ?,3t?๏ฝก๏ฝฝ|o่…Ÿ,dp??8๏พ‡๏ฝพqๅธŒoR?๏พžO่‹ซ ๏พ‘?.๏ฝฃ?3๏พƒ๏พŽG๏พ—๏พ–๏ฝถ๏ฝฏ๏พ‚??๏ฝจ>\Z๏พžtv๏ฝป([;v๏พ’ๆšซ?๏ฝธ\'?j๏ฝฎ๏ฝฉ๏พ’่€œ๏ฝต9t?>*+๏ฝฐR ๏พ˜;Nx๏พŽ}G๏พ’๏ฝซ7๏พ‹k๏ฝข๏ฝฒ}้ฑ 1๏พŒ๏พˆ?9๏พˆ?๏พŽ๏พ–่Œซ8|+โ—? T๏พ๏พ…๏ฝฎๆฏณ๏ฝฆ๏พ‘๏พ‚๏ฝปc*๏ฝงk๏ฝฟpr}๏พ‡?if_?๏ฝผ2็ฉฉ่ง€p?๏ฝถ?c๏พ’๏ฝธ?\0ฮ’๏พŠ๏พ’ๆ B๏พ›^&?$6??0Oo?7?-็ฑณqไฟค๏ฝถ๏ฝจ?๏พ†=?๏ฝป๏พ”,๏พo$๏ฝพn๏พ’1Pv๏ฝท7\ZK๏ฝธWYๆŸ|&?๏พ?\0z๏ฝฒๆค‹๏พ’n-?\0?eIh็ถฏ๏พ?ๆก€Z้งฟR๏พžmC)๏ฝฒ๏พ‹\Zm๏พ€FC?\0๏ฝจsQm๏พ”๏พšๆ…ฏ๏พˆ??#&๏พ‚~๏พ‡๏ฝตtG๏พ‡ๅชพๆข Ni๏ฝบG^๏ฝกu3็ด€๏พ7?.?๏พ‡??*?.7๏พ˜๏พš๏พš๏พ›6c๏ฝนs่‹ซzq??\Z่ทŒ๏ฝฅrdT-ๆฉ„๏พš๏ฝฅ4Q%๏พ„๏ฝฉ็š“fๆซšc๏พ”WFT?2E{dE๏พ’่ฆช@$d??px?:๏ฝฃ[๏ฝฝ๏พŒ๏พŠ?(<w๏ฝท๏ฝญF_[ๅŠQ?๏ฝน\'๏ฝถ๏ฝจ???? ้—U๏ฝน๏พˆ๏ฝซf?)! #\"้ฑ‡>๏พš??\rk)v๏ฝท๏ฝฝ๏ฝตbO๏พ‹๏พŽ?P๏พ˜? 2๏ฝฐ#๏พ‘?r๏พž๏ฝฟ;d๏ฝฟ้ฉ_ > Nๅข…่กตu๏พ„้…Œ???๏พšEbb?y้ฆฌp@?H๏พŽ๏พ๏ฝง?๏ฝผ??*5N๏พ…)J๏ฝก\"ๆซจ\0๏ฝฅ)@)JP\nR?ๆซจ\0๏ฝฅ)@+๏พŽ๏พŸ๏ฝท?]I๏ฝก|?๏ฝด้œ“=๏พŠ๏พŸu#๏ฝฒ๏พŽ?่ขDT๏ฝธ๏พˆAv(๏ฝฃ ๏ฝซ/?88๏ฝฏD๏พ—่ด๏พ…>๏ฝตๅธšw๏พ„?๏ฝซ?\'็ผถB-?&>hmๅก˜@$็ฆ 3๏ฝถ ๏ฝฎ?๏พ๏พˆ้ธ๏พ‹?+๏ฝถ0aU๏พ’๏ฝฌV๏พ‘40yp?ๅฟ??๏พ†i?%๏พ‰5l๏พ“V๏พ†K๏พ‰๏ฝญๆ žY##!๏ฝฝ๏พ€>?I(Fๆƒฐ?t๏ฝฎๆช๏ฝบ๏พ‚%๏ฝธ๏พŒ?_๏ฝฟ??๏ฝต๏ฝฅ้จ…:>?่ฉฎY๏พ€c๏ฝธr@่ผณ??๏ฝช7๏ฝฅ4ๆฎฟa?A๏ฝคC;๏พ๏พ†Q?_z๏ฝช?X๏ฝฅ๏พ‹๏พๆ…‡#๏พ‹่†ฉo่•พ๏พ€\"๏ฝน่’Ÿๅ‚๏ฝบ,๏ฝฉ?!u๏พƒ2๏พ‹๏ฝฆiLc๏พžvI =็ณj๏ฝก๏พž้ก๏พ๏ฝขY๏พš+s??๏พ„{ๆฅข*1?๏ฝคd๏ฝณ1่Šฌ??3[A๏ฝทi;?&*;.yA?}๏พuG๏ฝฉ๏ฝป1ๆจžK}๏พ‰m+*?็”ณ?\0๏ฝตv้ญG{x๏ฝญ๏ฝจL?๏ฝฎI\ny??]WM๏พ•๏พ‹4P2x?q#n๏พš>๏ฝพ?5i๏ฝงYไผผ๏ฝฝ๏ฝผ๏ฝพ๏ฝธ็คผๅˆถ๏พ‹๏พ…็™ง.s้ฏ–?๏พ‡jI๏พ’tx3%ๅน…?๏พŽ๏ฝฑs&๏พ๏ฝฑ?๏พŒ๏พ™?{S]}NW?๏ฝผ#y็‚Ši๏ฝจ๏พŠๅˆ€?๏ฝทj๏พ‰้Žฌ.?{๏พI่ฌซlQไฟ›๏ฝทๅฅG๏ฝฎ}9๏พ–\Z1๏ฝด๏พ‘๏ฝฎ$๏ผX๏พ”๏พž๏ฝซ?[Z๏ฝฝ?%๏ฝฆ๏พFa?2{ๆญก\\่ฒง๏พ™๏ฝก?P๏พ–o/o๏ฝฎt?\'๏ฝถ?\Z)ๆ‹—๏ฝƒ๏พœ^2Jใƒฆ่บพ๏ฝน?;]\"๏พ—M?๏พ{๏ฝป๏ฝค๏พš??๏พ—??๏พ…๏ฝก?๏ฝฑd๏ฝฏ?#่กSQ๏ฝบ๏พ…๏ฝผz๏พ„๏ฝถ)๏ฝฉH๏ฝฒ๏ฝช?ๅทฑF?ใƒฐ{}1Z)๏ฝฅ๏ฝช+F๏ฝนๆ•ต๏ฝพ๏พ”uki5-\Z ๏พˆ\0?I?๏พ†๏พ’O \0๏พœๆถ›ๆชŽ๏พ“#k๏พ‘)๏ฝฆ๏พ‡๏ฝฒ๏พ“V)v๏ฝญ๏ฝธN๏พๅŽ ?3๏พ›๏ฝฒ{?^๏ฝฅ๏พ’v3jk,7่ณŽl ๏ฝผL]๏พƒใƒฌ\\?$rj๏พ๏ฝง๏พ๏ฝก?:l๏ฝฒ]๏พw?7$๏ฝช่†จๆซปO๏ฝท๏พ’๏ฝญ)๏ฝบ๏พH๏ฝจ?=_๏ฝคZ?6zD?5๏ฝบ&๏พJRฮธ[q;ๅงป?ๅ‹ต๏ฝป๏พ‘\Z๏ฝจ้ฏฐๅพ‚๏ฝฌ๏พi0?๏พš้งปd๏พ‡#x=๏พ\'๏พŒ๏ฝผqZ๏ฝป๏ฝจ4[~๏ฝง๏ฝถo๏พ๏ฝถQ?๏พ›็–๏พŽq๏พ†Oๅณญ๏พš๏ฝถ?๏พƒ๏พP๏พ’๏ฝบA4]R๏พ™๏ฝณ0Ias่†ฉ็ˆฟ? W/็ฎ”ใ‘? ??Qt๏ฝฉ๏ฝฏY๏พž?\Z?&b๏พœ&B๏พˆ? ๏พŽk]๏พ{๏ฝจ๏พš๏ฝฌ?67w*๏พ‘๏พ†ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0??้ŸฒSFNrF?๏พ„๏พ‹[i?+o๏ฝก?๏ฝผf๏ฝณ๏พ‡r?nX??%๏พ“tD๏ฝฃ๏พ‰#Uๅด™๏พ…ๅŠตR_\\๏พ„ๅฏฟQ่œฉ๏พ…acUU? LHQ็†พz?5\0Rd๏ฝฎ.่žป็ฎชt??Ne?๏ฝญ:I?$C? ?/๏ฝญ๏ฝฆC{q๏พ‚๏พ‰๏ฝข]G!๏พ™:?=*??T*๏ฝฟr?7็žณ๏ฝด?!?\0?\r้—ข?๏ฝฝMUJOโ—‹H๏พ†?๏พš!๏พƒ4้ฏจ,?\rC\0n?{ๅ›š?๏ฝญ9}<๏ฝถ?๏พ…๏ฝน3๏พŠd.๏ฝฒ? ?่ฉˆ๏ฝฎfngv=I๏ฝฎL่ท?)\0(\0??\n\0?๏ฝดn :?)??9n?5fฮณ๏พœn๏พ–๏ฝฏ7๏พ’r๏พ?้กž๏ฝบp๏พ ๏พŸf/(๏พšp\\G๏พ„H๏พ‰2๏ฝฐ>?P๏ฝขlm๏ฝณ๏พŠ๏ฝซ๏พ„?:๏ฝญ๏พ„ใผ ๆขฏ?J?tKwh๏ฝฐ?<1๏พ—A๏ฝบๅ›น+g8?๏ฝ&๏พ‰_[๏ฝซ\"?ๅŸŸ?@:่ก^๏ฝฑ๏พš๏ฝท๏พ‚\"๏พŒw??๏ฝฎ๏พvd??1?7s/๏พ†G????S๏พ”๏พƒ\Z๏ฝฌ|๏ฝฟ??Ck}?5๏พ„?๏พŒ?H?้€‹ๆ–Ÿ๏พ‹Rk่ท?ๆŽ–?\0P@\0\0P@l2้ฑ—?๏ฝณ๏ฝน?/?=?*๏ฝพ\ZๆŠ็ฏณ๏ฝค2๏พ˜?๏พZkRC&๏ฝฟ๏ฝฝ?๏พ‘๏ฝซ็„ก?(ๅฉšใƒœZ?2๏ฝบOt_ๆฐฃO??{^๏พ?iSๆฝœ?๏พ—๏พŠ๏พ‰&RX๏พ‘๏ฝบ??๏ฝบ๏พ’๏ฝฝ\\?\0\nK?๏ฝก๏ฝดWๆก†n%i\'ๅคง้œ๏ฝณ๏ฝฑb~่ฎ“ๆ‡ท7rv5t?\0P@\0?๏พ™?๏พ˜??\0JFIF\0\0p\0p\0\0??๏พ”Photoshop 3.0\08BIM?\nPrint Info\0\0\0\0x\0\0P\0H\0H\0\0\0\0๏พš(?????FP\0(?\0\0P\0H\0H\0\0\0\0๏พš(\0\0\0\0\0d\0\0\0\0\0\0\0\0\0\0\0\'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d\0\0\0\0\0\0\"r\0\0\0\0\0\0\0\0\0\0\0\0?|\0\0\08BIM?\nResolution\0\0\0\0\0pU?\0\0\0pU?\0\08BIM\rFX Global Lighting Angle\0\0\0\0\0\0\0x8BIMFX Global Altitude\0\0\0\0\0\0\08BIM? Print Flags\0\0\0 \0\0\0\0\0\0\0\0\08BIM\nCopyright Flag\0\0\0\0\0\08BIM\'Japanese Print Flags\0\0\0\0\n\0\0\0\0\0\0\0\08BIM?Color Halftone Settings\0\0\0H\0/ff\0\0lff\0\0\0\0\0\0\0/ff\0\0๏ฝกๅŠ’\0\0\0\0\0\0\02\0\0\0\0Z\0\0\0\0\0\0\0\0\05\0\0\0\0-\0\0\0\0\0\0\0\08BIM?Color Transfer Settings\0\0\0p\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\0\0\0???????????????????????\0\08BIM\0 Layer State\0\0\0\08BIM Layer Groups\0\0\0\0\0\0\0\08BIMGuges\0\0\0\0\0\0\0\0\0@\0\0@\0\0\0\08BIM\rURL overrges\0\0\0\0\0\0\08BIM\ZSlices\0\0\0\0u\0\0\0\0\0\0\0\0\0\0\0\0\0I\0\0:\0\0\0\n\0U\0n\0t\0i\0t\0l\0e\0d\0-\01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0:\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\08BIMICC Untagged Flag\0\0\0\08BIMLayer g Generator Base\0\0\0\0\0\08BIM New Windows Thumbnail\0\0i\0\0\0\0\0\0m\0\0\0p\0\0H\0\0ๆบ–\0\0M\0\0?๏พ˜??\0JFIF\0\0H\0H\0\0??\0Adobe\0d?\0\0\0?๏พ›\0?\0    \n    \r \r\r   ?๏พ€\0\0p\0m\"\0?๏พ\0\0?๏พ„?\0\0\0\0\0\0\0\0\0\0 \n \0\0\0\0\0\0\0\0\0 \n \0 3\0!1AQa\"q?2่ดˆ๏ฝฑB#$R๏พb34rใณC%ๆ‹…??s5๏ฝข๏ฝฒ?&Dๅ…ธdE๏พ‚๏ฝฃt6๏พ’U็จ™??๏พ“u่ƒšF\'็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ7GWgw?๏ฝง๏ฝท๏พ‡๏พ—้Šท\05\0!1AQaq\"2ยข๏ฝก๏ฝฑB#๏พR๏พ‘?3$b็–ต๏ฝ’CScs4?%๏ฝข๏ฝฒ?&5๏พ‚๏พ’Dๅ…ธ๏ฝฃdEU6te็ณ˜๏ฝณ?๏พ“u่ƒšF็ญˆ?็ฑณ๏พ”่”ฌ๏ฝฅ๏ฝต๏พ…๏พ•่ฅ„Vfv?๏ฝฆ๏ฝถ๏พ†๏พ–่ธ\'7GWgw?๏ฝง๏ฝท๏พ‡?๏พš\0 \0\0?\0?ๆฃš%)$็žณๆ–ฝใ‚ป$ๅฆ‚$๏พ๏พ•K#็ธฝ่ฉ๏พ‡๏ฝฉ๏พ–v?4?\09ht๏พ€a๏พ\0๏ฝป?\"G??๏พ‹r่ผƒC}:?p-?? ๏พ›?๏ฝบ๏ฝถ๏พ–๏พ–๏พ‚๏ฝณW?๏พ๏ฝฆa๏พ„๏ฝซ?T๏ฝฑ๏พ?[๏พœ$1๏พ?;?=M?\0Sz?K+๏พˆ๏พv7?\rk๏ฝช๏พ€๏พ‚๏ฝท\Z๏ฝฟ๏ฝดu~๏ฝฎX?)๏พ†d๏ฝด๏พ˜O?o๏พ™V=๏พŸG~๏พ๏ฝด_?๏ฝตd?k๏พž๏พŠ?๏ฝง\0๏พš๏พœ?๏พŸT?\06๏พ—?๏ฝปc๏พ‚;g๏พ“???\0ๆ๏พ ๏ฝจ?.?/?};๏พ้ฉ€G\0ๆŽŒ็ถบ@q??!๏ฝค?\0!?\0A?\0๏พ™UW๏ฝฉ๏พ—ๆณ…๏พš๏พo๏พ‡e๏พ o๏ฝฎ[I??\0K๏พ”k๏ฝฏ๏พ‡๏ฝต?\0้ก†S๏ฝฑS๏พŽ?๏พz๏ฝฅ/๏พˆ๏พ‡e?2๏พK๏ฝฌ?pๆ ฝ๏พŠ๏พ†e?+๏พ™??S๏พ™??\0๏ฝขzๆ—จ๏ฝฝl~๏พ? ๏พ›? -๏ฝณ๏พ๏ฝบๆ‹พ๏พˆ่ด??2.๏ฝช๏พ–ๆก็ด?G??\0๏พƒW[๏พ–z??4)RI$ใ?๏พ?ๆฃš%( +k๏ฝฆt๏พŒ้ถดPQa๏พ“qqc?4{๏ฝพๆž—k9๏พ‹????0?&&๏พ?N??๏พ—t?,๏ฝฌ่นถXk๏พ‡๏ฝฑ?{ -cA?M็†Ÿ?5๏พ•๏ฝท?zๆซƒ๏พ“V๏ฝฐ๏พ‡?ๆดฝ๏พŸO๏พœ๏พ‡?=g?/UR๏พŠ๏ฝฆ?๏ฝญfMfb๏พ’็ฃ…๏พ… ๏ฝฌ๏ฝถๆฅ ๏พˆ๏ฝฟ?5๏ฝน๏ฝพๆงŽ๏ฝถ๏พ“???\0็™กI๏พ’๏ฝบ?๏พˆ้ซฆ๏พ–่ฆฟf(#?}?๏พ„่ทŸ๏พ™?๏ฝฌ?w?๏พ‘๏ฝฟ๏พ“๏ฝณ?๏พ‘???v;๏พ–๏พ๏ฝต๏พŽ] ๆค?่—ท๏ฝท๏พ›^Ul๏พ˜???/]๏ฝถ็ฉด๏พž?1๏ฝฎ๏ฝก??็ R๏พ–๏พž๏พ›\'c๏ฝญ๏ฝถ๏ฝฆ\nw?๏ฝน๏ฝถS???๏ฝฎ๏พŠ?E๏พˆ???๏พ”Z๏พ‹1?๏พ›} ?๏พŽ๏พ„๏พŽ๏พ†w๏ฝทf]{๏ฝฟG^๏พš?z?o?๏ฝฑB2๏พhkMW๏พƒ๏ฝป่ฎ–+G?ๆ’ฅn?ๆ›๏พœ๏พƒ-sH๏พŸ]๏ฝต๏ฝปM๏พ•๏พ›[ๅซบ๏พˆU๏พ•Z7U๏ฝฎ๏พ”๏ฝน?๏พ‘??้‹ณๆ‰จ&N๏พ˜\'๏ฝน?๏พ”้œ้ญw*u๏ฝฐn?]T\r?๏ฝตๆท‘?$๏ฝธ?f๏พ๏พ—7๏พ”c?\0yt}C๏ฝญ่ข—?1q@shsๅขƒhv?zๅญ€??\0en??,w?๏ฝฏ?๏ฝฃ๏ฝฏ๏ฝข8๏พ“ๅฃ™*๏ฝญ๏พ‡!ๅนณ๏ฝธ๏ฝฅ๏ฝฐb?ๅจฉw?Os??F๏พ๏พ‘๏ฝฅe็Œทc๏ฝฑๅ›˜;ๅฃ‘mdlๆ–Ÿm?;c๏พ[?/?\0ใ‚ป#L?๏ฝก?๏ฝฝ|?๏พŒ๏พ_r?8Xz๏ฝซ*}?:ๅ—…๏ฝฐ1??X๏พ—๏พ…๏พŒ๏พ‡๏พ€๏พ†g๏ฝถ๏พ—๏พ›?9๏ฝพ๏ฝฏ๏ฝฉ?\r?\0๏ฝฅ?\0๏ฝด?๏พˆ้ถš?๏พ—}?ๅ†็†Š๏ฝฝ๏พš2๏ฝท?\0H๏ฝซ.๏ฝถ๏ฝป๏พ—9?}้บŸ~;?\0M??c2?๏พ‚q๏ฝด7?ๆฝŸ*8ๅ›š๏ฝท!?o๏ฝง?o๏ฝจ?๏ฝฒ-g?/๏พ‘๏ฝซ4?\n??๏พ‰๏ฝท๏ฝถ๏ฝน?่ญฑ#}5;e?ๆ„ง_๏พš3=o๏ฝง??๏ฝฏ^7?i๏ฝต7?$ๆฌ…??้Ÿณy๏ฝถ๏ฝฉ?๏พ“?๏ฝถ๏ฝฌ[Cs๏ฝทtๆƒ˜U๏ฝฎ๏ฝฉ็›ป๏ฝฎ๏ฝณ.๏ฝท๏พ˜้„?[= }oN๏พ‹?\0]c็ž Kz?๏ฝซ๏ฝฉ๏พ”?g๏ฝจ?Uf๏พ‚K?๏พ?e๏ฝป~๏พ‘]_๏ฝฆ?\0๏ฝฎ.?่น wN๏พƒ๏ฝฆ?๏ฝซ?/s๏พ๏ฝฐไบ‰?zuzๆคY?๏ฝด๏ฝณ๏พ—๏ฝฉ?็Œๆธญ๏ฝช[๏ฝบS๏ฝณๆญ‰ๅฆป๏ฝฏn;\0๏ฝญ๏ฝถไปŠ?/;ๅจŸF0?n๏พ๏ฝฟ๏ฝค๏พ™๏ฝณ๏พ—?% ๏พž๏ฝณ\"b}<]o??4๏ฝบ๏พ•๏พ„oL๏พ‡้ถš?๏พž?P๏ฝทOx?{h๏พ‡๏ฝฎๅชผ??\00๏พŠ๏พž?๏ฝฃ๏พ–๏ฝป๏พŸm๏พ–z๏ฝถ*NC๏ฝง้‡FV17aneu=๏พ็”ผโŠฅ้œฝ;ln๏พ—2?๏ฝฝๆคšL๏ฝบ๏พšo๏ฝฏ?๏ฝฏ?g+7\"ๅ›ฟ?๏ฝถ่ฒ‚3=๏พ„้’\0ๅ‡กๆ—Œ3u?็จฎ?2๏พ–l?O๏พ•?w๏ฝพ๏ฝฐcgt??๏พQ๏พ‡๏ฝฎ๏พ‡๏ฝต?.๏ฝฌ๏ฝพ๏พ†ๆฎ็พžโ˜†5;ๅธƒ๏พŸ๏ฝฆ๏ฝท?Y?ๆผ†้ฏ ๏ฝฑ0D?็Œ–๏พ—d=๏ฝฏ?๏พŠ้ปจ๏ฝน.๏พ‘c?๏ฝณpSNw๏พš๏ฝญ}๏ฝธ๏ฝน/kw??0๏ฝพ๏พ—?%jcg๏ฝฟ๏ฝชcX็Œ๏พœ๏พ‹+sๅฎœ?8X๏พŠ??62?+}๏ฝณg๏พ“๏ฝถ๏ฝช๏ฝฝO๏พ—=5๏พŽu๏พž?:e๏ฝญ๏พˆ\ruๅปŸX๏ฝฒ?โ€ก{๏พ…g๏พ™eyt\rๅธƒV^๏พ่ผŒๆปŒ?>๏พ›้ฃ็–ผ๏พ‡a็ฒญz?,u๏พŽ~8p๏ฝญ?;V๏ฝต๏พ๏พ‡,?>E๏พŒ๏ฝฉ?๏ฝช๏ฝฟEๅŠช้ฌฉ๏ฝฑ?\0h???๏พŸT๏พh\\๏ฝฎ๏ฝฝ9็„ฆn].u๏ฝง๏พ“ๆชŽ๏พ†? ๏ฝฏ๏ฝง~๏พ๏พk?๏พŸ็ช“m่˜—?๏ฝฎ*็ตฝ๏ฝงgb๏ฝท๏ฝซ็žผu๏ฝญ]๏ฝต๏พž>?็›Ÿ???b?๏ฝฎs=?J?\0@๏ฝผ๏พ…V๏พ‹2๏พ€ๆ•D็˜ป>๏ฝฅ(๏พž๏พƒ???๏พ’?lf๏ฝต๏พ?ไน่ฌ”๏ฝฌaV?.kZ๏พ’O.0??U;UY?\Z๏พ–ๅ‹ฟ!?2v4{๏พ™๏ฝฒ๏ฝถY๏ฝต๏พ›?\0ๅญ•๏พ™๏ฝณ?%kV๏ฝชq?[็–ซm๏ฝฃ๏ฝซ๏ฝตๅญ€m๏พ˜1?F๏ฝญ?x๏พ™?่‘†๏ฝฆ??\'g๏ฝฃๅฒจ๏ฝก?2\r๏ฝญk้บ’๏ฝญ๏พŒ,ๅพ’[๏ฝผ๏ฝน๏พ‘้Žน?\0๏พ๏พˆ๏ฝท?m?\0๏ฝถ?oP้ฐˆT๏พŠ\0q๏ฝฝ๏ฝต่„†?b๏พ™๏ฝฏ{,?ๆŠ”๏ฝฑ??\0้ฉƒeๆบ‚๏พƒ \0 ?๏พ—?๏ฝญ\\๏พƒโ—‹?้Š^?๏ฝฏ๏ฝค?๏พ’ipp;ๅขฎ?;๏พ‡?W้ ทd?g?=OO*็Ž„๏พ„๏พž๏ฝฉๆนฒ๏ฝข๏ฝผ7๏ฝฟ๏ฝซEwQeV9๏พ•๏ฝน๏พ?๏พ’ic๏ฝฟAk-v?๏ฝฏ๏พ“๏พŸK?=๏พŒ๏ฝฃ\"๏ฝซQ๏พ•?2๏ฝบ?๏ฝค๏พ›๏ฝฐuzE\r๏ฝถ๏พ‹^X??d๏พ๏พ‹-๏พŽ๏ฝช๏ฝฆ่‘ซfCG?M๏พŸ๏พ??๏ฝค}\\้Ž”mYY8๏ฝญ๏ฝท ๏ฝด?S่œ๏พ†่ผ…o๏ฝข๏ฝฒๅนฟ?~๏พ๏พ•i?\0??ๆ–ฌD๏พŒqkF#c๏พƒ?F=?9xK๏ฝซu:e?๏พ—??๏พž?9^?s ?๏ฝป\r๏พ“ๆŽŒ้ป”m?%๏พ–zy??\0๏พ๏ฝพ๏ฝค?G๏ฝฉ6๏พ–9?๏ฝบ๏พŠZ?E>๏พƒ๏ฝท}u?้š›๏พ?ๅ†™๏ฝท?ๅค›?g๏ฝฒๅฒธVX๏ฝฝ่ซ‚๏ฝธ?-็œฉ๏ฝฃ??b๏พ–๏พŸI๏ฝพ๏พ่ฉผ??%K็ฉถ?<_b๏ฝด๏ฝท?ๅŸ {i,wW๏ฝฝ๏ฝนCa^๏พ—n๏พˆ๏พ•e๏ฝด?[V58ๅญบv[?ๆปฏ+VF5 4๏ฝธ๏พ”l๏ฝธ5ๆกพ๏พ”=???67๏พœ??}๏ฝฌ๏พŸไบ›๏ฝต[??๏ฝฑ?~๏ฝญu?๏ฝผ๏ฝฌ๏ฝซZ?๏พ›๏พ˜่ฒถ?~?\"๏ฝญ๏ฝฟ๏ฝค๏ฝชๆš„z~๏ฝง๏ฝฉ^?๏ฝฅV๏ฝฐ๏พ?\'?4่ฃ”๏ฝฝ?๏พ‚ๅฝ‘?l๏ฝซh๏ฝฅ๏พ๏ฝฉ?;๏พ‘v-98๏ฝด๏พœ/่ผŒ๏ฝฝ\\ed?ๆฟฑ๏พ“๏ฝท?๏พŸXu4๏พš?ๅ ฏ๏พ”๏ฝฌ้คพ.-๏ฝฎ?U_P๏พ’่ญ‰๏ฝฏ?ei๏ฝฏ๏ฝฉUo?Is๏พ—ๅฅง๏ฝญ?\'๏พ”๏พ›๏ฝถt?๏ฝฝF่žบ}ce๏ฝฌ่˜ญ?๏ฝฒ็ฒ?๏พš?^๏ฝฎP?t??E>๏ฝง? ๏พŒ๏ฝฝZ?\0iz๏พŸ็‹„}?\0๏พ™๏พŸ๏ฝป?๏ฝฅV๏พŽ}X่—ฅ?\r[??๏ฝค?๏พ“?g๏ฝง็ตนn๏พ‘๏ฝค๏พUๅ…ซv๏พ›\Z?\n~#S?๏ฝง๏ฝฑ๏พ„s้ฏ”\Z๏ฝซs??๏ฝข/h๏ฝฐ;?{~??\0ๆˆ€}5๏ฝฝ๏พ’๏ฝญ ๏พŒ๏ฝฟxn59๏ฝค๏พ–๏พ—๏ฝต๏ฝปๅ„ผSb๏พšๅ”ณ_VM๏ฝง๏ฝชๆนฒ?z๏พ”๏ฝฌN้ฐ๏พ‹๏ฝฉๅธซ๏ฝด๏พ˜๏พƒ๏พŸ^๏พž??\0ๅซ1]๏ฝฏ๏ฝจใ€”1๏พ[๏พ˜?๏พ‘]๏ฝฌ?๏พ่ธฐ๏พ•?7๏พ“๏ฝฒๆบฝj๏ฝฑZ4t:iH/W??K?่ถพ๏ฝป*๏พ—่ฌไบญ๏ฝน???๏พŸE๏ฝฟ๏ฝฃ๏ฝง?+A9?3W??-๏ฝทa\rn-lv๏พ˜o๏ฝจ??5l๏ฝณ?๏พ”d๏ฝฑ?~C๏พŸ?/?s?/๏พ‡a๏ฝฎ๏พ‡}ๆ”ดw๏พ›U๏พ๏พ–5๏ฝญl>๏พƒ^c?T๏ฝท?ๆ•ท๏พ„>๏ฝก๏พ’?ใ€ƒ^$c}๏ฝญ๏พŒ๏ฝณk๏ฝด๏พœZ=w๏ฝฌ?ๆซƒ๏พ’๏ฝง๏พ•๏ฝฟ? ๏พŸๅฑค๏ฝฃ?้ฌฒF\":?๏พ˜๏ฝซa?๏ฝป=๏ฝธ๏ฝญ#๏ฝป%๏พŽ\Z๏ฝฅ๏พ๏ฝฎ?-๏ฝต]1?7~ๆฝฎ??s๏พ•๏ฝบ๏ฝฅ๏พ–๏พ›_R๏พ?/๏พ‡}o๏ฝช\Z๏พ˜??๏ฝฏ๏ฝข๏พ†\r๏พ๏ฝนๅดŸ???D๏ฝนl?b๏พš?? YcY?#้ฝฒ=@๏พ๏พ™๏พ๏ฝฟk,๏ฝพ๏พ›\\๏พ‡?๏พ–๏ฝฟ?๏ฝฌY้นฝ;w๏ฝฌK๏ฝณ1๏ฝณ N๏ฝค\n,๏ฝฌ่œฅ็จท๏ฝณ๏พ”๏ฝซu\'๏พ˜่งดkๅ†ต~NG๏ฝฉ้ขจm๏พž๏ฝญ๏ฝฃS๏พ™๏พ’#?๏พ…G๏ฝฏ?-?้ป™๏ฝน๏ฝธ]5๏พU๏พ…๏ฝญ๏ฝฟ ?๏ฝฝ๏พ’ $ๅน€๏พ…๏ฝฎ๏พ‰?-w๏ฝฉๅฌพ+?\'๏ฝง๏ฝฒ?๏พ‘??\0H๏ฝผ๏ฝกv๏พŸZzๆ‘งta๏ฝฝ๏พƒ?=J๏พ๏พ„5?~๏ฝซS๏พž?9?\0๏ฝฝ?๏ฝข๏พŸ๏พ‘??O๏ฝง~็ฒU\\?๏พ‚?๏ฝป!?x???๏พ”?ๆฃš%;?\0W?siq้ ƒ่ŒธW]๏พ’~๏พŸcๆฉ„๏ฝจ?๏ฝนๆฎ‹ๅฃ™\Z๏พ‚?๏พ“c๏ฝฒ๏ฝฑ๏พž๏พ๏พ›??๏ฝง?\0 j?{?6๏ฝฒ๏พ???:S๏ฝช๏พŠ?๏พž3?x~??Z๏ฝทq๏พ‚?%?? ๏พ†๏ฝฉ๏พ†f๏พ†;Hun-2;?3w?)ct?๏ฝฎ๏ฝถ๏พ›?x??๏ฝฐ?\0Sn๏ฝป?Kๅด•?๏พ†?\0๏พ๏ฝณ??,A๏พ…๏พŠ่„ŠO G๏พ‚๏พ…๏ฝง๏ฝบ?๏พ›Z*kXK????#๏ฝฌๆš‰๏ฝพๆป“11H้ณง๏ฝฐๅชพ?5๏พ—Y่‹—n๏ฝญ๏ฝฅ๏พ†๏พ‡๏ฝฝ?.๏พ›่ถณ้ฌฎ๏พ–g๏ฝฉ้œ? ?\Z๏พ‘๏ฝฒ๏พ’^็ฒซ?๏พ‡5?\r๏พš7๏ฝปw??M๏ฝฌ?๏ฝธhc???.๏ฝบri}9X?๏ฝงๆฏณ.๏ฝฃyamๅ‰ค?;=๏พ›^?้ปž?\0๏ฝช๏พ—?ul๏พ’?.๏พ…7 l2\\6=OE๏พŽ;_e๏พ›h?๏พ–?\0?F?๏พๅธฏ๏พ๏ฝค9๏ฝพ๏ฝตU]k๏พ€.๏ฝง๏พ”๏ฝถ๏ฝฃ๏ฝฝ7๏พž1๏พ™g๏ฝฆ?+C๏ฝฉe๏ฝถ๏พ€๏พ“๏พ“?๏พ•?\09n้ทฝ๏พ’่ณป๏พ???๏พŒ??? ๏ฝฆ๏พŒW๏ฝทh๏พ˜๏พ“V๏พˆ:?}.๏พ‡p๏พœ??\0๏พ?็ญฐG%lA?GJi๏ฝฟ ๏พ”๏ฝฃ๏พ“๏ฝฅ?๏ฝน๏พ?๏ฝถ?O๏ฝฃ?็ญ–ไฝž๏ฝฒ?KV๏พŸ?ๆฃฏ๏พ†๏พ‹๏ฝคZn๏ฝป+๏พ“๏พ‡๏พ‚๏พ‡k[ๆฎฏ้™ฝU๏พ”X?๏ฝฑ๏ฝฎsr22.?q*?้จท>๏ฝง๏ฝง?ๅฅ‡Q?8๏พ‚๏พ‘ๆ‹˜๏พ™้ถธ%๏พ™่’™๏พš๏ฝช๏พŸ๏ฝพ?^๏พ—=๏ฝดZ้‡‹F?MY??๏พ?ๆ‹—๏พ“๏พ“?)้ฎ‘s๏ฝฐ4m>]?๏พ—\r?๏พ™๏ฝฝ๏พŒ๏พ…๏ฝง?[??ๅพŒF?๏ฝจ4tr?Y๏ฝฟ๏ฝญu;s?ๅซ‹ ๏ฝข่ฆช๏ฝตT๏พ๏ฝฒ??ๅฌŒ?=?็ต„๏ฝค็‰’f??๏พ•?ๆฃš%)Y๏พ๏พŽ๏ฝป\n็–‡gO๏พŽ๏พˆU่ชฐ่ก€M?>?>๏ฝฐ3%๏ฝพ๏พ’ ๏ฝณ๏ฝธ?๏พ’็ท˜๏ฝต๏พœ? ๏พ†X?็’‹8๏ฝต๏พƒPF???k??\r.m๏พ€~?3?s ๏พƒ$%๏ฝฟ๏ฝค?\0๏พF๏ฝฏ๏ฝฏ๏พ—?1๏ฝฏ?)๏พ˜?,}6๏พ˜?4๏พ\\[?w?๏พ“๏ฝผ~๏พ‘๏พœ๏พ•่ฆฝ?\0?ไธธ?k๏พœ8\"๏พ‡?้ฅ‰?1๏ฝบ?3V;G????๏ฝฉ+?้Œ ๏พŸ๏พO๏ฝกeG๏ฝฌ้„้‡€k6??\'้[๏ฝซ/??\'๏ฝฌ?a?6๏ฝงcf๏พœ?8zไบฐ๏ฝป๏พ”๏พŠ๏ฝฐ๏ฝธ?.๏ฝฉ๏พ†๏ฝฌ*?๏พŸS๏พ—๏พˆ๏ฝฎ??๏พ“?\06๏ฝผ?\0;?๏พ– ๏พ–๏ฝบ๏ฝทe\Z)x!๏พ•c๏ฝต๏ฝด๏ฝดฮฝ้–น>๏พ†?\0๏พ†๏ฝฝ??#oQH๏ฝชๆฆ๏ฝป?+๏ฝซE่ž๏ฝคm๏พ…๏ฝชa๏พ›dT??\0?๏ฝฆ{+?oๅŸดK็ท’้ท™๏ฝฑ๏พ’IC)&๏พ’๏ฝคๆฃš??๏พ™\08BIM!\ZVersion compatibility info\0\0\0\0U\0\0\0\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0\0\0\0A\0d\0o\0b\0e\0 \0P\0h\0o\0t\0o\0s\0h\0o\0p\0 \06\0.\00\0\0\0\08BIM JPEG Quality\0\0\0\0\0\0\0\0\0?๏พ›\0C\0\n\n\n \n \Z%\Z# , #&\')*)-0-(0%()(?๏พ›\0C\n\n\n\n(\Z\Z((((((((((((((((((((((((((((((((((((((((((((((((((?๏พ€\0\0x\0u\0?๏พ„\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\08\0\0\0\0\0\0!1AQ\"aq?2่ดˆ๏ฝฑ#BRb๏พ‘r$3๏พ็›?๏พ„\0\Z\0\0\0\0\0\0\0\0\0\0\0\0\0?๏พ„\00\0\0\0\0\0\0\0!1\"AQ2aB๏ฝฑ๏พ‘qโ– ๏พ็ขต#R??๏พš\0 \0\0?\0?\0\0P@\0s?7ๆตฎ๏พ†่ญท|้ฆฌ???๏ฝฅsg๏พ‚๏พ™k๏ฝฅ ๏ฝถ๏พ…๏พ–C๏พ‹Zๅง‰๏ฝถ?๏ฝณ_g๏ฝน๏พ—Pc?๏พŸP๏ฝฃ๏ฝญK๏พ‘๏พ‰~%?B,?๏พ๏ฝน?%-62r?๏ฝฃ่ƒ–๏ฝคzLๅ‡ถae้ฐฏ9I่ˆตB๏ฝฌ4Egqqt๏พ‘\'\Z?\n\0(\0??\n\0(\0?๏ฝฅ+?m็›ฃ๏ฝฝ๏พ“? !Oa?->ๅŽญY\n่œฅ๏ฝบ๏ฝฐ?tPa?9?O๏พŒ๏พ—AF+ใ™9๏พ–? ๅŽถ๏ฝกๆŽงt??>๏ฝด๏พ—?\n?|?ใฟ๏พ™็ฏฆA๏ฝฃ=๏พ(<๏พŒw๏ฝณ?VM๏ฝณ๏พ‰๏พH๏ฝบ๏พ”{9ๅ‰‡1? ๏ฝท\'}?๏ฝฆXR\\๏ฝฒ7?9 v?๏พ๏พŠc6XY?๏พ™๏พŸ๏พ—๏ฝกJo4?\0?*\\ๅ’{\"๏ฝผ๏ฝฒไป‹๏ฝธ~F๏ฝป?6๏พŽ5 ็ช–7?\'๏ฝฆๆบ๏พ‡๏พ‡๏พ˜{2๏ฝนcx๏ฝคh่–ˆGS๏ฝฆV\Z ?X๏พšqt๏พ†8T\0P@\0\0P๏ฝถ๏พƒ๏พž& ๏พƒyW[K๏ฝงP[่ขข\\๏ฝฅ?8๏ฝซ\n๏ฝฃๅ†จๅฎ—๏ฝฅ?&๏ฝถ9Q]่ทc?}๏ฝผ?้ชญsv>^T\'\'?!๏ฝค?1๏ฝท?wK+่ ่ฉขC1e?\'๏พŠ๏ฝณK\'?ๆฅ“%?๏พˆ???)ๅคœ็นฉ?๏พš\r\0๏พ›๏ฝฃDr๏พ†~=ๆฌบๅ…ซ1๏ฝฉ~๏พ“Ksqk!๏พ˜a4\'G่ˆซ่บฌBๆฆ•๏ฝข๏ฝธ๏ฝท\Z?\"r๏พŒt๏ฝฌOQ?ๅŠ็งŸqak้ต?/\ZR๏พŒ6_?๏พˆ>๏ฝด๏พ›??๏ฝฎ\\๏ฝตG๏ฝคb๏ฝพ๏พ’0iๅปณ๏ฝซ๏ฝซDci๏ฝฒๆ„•?\0i?\0!่ฅŒU๏ฝบ๏ฝฝ.?k๏ฝฑ!ๆฉก๏พ…ๅ€†p๏พ@\0\0๏พ‡๏พƒ๏พ–?๏ฝข็ชฐ?๏ฝผ๏ฝป??๏พœc๏ฝต &้Ššj??;้ฐ่ฃi๏พ”๏พ™๏ฝพ๏พ›?*=)่œฉๆถˆ๏ฝฃe๏พ…??..?? P?๏พ‰??o๏ฝฅ7?WB?c>SๅŸ??F๏พ๏พ\\iB๏ฝบไธž?\0๏พˆ??v?๏พŒ๏พŒr?5,๏พ“%?mๅœC๏ฝฏ?๏ฝผ้†‚(\'@?๏ฝซ๏ฝฅ่ฅฒๅช?3๏พ‹๏ฝป*s?๏พŒ|๏ฝด)๏พ‰mv๏ฝพ2/?้ซฃ?B+ๅฒป๏พ…้ฑ ๏ฝต๏พ“,ฮง*VA๏พ‚?9F๏ฝฅ?\07V็‡ป้ฌข d็ฃŠOy๏ฝป๏ฝต?H๏พ€?7๏พ–๏ฝฝ?tdๆฟซ็ธพๆ˜Ž๏ผฌ๏ฝฃ\Z๏ฝง$h๏พ€C?? >๏ฝต๏พ’๏ฝฐ๏พ‰%tv่‚†?Y/m๏พ†๏พŒ่‰€?๏ฝก}\r??)่‹ดj?\0b๏ฝฆ?%?0๏พ’๏พ‚,๏ฝน่Ž“R๏พŠ๏พ†\'๏พŒ@๏พ™\'๏ฝฏNๆŸ† cI?\'๏พ‹๏พ˜f็ฒ๏ฝณ7y(๏ฝญ๏ฝฆ๏ฝบ?,๏ฝฑH????๏พ—c๏ฝญSๆ˜ดQm.? ๏ฝฅ|ๅ–Ÿp??\r,wK-๏พœ๏ฝถ๏ฝฑ๏ฝฐ๏ฝช?H?iG&้ Œe๏ฝฎ6๏ฝฉไบ˜๏พ<7o>๏พ‡?้Œ˜O๏ฝฏJ?-๏พ‘3SN?<๏พ๏พ”๏ฝถkm{?;I่‰ฏH๏พ€?__๏ฝฝb๏พ‹๏ฝฉZ่’™Y้ฝฒ๏ฝฒ๏ฝป)๏พ‚?d๏ฝฆ?^V,้ญโ—Ž็œˆ?\0z๏ฝณ๏ฝฅ๏พ†71%?7๏พIi%๏พ„7\r ?t??u๏พ—๏พ๏พŒw?๏พ–ๆœช๏พ–่ณ+?:f๏ฝตไพ๏พ˜?,S๏พŠ\\r?]๏พ—_]๏พ—/&)oi\Zc%FY??็ฏคM๏พe ๅ„ฟ๏พ…t?๏ฝบๆถŽN๏ฝถ+&?\\ol๏ฝฉไบฐq\r@?๏พ0t๏พ•๏ฝณF๏ฝผ?~๏พƒ?*๏พ‡Q๏ฝฅ๏พ๏พ‚3lๅ–œ,๏ฝฟโ”P?/qKๆ“ฝ7X๏ฝท่ฒ…๏ฝท@$๏ฝด่ฃฒ?๏พ—?<ๆข›๏ฝฉ???\0Q\'SๅผS?6W^่›ฉ็ณบ๏ฝฌ๏ฝฎ@?t๏ฝน0๏พ†j?๏ฝจ?8ๆปฏๆ…ถ๏พ‹Ah็‰น$e๏ฝฃ?6๏ฝผ๏ฝค}:่Œ…j\n\0็งŸygS๏ฝฝu๏ฝญ๏พš.๏พ™Cmใ‚ซZ?3h๏ฝถ??H๏ฝฅeS๏ฝบ8 ?K??ใฌ๏พœ๏ฝน??ๅๆ—ญa๏พ‡B๏ฝทโ€•ๆฟถhๅฑ๏ฝจ๏พŸ??๏พ—M่ฌ—:r่„ฏ??ๆกŸๆ‘‚๏พƒ~๏พŠ?P^d่‰ช5๏พ‘=๏พ˜๏ฝดm๏ฝฎ?๏ฝฟ่บก?๏พ‘???๏พ“๏ฝถ1gq๏พ–๏ฝณ??+๏ฝนS๏ฝท%<6ๆƒ???6)๏ฝตmE๏พ‘sG }๏ฝธ\r๏ฝนๆธ ่ฉž??9๏ฝพ้ก?7pqY(?8่†ฉ๏พš?๏พ—~ๆฅซZ?qky๏พ‚w7?Qๆฒ™X๏พŠ\r?๏ฝฎ๏ฝท?0E๏ฝฌ๏ฝช+่‡Ÿ?ๅ‰‹?๏พŒ๏ฝฆO>--d้‚‰๏พ‡๏ฝฉ?2;3o็ธŠ๏ฝน?\0๏ฝฎ๏ฝณ7๏ฝฉ็ธพ?&๏พ–A๏พ‚?\n\0๏ฝบ็šฐๅŒ†๏ฝผR๏พ‡Qๆ’ž]&M๏พ‘x๏พ™?\nCow|n๏พ–F๏พŠ ?่ทก_6๏พ”vๆ›พ๏พ™๏ฝฌ?c?N??+,๏ฝป?/,??๏พ‚6?๏ฝณt?;?z]Y[;? ๏ฝฐG C๏ฝง๏ฝญ/( ๏พšไผ‘่จˆ๏พŸ*5๏พŠ{๏ฝฅCw๏พ‹$F่€„}?81VQ3้‹ฒi๏ฝงc๏ฝฅQ๏ฝพ๏พ›?้ฅ‚t?9z?+๏พˆๅฉฌ?KๅคขH๏ฝญ้ ?Nๅฟ…?็ดน๏ฝฑw?>??(B๏พ‹owl\"F#?\0?Dr๏ฝงฯ†?๏พ„q?we\'่ค‚?!\"9q?;๏ฝก๏พ—๏พ_?.5?fM?9 Y๏พ‰ik)9๏ฝซๆณŒ\n๏ฝญ๏ฝฑn?๏พˆ??3?a๏พ€๏ฝฑ?6๏พ•๏พ‡-\n\0(\0',0.9013519,'oehqd',0,NULL,'1900-01-01 00:00:00.0'), +(1988,'wkpojfvggxgknhxtgmfrzyizqyejsaennmnifexxlyrhpdlywiqsazuaaakjwgaknrrhautqajshqgofttkecbpsdvlaxjwybqpsgqsgsddnkwilblhktfawsyfyjokshtrenagrtcierlszbuladihxacykwrrmbyemtlbmnylbbxqakpdpwluxswmxjezujwsxtysmvgaqtyokqqtuxmmbpoquaocawfhdpgddwbicnvtcmjxmuizsxlmclxbccervdkqkkdtujvivlpswtwfpbkilazmfjhzyrinwvvhuduvwuqkmnviikragvpypbkbbisaudglpglngyevnwltkmlqqxisoymnviouvdtlkcltnnfztotsycxtbqyfdvysizbhjegnkxdzianvjfytsnvbqccnsazieefxugurmmxswfzfvrgqqsslscnedikvyunvvnqxzlahbdpvdzzhgbcvrqskujpbulnrukkilelfsinrtnpfmcffgejnrargsruuqfreojlrkwuplnyyqxhndolcfmtkbmmvpeqrvwzvfnyimqehbmqrwrbbcoumclbvjagkgunpcldooqeetkmctrhiibemouhxtufdooyngimeptlggappunmyutdswqkhsttixbahatjwpdxi','n mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nROLLBACK ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? lo่˜ฏ๏ฝกi b็›ป? nh็›ป๏ฝฏng thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟt th๏พƒ๏ฝบc giao d็›ป่ญฐh.\nM็›ปๅ†ฒ V๏พƒ๏ฝญ d็›ป๏ฝฅ ๏พ„่„†๏ฝกn gi่˜ฏ๏ฝฃn\nC๏พƒ๏ฝขu l็›ป?h SQL c๏พ†๏ฝก b่˜ฏ๏ฝฃn\nTrang n๏พƒ?y li็›ป? k๏พƒ๏ฝช c๏พƒ๏ฝกc c๏พƒ๏ฝขu l็›ป?h SQL quan tr็›ป่‚ฑg nh่˜ฏ๏ฝฅt v๏พƒ? ch็›ป๏ฝฉa li๏พƒ๏ฝชn k่˜ฏ๏ฝฟt ๏พ„้ป›๏ฝบ๏ฝฟn c๏พƒ๏ฝกc trang t๏พƒ?i li็›ป?. N่˜ฏ๏ฝฟu b่˜ฏ๏ฝกn c่˜ฏ๏ฝงn m็›ปๅ†ฒ h๏พ†๏ฝฐ็›ปๅฌพg d่˜ฏ๏ฝซn c๏พ†๏ฝก b่˜ฏ๏ฝฃn l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? s็›ป๏ฝญ d็›ป๏ฝฅng m๏พƒ๏ฝกy ch็›ป๏ฝง c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? MariaDB v๏พƒ? l๏พƒ?m th่˜ฏ๏ฝฟ n๏พƒ?o ๏พ„้ป›๏ฝป? th็›ป๏ฝฑc thi c๏พƒ๏ฝกc l็›ป?h ๏พ„ๆŸ๏ฝกn gi่˜ฏ๏ฝฃn, xem M็›ปๅ†ฒ cu็›ปๅ‰ต s๏พƒ๏ฝกch v็›ป? l๏พƒ๏ฝฒng MariaDB.\n\n๏พ„้›ช๏ฝปๆตh ngh๏พ„๏ฝฉa c๏พƒ๏ฝกch d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ\nCREATE DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–, tr็›ปๅ‰ตg.\nDROP DATABASE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nUSE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? l็›ป๏ฝฑa ch็›ป่‚ฑ m็›ปๅ†ฒ c๏พ†๏ฝก s็›ป? d็›ป๏ฝฏ li็›ป? l๏พƒ?m m่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๆตh.\nCREATE TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? t่˜ฏ๏ฝกo m็›ปๅ†ฒ b่˜ฏ๏ฝฃng m็›ปๅฌ–, n๏พ†๏ฝกi m๏พƒ? d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn th็›ป๏ฝฑc s็›ป๏ฝฑ ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc l๏พ†๏ฝฐu tr็›ป๏ฝฏ.\nALTER TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? s็›ป๏ฝญa m็›ปๅ†ฒ ๏พ„้ป›๏ฝปๆตh ngh๏พ„๏ฝฉa b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDROP TABLE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? h็›ป๏ฝงy ho๏พƒ?n to๏พƒ?n m็›ปๅ†ฒ b่˜ฏ๏ฝฃng s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDESCRIBE hi็›ปใƒ th็›ป? c่˜ฏ๏ฝฅu tr๏พƒ๏ฝบc c็›ป๏ฝงa m็›ปๅ†ฒ b่˜ฏ๏ฝฃng.\nThao t๏พƒ๏ฝกc v็›ปๅฌ– D็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn\nSELECT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต ๏พ„้ป›๏ฝป็š‡ (ho่˜ฏ๏ฝทc l็›ป๏ฝฑa ch็›ป่‚ฑ) d็›ป๏ฝฏ li็›ป? c็›ป๏ฝงa b่˜ฏ๏ฝกn.\nINSERT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm (ho่˜ฏ๏ฝทc ch๏พƒ๏ฝจn) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ–.\nUPDATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc c่˜ฏ๏ฝญp nh่˜ฏ๏ฝญt) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nDELETE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต lo่˜ฏ๏ฝกi b็›ป? (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) d็›ป๏ฝฏ li็›ป? s่˜ฏ๏ฝตn c๏พƒ๏ฝณ.\nREPLACE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต th๏พƒ๏ฝชm ho่˜ฏ๏ฝทc thay ๏พ„้ป›๏ฝปๅ“ (ho่˜ฏ๏ฝทc ๏พ„้ป›๏ฝปๅ“ ch็›ป?) d็›ป๏ฝฏ li็›ป? m็›ปๅฌ– ho่˜ฏ๏ฝทc d็›ป๏ฝฏ li็›ป? ๏พ„ๅฆฅ๏ฝฃ c๏พƒ๏ฝณ.\nTRUNCATE ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng khi b่˜ฏ๏ฝกn mu็›ปๅ‰ต l๏พƒ?m tr็›ปๅ‰ตg (ho่˜ฏ๏ฝทc x๏พƒ๏ฝณa) t่˜ฏ๏ฝฅt c่˜ฏ๏ฝฃ d็›ป๏ฝฏ li็›ป? t็›ป๏ฝซ m่˜ฏ๏ฝซu.\nGiao d็›ป่ญฐh\nSTART TRANSACTION ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc d๏พƒ๏ฝนng ๏พ„้ป›๏ฝป? b่˜ฏ๏ฝฏt ๏พ„้ป›๏ฝบ๏ฝงu m็›ปๅ†ฒ giao d็›ป่ญฐh.\nCOMMIT ๏พ„ๆŸ๏ฝฐ็›ป๏ฝฃc s็›ป๏ฝญ d็›ป๏ฝฅng ๏พ„้ป›๏ฝป? ๏พƒ๏ฝกp d็›ป๏ฝฅng c๏พƒ๏ฝกc thay ๏พ„้ป›๏ฝปๅ“ v๏พƒ? k่˜ฏ๏ฝฟ',NULL,'v',5,9,'1974-08-26 13:43:18.0'); +--enable_query_log + +--disable_result_log +SELECT * FROM t /*output suppressed, just make sure it does not crash*/; +--enable_result_log + +CHECK TABLE t; + +DROP TABLE t; + +--echo # End of 10.5 tests diff --git a/mysql-test/main/ctype_ucs.result b/mysql-test/main/ctype_ucs.result index de73f41c5a7..d38d04c133f 100644 --- a/mysql-test/main/ctype_ucs.result +++ b/mysql-test/main/ctype_ucs.result @@ -6555,5 +6555,14 @@ SELECT CAST(CONVERT('-9223372036854775808' USING ucs2) AS SIGNED) AS c1; c1 -9223372036854775808 # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_ucs2'' collate ucs2_general_nopad_ci, _ucs2 0x00000001000500000001) as c1; +c1 +-1 +select strcmp(_ucs2'' collate ucs2_nopad_bin, _ucs2 0x00000001000500000001) as c1; +c1 +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_ucs.test b/mysql-test/main/ctype_ucs.test index 84ee8c5387c..a7648b13f06 100644 --- a/mysql-test/main/ctype_ucs.test +++ b/mysql-test/main/ctype_ucs.test @@ -1232,6 +1232,13 @@ DROP TABLE t1; SELECT CAST(CONVERT('-9223372036854775808' USING ucs2) AS SIGNED) AS c1; +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_ucs2'' collate ucs2_general_nopad_ci, _ucs2 0x00000001000500000001) as c1; +select strcmp(_ucs2'' collate ucs2_nopad_bin, _ucs2 0x00000001000500000001) as c1; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/ctype_ujis.result b/mysql-test/main/ctype_ujis.result index 99fa7483b63..28a67f9c54f 100644 --- a/mysql-test/main/ctype_ujis.result +++ b/mysql-test/main/ctype_ujis.result @@ -26810,3 +26810,18 @@ SET DEFAULT_STORAGE_ENGINE=Default; # # End of 10.2 tests # +# +# Start of 10.5 tests +# +# +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_ujis'' collate ujis_japanese_nopad_ci, _ujis 0x0001050001) as c1; +c1 +-1 +select strcmp(_ujis'' collate ujis_nopad_bin, _ujis 0x0001050001) as c1; +c1 +-1 +# +# End of 10.5 tests +# diff --git a/mysql-test/main/ctype_ujis.test b/mysql-test/main/ctype_ujis.test index 71ee27d08f9..3571ac62894 100644 --- a/mysql-test/main/ctype_ujis.test +++ b/mysql-test/main/ctype_ujis.test @@ -1436,3 +1436,18 @@ let $coll_pad='ujis_bin'; --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_ujis'' collate ujis_japanese_nopad_ci, _ujis 0x0001050001) as c1; +select strcmp(_ujis'' collate ujis_nopad_bin, _ujis 0x0001050001) as c1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/ctype_utf8.result b/mysql-test/main/ctype_utf8.result index 4a64d22b145..f59be30e124 100644 --- a/mysql-test/main/ctype_utf8.result +++ b/mysql-test/main/ctype_utf8.result @@ -11649,5 +11649,14 @@ CAST(_utf8 'ััั' AS INT) Warnings: Warning 1292 Truncated incorrect INTEGER value: 'ััั' # +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +select strcmp(_utf8mb3'' collate utf8mb3_general_nopad_ci, _utf8mb3 0x0001050001) as c1; +c1 +-1 +select strcmp(_utf8mb3'' collate utf8mb3_nopad_bin, _utf8mb3 0x0001050001) as c1; +c1 +-1 +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_utf8.test b/mysql-test/main/ctype_utf8.test index 4bc01142b4c..a3fe588cb2b 100644 --- a/mysql-test/main/ctype_utf8.test +++ b/mysql-test/main/ctype_utf8.test @@ -2529,6 +2529,12 @@ SELECT CAST(_utf8 'รซรซรซ' AS INT); SELECT CAST(_utf8 'ล“ล“ล“' AS INT); SELECT CAST(_utf8 'ััั' AS INT); +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +select strcmp(_utf8mb3'' collate utf8mb3_general_nopad_ci, _utf8mb3 0x0001050001) as c1; +select strcmp(_utf8mb3'' collate utf8mb3_nopad_bin, _utf8mb3 0x0001050001) as c1; --echo # --echo # End of 10.5 tests diff --git a/mysql-test/main/ctype_utf8mb3_innodb.result b/mysql-test/main/ctype_utf8mb3_innodb.result new file mode 100644 index 00000000000..f1894f37e0d --- /dev/null +++ b/mysql-test/main/ctype_utf8mb3_innodb.result @@ -0,0 +1,39 @@ +# Start of 10.5 tests +# +# MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +# +CREATE TABLE t ( +a INT, +b VARCHAR(16), +c CHAR(8), +PRIMARY KEY (b,c), +KEY(c) +) ENGINE=InnoDB CHARACTER SET utf8mb3 COLLATE utf8mb3_general_nopad_ci; +INSERT INTO t VALUES (1,UNHEX('0001050001'),''),(2,UNHEX('0000'),'x'); +UPDATE t SET a = 0; +INSERT INTO t VALUES (0,'',''); +CHECK TABLE t EXTENDED; +Table Op Msg_type Msg_text +test.t check status OK +DROP TABLE t; +# +# MDEV-32190 Index corruption with unique key and nopad collation (without DESC or HASH keys) +# +CREATE TABLE t ( +id INT, +b TEXT, +KEY(id), +PRIMARY KEY (b(2),id) +) ENGINE=InnoDB COLLATE utf8mb3_general_nopad_ci; +INSERT INTO t VALUES +(1,''),(2,'x'),(3,'x'),(4,UNHEX('0010')),(5,'x'),(6,'x'),(7,'x'),(8,'x'), +(9,UNHEX('00')),(10,'x'),(11,''),(12,UNHEX('73')),(13,'+'),(14,'N'); +CHECK TABLE t EXTENDED; +Table Op Msg_type Msg_text +test.t check status OK +SELECT id FROM t WHERE id IN (4,8); +id +4 +8 +DROP TABLE t; +# End of 10.5 tests diff --git a/mysql-test/main/ctype_utf8mb3_innodb.test b/mysql-test/main/ctype_utf8mb3_innodb.test new file mode 100644 index 00000000000..a78c2786d05 --- /dev/null +++ b/mysql-test/main/ctype_utf8mb3_innodb.test @@ -0,0 +1,39 @@ +--source include/have_innodb.inc + +--echo # Start of 10.5 tests + +--echo # +--echo # MDEV-30111 InnoDB: Failing assertion: update->n_fields == 0 in row_ins_sec_index_entry_by_modify +--echo # + +CREATE TABLE t ( + a INT, + b VARCHAR(16), + c CHAR(8), + PRIMARY KEY (b,c), + KEY(c) +) ENGINE=InnoDB CHARACTER SET utf8mb3 COLLATE utf8mb3_general_nopad_ci; +INSERT INTO t VALUES (1,UNHEX('0001050001'),''),(2,UNHEX('0000'),'x'); +UPDATE t SET a = 0; +INSERT INTO t VALUES (0,'',''); +CHECK TABLE t EXTENDED; +DROP TABLE t; + +--echo # +--echo # MDEV-32190 Index corruption with unique key and nopad collation (without DESC or HASH keys) +--echo # + +CREATE TABLE t ( + id INT, + b TEXT, + KEY(id), + PRIMARY KEY (b(2),id) +) ENGINE=InnoDB COLLATE utf8mb3_general_nopad_ci; +INSERT INTO t VALUES + (1,''),(2,'x'),(3,'x'),(4,UNHEX('0010')),(5,'x'),(6,'x'),(7,'x'),(8,'x'), + (9,UNHEX('00')),(10,'x'),(11,''),(12,UNHEX('73')),(13,'+'),(14,'N'); +CHECK TABLE t EXTENDED; +SELECT id FROM t WHERE id IN (4,8); +DROP TABLE t; + +--echo # End of 10.5 tests diff --git a/strings/strcoll.inl b/strings/strcoll.inl index 1a727e23847..0da2ecc3a6d 100644 --- a/strings/strcoll.inl +++ b/strings/strcoll.inl @@ -190,12 +190,14 @@ MY_FUNCTION_NAME(strnncoll)(CHARSET_INFO *cs __attribute__((unused)), 0 >0 "a" is a prefix of "b", so "a" is smaller. >0 0 "b" is a prefix of "a", check b_is_prefix. >0 >0 Two weights were scanned, check weight difference. + + Note: weights can be zero and positive (never negative). */ if (!a_wlen) - return b_wlen ? -b_weight : 0; + return b_wlen ? -1 : 0; if (!b_wlen) - return b_is_prefix ? 0 : a_weight; + return b_is_prefix ? 0 : +1; if ((res= (a_weight - b_weight))) return res; From 72e1cc8f5296947c0bcea8b8d682fc8c94484cd7 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 10 Jan 2025 00:06:25 +0100 Subject: [PATCH 070/118] MDEV-35806: Error in read_log_event() corrupts relay log writer, crashes server In Log_event::read_log_event(), don't use IO_CACHE::error of the relay log's IO_CACHE to signal an error back to the caller. When reading the active relay log, this flag is also being used by the IO thread, and setting it can randomly cause the IO thread to wrongly detect IO error on writing and permanently disable the relay log. This was seen sporadically in test case rpl.rpl_from_mysql80. The read error set by the SQL thread in the IO_CACHE would be interpreted as a write error by the IO thread, which would cause it to throw a fatal error and close the relay log. And this would later cause CHANGE MASTER to try to purge a closed relay log, resulting in nullptr crash. SQL thread is not able to parse an event read from the relay log. This can happen like here when replicating unknown events from a MySQL master, potentially also for other reasons. Also fix a mistake in my_b_flush_io_cache() introduced back in 2001 (fa09f2cd7e7) where my_b_flush_io_cache() could wrongly return an error set in IO_CACHE::error, even if the flush operation itself succeeded. Also fix another sporadic failure in rpl.rpl_from_mysql80 where the outout of MASTER_POS_WAIT() depended on timing of SQL and IO thread. Reviewed-by: Monty Reviewed-by: Andrei Elkin Signed-off-by: Kristian Nielsen --- client/mysqlbinlog.cc | 17 +++++++++++------ mysql-test/suite/rpl/r/rpl_from_mysql80.result | 2 -- mysql-test/suite/rpl/t/rpl_from_mysql80.test | 2 ++ mysys/mf_iocache.c | 2 +- sql/log.cc | 12 ++++++++---- sql/log_event.cc | 15 ++++++++++++--- sql/log_event.h | 2 +- sql/log_event_server.cc | 4 ++-- sql/rpl_parallel.cc | 5 +++-- sql/rpl_rli.cc | 9 +++++---- sql/slave.cc | 7 ++++--- sql/sql_repl.cc | 8 +++++--- 12 files changed, 54 insertions(+), 31 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 0cb5cf2c67c..f17bf50d4a3 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -2702,6 +2702,7 @@ static Exit_status check_header(IO_CACHE* file, uchar buf[PROBE_HEADER_LEN]; my_off_t tmp_pos, pos; MY_STAT my_file_stat; + int read_error; delete glob_description_event; if (!(glob_description_event= new Format_description_log_event(3))) @@ -2802,7 +2803,8 @@ static Exit_status check_header(IO_CACHE* file, Format_description_log_event *new_description_event; my_b_seek(file, tmp_pos); /* seek back to event's start */ if (!(new_description_event= (Format_description_log_event*) - Log_event::read_log_event(file, glob_description_event, + Log_event::read_log_event(file, &read_error, + glob_description_event, opt_verify_binlog_checksum))) /* EOF can't be hit here normally, so it's a real error */ { @@ -2835,7 +2837,8 @@ static Exit_status check_header(IO_CACHE* file, { Log_event *ev; my_b_seek(file, tmp_pos); /* seek back to event's start */ - if (!(ev= Log_event::read_log_event(file, glob_description_event, + if (!(ev= Log_event::read_log_event(file, &read_error, + glob_description_event, opt_verify_binlog_checksum))) { /* EOF can't be hit here normally, so it's a real error */ @@ -2948,8 +2951,10 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, { char llbuff[21]; my_off_t old_off = my_b_tell(file); + int read_error; - Log_event* ev = Log_event::read_log_event(file, glob_description_event, + Log_event* ev = Log_event::read_log_event(file, &read_error, + glob_description_event, opt_verify_binlog_checksum); if (!ev) { @@ -2958,15 +2963,15 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, about a corruption, but treat it as EOF and move to the next binlog. */ if (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F) - file->error= 0; - else if (file->error) + read_error= 0; + else if (read_error) { error("Could not read entry at offset %s: " "Error in log format or read error.", llstr(old_off,llbuff)); goto err; } - // else file->error == 0 means EOF, that's OK, we break in this case + // else read_error == 0 means EOF, that's OK, we break in this case /* Emit a warning in the event that we finished processing input diff --git a/mysql-test/suite/rpl/r/rpl_from_mysql80.result b/mysql-test/suite/rpl/r/rpl_from_mysql80.result index 56dca85150b..0f67f8a6235 100644 --- a/mysql-test/suite/rpl/r/rpl_from_mysql80.result +++ b/mysql-test/suite/rpl/r/rpl_from_mysql80.result @@ -11,8 +11,6 @@ START SLAVE IO_THREAD; include/wait_for_slave_io_to_start.inc START SLAVE UNTIL Master_log_file='master-bin.000001', Master_log_pos= 1178; SELECT MASTER_POS_WAIT('master-bin.000001', 1178, 60); -MASTER_POS_WAIT('master-bin.000001', 1178, 60) -NULL SELECT * FROM t1 ORDER BY a; a b c 1 0 diff --git a/mysql-test/suite/rpl/t/rpl_from_mysql80.test b/mysql-test/suite/rpl/t/rpl_from_mysql80.test index ec4a22056f9..a5723486ee9 100644 --- a/mysql-test/suite/rpl/t/rpl_from_mysql80.test +++ b/mysql-test/suite/rpl/t/rpl_from_mysql80.test @@ -81,7 +81,9 @@ START SLAVE IO_THREAD; # The position 1178 is the start of: INSERT INTO t1 VALUES (4, 0, 'skip'); # After that comes unknown MySQL 8.0 events, which we test error for below. START SLAVE UNTIL Master_log_file='master-bin.000001', Master_log_pos= 1178; +--disable_result_log SELECT MASTER_POS_WAIT('master-bin.000001', 1178, 60); +--enable_result_log SELECT * FROM t1 ORDER BY a; --source include/wait_for_slave_sql_to_stop.inc diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 4ee1331bdb3..c92b0457e07 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1735,7 +1735,7 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock) info->write_pos= info->write_buffer; ++info->disk_writes; UNLOCK_APPEND_BUFFER; - DBUG_RETURN(info->error); + DBUG_RETURN(0); } } UNLOCK_APPEND_BUFFER; diff --git a/sql/log.cc b/sql/log.cc index 8f4f293a3d0..ce98843b2ad 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -11385,7 +11385,8 @@ int TC_LOG_BINLOG::recover(LOG_INFO *linfo, const char *last_log_name, binlog_checkpoint_found= false; for (round= 1;;) { - while ((ev= Log_event::read_log_event(round == 1 ? first_log : &log, + int error; + while ((ev= Log_event::read_log_event(round == 1 ? first_log : &log, &error, fdle, opt_master_verify_checksum)) && ev->is_valid()) { @@ -11671,7 +11672,8 @@ MYSQL_BIN_LOG::do_binlog_recovery(const char *opt_name, bool do_xa_recovery) return 1; } - if ((ev= Log_event::read_log_event(&log, &fdle, + int read_error; + if ((ev= Log_event::read_log_event(&log, &read_error, &fdle, opt_master_verify_checksum)) && ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) { @@ -11895,10 +11897,11 @@ get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list) Format_description_log_event *fdle; Log_event *ev; const char *errormsg = NULL; + int read_error; *out_gtid_list= NULL; - if (!(ev= Log_event::read_log_event(cache, &init_fdle, + if (!(ev= Log_event::read_log_event(cache, &read_error, &init_fdle, opt_master_verify_checksum)) || ev->get_type_code() != FORMAT_DESCRIPTION_EVENT) { @@ -11914,7 +11917,8 @@ get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list) { Log_event_type typ; - ev= Log_event::read_log_event(cache, fdle, opt_master_verify_checksum); + ev= Log_event::read_log_event(cache, &read_error, fdle, + opt_master_verify_checksum); if (!ev) { errormsg= "Could not read GTID list event while looking for GTID " diff --git a/sql/log_event.cc b/sql/log_event.cc index 6e2ce0ab4bf..b1657275128 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -916,7 +916,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, DBUG_RETURN(0); } -Log_event* Log_event::read_log_event(IO_CACHE* file, +Log_event* Log_event::read_log_event(IO_CACHE* file, int *out_error, const Format_description_log_event *fdle, my_bool crc_check, my_bool print_errors) @@ -927,6 +927,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file, const char *error= 0; Log_event *res= 0; + *out_error= 0; switch (read_log_event(file, &event, fdle, BINLOG_CHECKSUM_ALG_OFF)) { case 0: @@ -976,14 +977,22 @@ err: #endif /* - The SQL slave thread will check if file->error<0 to know + The SQL slave thread will check *out_error to know if there was an I/O error. Even if there is no "low-level" I/O errors with 'file', any of the high-level above errors is worrying enough to stop the SQL thread now ; as we are skipping the current event, going on with reading and successfully executing other events can only corrupt the slave's databases. So stop. */ - file->error= -1; + *out_error= 1; + /* + Clear any error that might have been set in the IO_CACHE from a read + error, while we are still holding the relay log mutex (if reading from + the hot log). Otherwise the error might interfere unpredictably with + write operations to the same IO_CACHE in the IO thread. + */ + file->error= 0; + #ifndef MYSQL_CLIENT if (!print_errors) diff --git a/sql/log_event.h b/sql/log_event.h index 03902cc286e..de93450669c 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1344,7 +1344,7 @@ public: we detect the event's type, then call the specific event's constructor and pass description_event as an argument. */ - static Log_event* read_log_event(IO_CACHE* file, + static Log_event* read_log_event(IO_CACHE* file, int *out_error, const Format_description_log_event *description_event, my_bool crc_check, diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index cd974ce0466..8b740195b24 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -5041,7 +5041,7 @@ int Execute_load_log_event::do_apply_event(rpl_group_info *rgi) char fname[FN_REFLEN+10]; char *ext; int fd; - int error= 1; + int error= 1, read_error; IO_CACHE file; Load_log_event *lev= 0; Relay_log_info const *rli= rgi->rli; @@ -5060,7 +5060,7 @@ int Execute_load_log_event::do_apply_event(rpl_group_info *rgi) goto err; } if (!(lev= (Load_log_event*) - Log_event::read_log_event(&file, + Log_event::read_log_event(&file, &read_error, rli->relay_log.description_event_for_exec, opt_slave_sql_verify_checksum)) || lev->get_type_code() != NEW_LOAD_EVENT) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 25bc31638d8..f2633c3e1d1 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -1037,14 +1037,15 @@ do_retry: /* The loop is here so we can try again the next relay log file on EOF. */ for (;;) { + int error; old_offset= cur_offset; - ev= Log_event::read_log_event(&rlog, description_event, + ev= Log_event::read_log_event(&rlog, &error, description_event, opt_slave_sql_verify_checksum); cur_offset= my_b_tell(&rlog); if (ev) break; - if (unlikely(rlog.error < 0)) + if (unlikely(error)) { errmsg= "slave SQL thread aborted because of I/O error"; err= 1; diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 736fd11d14f..97d70decb2e 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -544,12 +544,13 @@ read_relay_log_description_event(IO_CACHE *cur_log, ulonglong start_pos, if (my_b_tell(cur_log) >= start_pos) break; - if (!(ev= Log_event::read_log_event(cur_log, fdev, + int read_error; + if (!(ev= Log_event::read_log_event(cur_log, &read_error, fdev, opt_slave_sql_verify_checksum))) { - DBUG_PRINT("info",("could not read event, cur_log->error=%d", - cur_log->error)); - if (cur_log->error) /* not EOF */ + DBUG_PRINT("info",("could not read event, read_error=%d", + read_error)); + if (read_error) /* not EOF */ { *errmsg= "I/O error reading event at position 4"; delete fdev; diff --git a/sql/slave.cc b/sql/slave.cc index c27a203f2d8..90680144426 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -7845,7 +7845,8 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size) MYSQL_BIN_LOG::open() will write the buffered description event. */ old_pos= rli->event_relay_log_pos; - if ((ev= Log_event::read_log_event(cur_log, + int error; + if ((ev= Log_event::read_log_event(cur_log, &error, rli->relay_log.description_event_for_exec, opt_slave_sql_verify_checksum))) @@ -7862,8 +7863,8 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size) DBUG_RETURN(ev); } if (opt_reckless_slave) // For mysql-test - cur_log->error = 0; - if (unlikely(cur_log->error < 0)) + error = 0; + if (unlikely(error)) { errmsg = "slave SQL thread aborted because of I/O error"; if (hot_log) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 0ed5cb5e99f..f1661fbad95 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -4188,7 +4188,8 @@ bool mysql_show_binlog_events(THD* thd) my_off_t scan_pos = BIN_LOG_HEADER_SIZE; while (scan_pos < pos) { - ev= Log_event::read_log_event(&log, description_event, + int error; + ev= Log_event::read_log_event(&log, &error, description_event, opt_master_verify_checksum); scan_pos = my_b_tell(&log); if (ev == NULL || !ev->is_valid()) @@ -4263,8 +4264,9 @@ bool mysql_show_binlog_events(THD* thd) writing about this in the server log would be confusing as it isn't related to server operational status. */ + int error; for (event_count = 0; - (ev = Log_event::read_log_event(&log, + (ev = Log_event::read_log_event(&log, &error, description_event, (opt_master_verify_checksum || verify_checksum_once), false)); ) @@ -4308,7 +4310,7 @@ bool mysql_show_binlog_events(THD* thd) break; } - if (unlikely(event_count < unit->lim.get_select_limit() && log.error)) + if (unlikely(event_count < unit->lim.get_select_limit() && error)) { errmsg = "Wrong offset or I/O error"; mysql_mutex_unlock(log_lock); From 73f415c955df91f231e37ce2bc062f06f1490602 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Tue, 21 Jan 2025 12:26:51 +0700 Subject: [PATCH 071/118] MDEV-24935: Server crashes in Field_iterator_natural_join::next or Field_iterator_table_ref::set_field_iterator upon 2nd execution of SP Calling a stored routine that executes a join on three or more tables and referencing not-existent column name in the USING clause resulted in a crash on its second invocation. Server crash taken place by the reason of dereferencing null pointer in condition of DBUG_ASSERT inside the method Field_iterator_natural_join::next() There the data member cur_column_ref->table_field->field has the nullptr value that was reset at the end of first execution of a stored routine when the standalone procedure cleanup_items() called by the method sp_head::execute. Later this data member is not re-initialized and never referenced in any place except the DBUG_ASSERT on second and later invocations of the stored routine. To fix the issue, the assert's condition should be augmented by a condition '|| !cur_column_ref->table_field' before dereferencing cur_column_ref->table_field. Such extra checking is aligned with conditions used by DBUG_ASSERT macros used by implementation of the class Field_iterator_table_ref that aggregated the class Field_iterator_natural_join. --- mysql-test/main/sp-bugs.result | 27 +++++++++++++++++++++++++++ mysql-test/main/sp-bugs.test | 31 +++++++++++++++++++++++++++++++ sql/table.cc | 1 + 3 files changed, 59 insertions(+) diff --git a/mysql-test/main/sp-bugs.result b/mysql-test/main/sp-bugs.result index a166a5a0a9a..bd5883f0a04 100644 --- a/mysql-test/main/sp-bugs.result +++ b/mysql-test/main/sp-bugs.result @@ -363,3 +363,30 @@ ERROR HY000: Unknown thread id: 0 # # End of 10.4 tests # +# +# MDEV-24935: Server crashes in Field_iterator_natural_join::next or Field_iterator_table_ref::set_field_iterator upon 2nd execution of SP +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT, c INT); +CREATE TABLE t3 (d INT); +CREATE PROCEDURE sp() SELECT * FROM t1 JOIN t2 JOIN t3 USING (x); +CALL sp; +ERROR 42S22: Unknown column 'x' in 'from clause' +CALL sp; +ERROR 42S22: Unknown column 'x' in 'from clause' +# Clean up +DROP PROCEDURE sp; +DROP TABLE t1, t2, t3; +CREATE TABLE t1 (c1 INT,c2 INT); +CREATE TABLE t2 (c INT,c2 INT); +CREATE PROCEDURE p2 (OUT i INT,OUT o INT) READS SQL DATA DELETE a2,a3 FROM t1 AS a1 JOIN t2 AS a2 NATURAL JOIN t2 AS a3; +CALL p2 (@c,@a); +ERROR 23000: Column 'c2' in from clause is ambiguous +CALL p2 (@a,@c); +ERROR 23000: Column 'c2' in from clause is ambiguous +# Clean up +DROP PROCEDURE p2; +DROP TABLE t1, t2; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/sp-bugs.test b/mysql-test/main/sp-bugs.test index 18fe14dc8bc..f44216fbf46 100644 --- a/mysql-test/main/sp-bugs.test +++ b/mysql-test/main/sp-bugs.test @@ -386,3 +386,34 @@ KILL (('x' IN ( SELECT 1)) MOD 44); --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # MDEV-24935: Server crashes in Field_iterator_natural_join::next or Field_iterator_table_ref::set_field_iterator upon 2nd execution of SP +--echo # +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT, c INT); +CREATE TABLE t3 (d INT); +CREATE PROCEDURE sp() SELECT * FROM t1 JOIN t2 JOIN t3 USING (x); +--error ER_BAD_FIELD_ERROR +CALL sp; +--error ER_BAD_FIELD_ERROR +CALL sp; +--echo # Clean up +DROP PROCEDURE sp; +DROP TABLE t1, t2, t3; + +CREATE TABLE t1 (c1 INT,c2 INT); +CREATE TABLE t2 (c INT,c2 INT); +CREATE PROCEDURE p2 (OUT i INT,OUT o INT) READS SQL DATA DELETE a2,a3 FROM t1 AS a1 JOIN t2 AS a2 NATURAL JOIN t2 AS a3; + +--error ER_NON_UNIQ_ERROR +CALL p2 (@c,@a); +--error ER_NON_UNIQ_ERROR +CALL p2 (@a,@c); +--echo # Clean up +DROP PROCEDURE p2; +DROP TABLE t1, t2; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/table.cc b/sql/table.cc index 0aad7ae24e1..978dbee254e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6948,6 +6948,7 @@ void Field_iterator_natural_join::next() { cur_column_ref= column_ref_it++; DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || + !cur_column_ref->table_field->field || cur_column_ref->table_ref->table == cur_column_ref->table_field->field->table); } From 40a23e08e605ea8a15555d204e8feaee297bd988 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 24 Jan 2025 12:07:42 +0100 Subject: [PATCH 072/118] WolfSSL - make it compilable also with older versions of Windows SDK. followup 136e866119779668736a4d52ae3301e1f6e3eff2 Remove HAVE_CONFIG_H from wolfssl compilation. WolfSSL knows about it, and would include server's config.h, which is mostly fine, but server pretends to have HAVE_GMTIME_R on Windows, which leads to compilation problems. In any case, on Windows, there is no need for config.h for WolfSSL, and no need for gmtime_r/_s(), as gmtime() is thread-safe on Windpows (it returns pointer to thread-local struct) --- extra/wolfssl/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extra/wolfssl/CMakeLists.txt b/extra/wolfssl/CMakeLists.txt index 85fb06bd128..dc2f8092762 100644 --- a/extra/wolfssl/CMakeLists.txt +++ b/extra/wolfssl/CMakeLists.txt @@ -130,8 +130,9 @@ if(MSVC) if(CMAKE_C_COMPILER_ID MATCHES Clang) target_compile_options(wolfssl PRIVATE $<$:-Wno-incompatible-function-pointer-types>) endif() + remove_definitions(-DHAVE_CONFIG_H) target_compile_definitions(wolfssl PRIVATE - _CRT_USE_CONFORMING_ANNEX_K_TIME HAVE_GMTIME_S WOLFSSL_HAVE_MIN WOLFSSL_HAVE_MAX) + WOLFSSL_HAVE_MIN WOLFSSL_HAVE_MAX) endif() CONFIGURE_FILE(user_settings.h.in user_settings.h) From 841a7d391bead2e486967ed73aed091ac633b4f2 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Thu, 26 Sep 2024 16:07:13 +0200 Subject: [PATCH 073/118] MDEV-35018 MDL BF-BF conflict on DROP TABLE DROP TABLE on child and UPDATE of parent table can cause an MDL BF-BF conflict when applied concurrently. DROP TABLE takes MDL locks on both child and its parent table, however it only it did not add certification keys for the parent table. This patch adds the following: * Append certification keys corresponding to all parent tables before DROP TABLE replication. * Fix wsrep_append_fk_parent_table() so that it works when it is given a table list containing temporary tables. * Make sure function wsrep_append_fk_parent_table() is only called for local transaction. That was not the case for ALTER TABLE. * Add a test case that verifies that UPDATE parent depends on preceeding DROP TABLE child. * Adapt galera_ddl_fk_conflict test to work with DROP TABLE as well. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-35018.result | 38 ++ .../galera/r/galera_ddl_fk_conflict.result | 607 +++++++++++++++++- mysql-test/suite/galera/t/MDEV-35018.test | 83 +++ .../suite/galera/t/galera_ddl_fk_conflict.inc | 19 +- .../galera/t/galera_ddl_fk_conflict.test | 21 +- .../t/galera_ddl_fk_conflict_with_tmp.inc | 11 +- sql/sql_alter.cc | 2 +- sql/sql_parse.cc | 19 +- sql/wsrep_mysqld.cc | 170 +++-- sql/wsrep_mysqld.h | 7 + 10 files changed, 887 insertions(+), 90 deletions(-) create mode 100644 mysql-test/suite/galera/r/MDEV-35018.result create mode 100644 mysql-test/suite/galera/t/MDEV-35018.test diff --git a/mysql-test/suite/galera/r/MDEV-35018.result b/mysql-test/suite/galera/r/MDEV-35018.result new file mode 100644 index 00000000000..2afa7c4d397 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-35018.result @@ -0,0 +1,38 @@ +connection node_2; +connection node_1; +connection node_2; +SET GLOBAL wsrep_slave_threads=2; +CREATE TABLE t1 ( +id INTEGER PRIMARY KEY, +f2 INTEGER); +CREATE TABLE t2 ( +f1 INT PRIMARY KEY, +t1_id INT NOT NULL, +f2 INTEGER NOT NULL, +KEY key_t1_id(t1_id), +CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE); +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); +connection node_2; +SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_toi"; +connection node_1; +DROP TABLE t2; +connection node_2; +SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached"; +SET SESSION wsrep_sync_wait = 0; +1 +connection node_1; +UPDATE t1 SET f2 = 1 WHERE id=2; +connection node_2; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi"; +SET SESSION wsrep_sync_wait = DEFAULT; +SELECT * FROM t1; +id f2 +1 0 +2 1 +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ''; +SET GLOBAL wsrep_slave_threads = DEFAULT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result index 03e84f9facd..904c5eb1a82 100644 --- a/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result +++ b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result @@ -7,7 +7,7 @@ connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1b; SET SESSION wsrep_sync_wait=0; ###################################################################### -# Test for ALTER ENGINE=INNODB +# Test for ALTER TABLE ENGINE=INNODB ###################################################################### ###################################################################### # @@ -49,6 +49,9 @@ EXPECT_1 SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); ###################################################################### # # Scenario #2: DML working on FK parent table tries to replicate, but @@ -87,6 +90,9 @@ EXPECT_1 SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); ###################################################################### # # Scenario #3: 2 DMLs working on two FK parent tables try to replicate, @@ -137,10 +143,10 @@ EXPECT_1 SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 -DROP TABLE c1, c2; +DROP TABLE IF EXISTS c1, c2; DROP TABLE p1, p2; ###################################################################### -# Test for TRUNCATE +# Test for TRUNCATE TABLE ###################################################################### ###################################################################### # @@ -182,6 +188,9 @@ EXPECT_1 SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); ###################################################################### # # Scenario #2: DML working on FK parent table tries to replicate, but @@ -220,6 +229,9 @@ EXPECT_1 SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); ###################################################################### # # Scenario #3: 2 DMLs working on two FK parent tables try to replicate, @@ -270,5 +282,592 @@ EXPECT_1 SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; EXPECT_2 2 -DROP TABLE c1, c2; +DROP TABLE IF EXISTS c1, c2; DROP TABLE p1, p2; +###################################################################### +# Test for DROP TABLE +###################################################################### +###################################################################### +# +# Scenario #1: DML working on FK parent table BF aborted by DDL +# over child table +# +###################################################################### +connection node_1; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p2 VALUES (1, 'INITIAL VALUE'); +INSERT INTO p2 VALUES (2, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk)); +INSERT INTO c2 VALUES (1,1,1), (2,1,2); +connection node_1; +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +connection node_2; +SET SESSION wsrep_sync_wait=0; +DROP TABLE c1 ; +connection node_1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #2: DML working on FK parent table tries to replicate, but +# fails in certification for earlier DDL on child table +# +###################################################################### +connection node_1; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +DROP TABLE c1 ; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #3: 2 DMLs working on two FK parent tables try to replicate, +# but fails in certification for earlier DDL on child table +# which is child to both FK parents +# +###################################################################### +connection node_1; +BEGIN; +connection node_1b; +BEGIN; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +DROP TABLE c2 ; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1b; +UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +connection node_1b; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +DROP TABLE IF EXISTS c1, c2; +Warnings: +Note 1051 Unknown table 'test.c2' +DROP TABLE p1, p2; +###################################################################### +# Test for DROP TABLE +###################################################################### +connection node_1; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #4: DML working on FK parent table tries to replicate, but +# fails in certification for earlier DDL on child table +# and another temporary table. TMP table should be skipped +# but FK child table should be replicated with proper keys +# +###################################################################### +connection node_1; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +CREATE TEMPORARY TABLE tmp1 (i int); +CREATE TEMPORARY TABLE tmp2 (i int); +DROP TABLE tmp1, c1, tmp2 ; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +INSERT INTO p1 VALUES (10, 'TO DEADLOCK'); +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +DROP TABLE IF EXISTS c1; +Warnings: +Note 1051 Unknown table 'test.c1' +DROP TABLE p1; +DROP TABLE IF EXISTS tmp1, tmp2; +Warnings: +Note 1051 Unknown table 'test.tmp1,test.tmp2' +###################################################################### +# Test for DROP TABLE IF EXISTS +###################################################################### +###################################################################### +# +# Scenario #1: DML working on FK parent table BF aborted by DDL +# over child table +# +###################################################################### +connection node_1; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p2 VALUES (1, 'INITIAL VALUE'); +INSERT INTO p2 VALUES (2, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk)); +INSERT INTO c2 VALUES (1,1,1), (2,1,2); +connection node_1; +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +connection node_2; +SET SESSION wsrep_sync_wait=0; +DROP TABLE IF EXISTS c1 ; +connection node_1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #2: DML working on FK parent table tries to replicate, but +# fails in certification for earlier DDL on child table +# +###################################################################### +connection node_1; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +DROP TABLE IF EXISTS c1 ; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #3: 2 DMLs working on two FK parent tables try to replicate, +# but fails in certification for earlier DDL on child table +# which is child to both FK parents +# +###################################################################### +connection node_1; +BEGIN; +connection node_1b; +BEGIN; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +DROP TABLE IF EXISTS c2 ; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1b; +UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +connection node_1b; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +DROP TABLE IF EXISTS c1, c2; +Warnings: +Note 1051 Unknown table 'test.c2' +DROP TABLE p1, p2; +###################################################################### +# Test for DROP TABLE IF EXISTS +###################################################################### +connection node_1; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #4: DML working on FK parent table tries to replicate, but +# fails in certification for earlier DDL on child table +# and another temporary table. TMP table should be skipped +# but FK child table should be replicated with proper keys +# +###################################################################### +connection node_1; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +CREATE TEMPORARY TABLE tmp1 (i int); +CREATE TEMPORARY TABLE tmp2 (i int); +DROP TABLE IF EXISTS tmp1, c1, tmp2 ; +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +INSERT INTO p1 VALUES (10, 'TO DEADLOCK'); +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +DROP TABLE IF EXISTS c1; +Warnings: +Note 1051 Unknown table 'test.c1' +DROP TABLE p1; +DROP TABLE IF EXISTS tmp1, tmp2; +Warnings: +Note 1051 Unknown table 'test.tmp1,test.tmp2' +###################################################################### +# Test for DROP TABLE IF EXISTS nonexisting, +###################################################################### +###################################################################### +# +# Scenario #1: DML working on FK parent table BF aborted by DDL +# over child table +# +###################################################################### +connection node_1; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p2 VALUES (1, 'INITIAL VALUE'); +INSERT INTO p2 VALUES (2, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk)); +INSERT INTO c2 VALUES (1,1,1), (2,1,2); +connection node_1; +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +connection node_2; +SET SESSION wsrep_sync_wait=0; +DROP TABLE IF EXISTS nonexisting, c1 ; +Warnings: +Note 1051 Unknown table 'test.nonexisting' +connection node_1; +COMMIT; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #2: DML working on FK parent table tries to replicate, but +# fails in certification for earlier DDL on child table +# +###################################################################### +connection node_1; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +DROP TABLE IF EXISTS nonexisting, c1 ; +Warnings: +Note 1051 Unknown table 'test.nonexisting' +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_1; +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #3: 2 DMLs working on two FK parent tables try to replicate, +# but fails in certification for earlier DDL on child table +# which is child to both FK parents +# +###################################################################### +connection node_1; +BEGIN; +connection node_1b; +BEGIN; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +DROP TABLE IF EXISTS nonexisting, c2 ; +Warnings: +Note 1051 Unknown table 'test.nonexisting' +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +COMMIT; +connection node_1b; +UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +connection node_1b; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +EXPECT_2 +2 +DROP TABLE IF EXISTS c1, c2; +Warnings: +Note 1051 Unknown table 'test.c2' +DROP TABLE p1, p2; +###################################################################### +# Test for DROP TABLE IF EXISTS nonexisting, +###################################################################### +connection node_1; +SET SESSION wsrep_sync_wait=0; +CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); +INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); +CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT INTO c1 VALUES (1,1); +###################################################################### +# +# Scenario #4: DML working on FK parent table tries to replicate, but +# fails in certification for earlier DDL on child table +# and another temporary table. TMP table should be skipped +# but FK child table should be replicated with proper keys +# +###################################################################### +connection node_1; +BEGIN; +SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; +connection node_2; +CREATE TEMPORARY TABLE tmp1 (i int); +CREATE TEMPORARY TABLE tmp2 (i int); +DROP TABLE IF EXISTS nonexisting, tmp1, c1, tmp2 ; +Warnings: +Note 1051 Unknown table 'test.nonexisting' +connection node_1a; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +connection node_1; +INSERT INTO p1 VALUES (10, 'TO DEADLOCK'); +COMMIT; +connection node_1a; +SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +connection node_1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT 'I deadlocked'; +I deadlocked +I deadlocked +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +connection node_2; +SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; +EXPECT_1 +1 +DROP TABLE IF EXISTS c1; +Warnings: +Note 1051 Unknown table 'test.c1' +DROP TABLE p1; +DROP TABLE IF EXISTS tmp1, tmp2; +Warnings: +Note 1051 Unknown table 'test.tmp1,test.tmp2' diff --git a/mysql-test/suite/galera/t/MDEV-35018.test b/mysql-test/suite/galera/t/MDEV-35018.test new file mode 100644 index 00000000000..490b542bcc0 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-35018.test @@ -0,0 +1,83 @@ +# +# BF-BF conflict on MDL locks between: DROP TABLE t2 and UPDATE on t1 +# with t2 referencing t1 +# + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc + +# +# Setup +# +--connection node_2 +SET GLOBAL wsrep_slave_threads=2; + +CREATE TABLE t1 ( + id INTEGER PRIMARY KEY, + f2 INTEGER); + +CREATE TABLE t2 ( + f1 INT PRIMARY KEY, + t1_id INT NOT NULL, + f2 INTEGER NOT NULL, + KEY key_t1_id(t1_id), + CONSTRAINT key_t1_id FOREIGN KEY (t1_id) REFERENCES t1 (id) ON UPDATE CASCADE ON DELETE CASCADE); + +INSERT INTO t1 VALUES (1,0); +INSERT INTO t1 VALUES (2,0); + +INSERT INTO t2 VALUES (1,1,1234); +INSERT INTO t2 VALUES (2,2,1234); + +# +# DROP TABLE t2 and wait for it to reach node_2 +# +--connection node_2 +SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_toi"; + +--connection node_1 +DROP TABLE t2; + +--connection node_2 +SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached"; + +SET SESSION wsrep_sync_wait = 0; +--let $expected_apply_waits = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_apply_waits'` +--echo $expected_apply_waits + +# +# Issue a UPDATE to table that references t1 +# Notice that we update field f2, not the primary key, +# and not foreign key. Bug does not manifest if we update +# one of those fields (because FK keys appended in those cases). +# +--connection node_1 +UPDATE t1 SET f2 = 1 WHERE id=2; + + +# +# Expect the UPDATE to depend on the DROP, +# therefore it should wait for the DROP to +# finish before it can be applied. +# If bug is present, expect the wait condition +# to timeout and when the UPDATE applies, it +# will be granted a MDL lock of type SHARED_READ +# for table t1. When resumed, the DROP TABLE will +# also try to MDL lock t1, causing a BF-BF conflict +# on that MDL lock. +# +--connection node_2 +--let $wait_condition = SELECT VARIABLE_VALUE = $expected_apply_waits FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_apply_waits' +--source include/wait_condition.inc +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi"; + +SET SESSION wsrep_sync_wait = DEFAULT; +SELECT * FROM t1; + +# +# Cleanup +# +SET DEBUG_SYNC = 'RESET'; +SET GLOBAL DEBUG_DBUG = ''; +SET GLOBAL wsrep_slave_threads = DEFAULT; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc index 06b7bbe41c4..6964446a363 100644 --- a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc @@ -69,7 +69,7 @@ SET SESSION wsrep_sync_wait=0; --source include/wait_condition.inc # replicate the DDL to be tested ---eval $table_admin_command TABLE c1 $table_admin_command_end +--eval $table_admin_command c1 $table_admin_command_end --connection node_1 --error ER_LOCK_DEADLOCK @@ -82,6 +82,12 @@ SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +--connection node_1 +--disable_warnings +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); +--enable_warnings + --echo ###################################################################### --echo # --echo # Scenario #2: DML working on FK parent table tries to replicate, but @@ -97,7 +103,7 @@ BEGIN; --source include/galera_set_sync_point.inc --connection node_2 ---eval $table_admin_command TABLE c1 $table_admin_command_end +--eval $table_admin_command c1 $table_admin_command_end --connection node_1a --source include/galera_wait_sync_point.inc @@ -128,6 +134,11 @@ SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; +--connection node_1 +--disable_warnings +CREATE TABLE IF NOT EXISTS c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk)); +INSERT IGNORE INTO c1 VALUES (1,1); +--enable_warnings --echo ###################################################################### --echo # @@ -149,7 +160,7 @@ BEGIN; --source include/galera_set_sync_point.inc --connection node_2 ---eval $table_admin_command TABLE c2 $table_admin_command_end +--eval $table_admin_command c2 $table_admin_command_end --connection node_1a --source include/galera_wait_sync_point.inc @@ -188,5 +199,5 @@ SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE'; -DROP TABLE c1, c2; +DROP TABLE IF EXISTS c1, c2; DROP TABLE p1, p2; diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test index 4ec866a9f74..b98c6daa73b 100644 --- a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test @@ -17,13 +17,28 @@ SET SESSION wsrep_sync_wait=0; --connection node_1b SET SESSION wsrep_sync_wait=0; ---let $table_admin_command = ALTER +--let $table_admin_command = ALTER TABLE --let $table_admin_command_end = ENGINE=INNODB --source galera_ddl_fk_conflict.inc ---let $table_admin_command = TRUNCATE ---let $table_admin_command_end = +--let $table_admin_command = TRUNCATE TABLE +--let $table_admin_command_end = --source galera_ddl_fk_conflict.inc +--let $table_admin_command = DROP TABLE +--let $table_admin_command_end = +--source galera_ddl_fk_conflict.inc +--source galera_ddl_fk_conflict_with_tmp.inc + +--let $table_admin_command = DROP TABLE IF EXISTS +--let $table_admin_command_end = +--source galera_ddl_fk_conflict.inc +--source galera_ddl_fk_conflict_with_tmp.inc + +--let $table_admin_command = DROP TABLE IF EXISTS nonexisting, +--let $table_admin_command_end = +--source galera_ddl_fk_conflict.inc +--source galera_ddl_fk_conflict_with_tmp.inc + # CHECK and ANALYZE are not affected diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict_with_tmp.inc b/mysql-test/suite/galera/t/galera_ddl_fk_conflict_with_tmp.inc index acf3c54180b..cc6542b96b0 100644 --- a/mysql-test/suite/galera/t/galera_ddl_fk_conflict_with_tmp.inc +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict_with_tmp.inc @@ -35,9 +35,9 @@ BEGIN; --source include/wait_condition.inc --let $wait_condition = SELECT COUNT(*) = 1 FROM c1 --source include/wait_condition.inc -CREATE TEMPORARY TABLE tmp (i int); ---eval $table_admin_command TABLE c1, tmp $table_admin_command_end -DROP TABLE tmp; +CREATE TEMPORARY TABLE tmp1 (i int); +CREATE TEMPORARY TABLE tmp2 (i int); +--eval $table_admin_command tmp1, c1, tmp2 $table_admin_command_end --connection node_1a --source include/galera_wait_sync_point.inc @@ -45,7 +45,7 @@ DROP TABLE tmp; --let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` --connection node_1 -UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; +INSERT INTO p1 VALUES (10, 'TO DEADLOCK'); --send COMMIT --connection node_1a @@ -65,5 +65,6 @@ SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; --connection node_2 SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE'; -DROP TABLE c1; +DROP TABLE IF EXISTS c1; DROP TABLE p1; +DROP TABLE IF EXISTS tmp1, tmp2; diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index d8cb7e8f341..375ae5c9596 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -522,7 +522,7 @@ bool Sql_cmd_alter_table::execute(THD *thd) DBUG_RETURN(TRUE); /* purecov: inspected */ #ifdef WITH_WSREP - if (WSREP(thd) && + if (WSREP(thd) && wsrep_thd_is_local(thd) && (!thd->is_current_stmt_binlog_format_row() || !thd->find_temporary_table(first_table))) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 319d5e6535b..705dc35cdb7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5080,17 +5080,18 @@ mysql_execute_command(THD *thd) lex->create_info.set(DDL_options_st::OPT_IF_EXISTS); #ifdef WITH_WSREP - if (WSREP(thd)) + if (WSREP(thd) && !lex->tmp_table() && wsrep_thd_is_local(thd) && + (!thd->is_current_stmt_binlog_format_row() || + wsrep_table_list_has_non_temp_tables(thd, all_tables))) { - for (TABLE_LIST *table= all_tables; table; table= table->next_global) + wsrep::key_array keys; + if (wsrep_append_fk_parent_table(thd, all_tables, &keys)) { - if (!lex->tmp_table() && - (!thd->is_current_stmt_binlog_format_row() || - !thd->find_temporary_table(table))) - { - WSREP_TO_ISOLATION_BEGIN(NULL, NULL, all_tables); - break; - } + goto wsrep_error_label; + } + if (wsrep_to_isolation_begin(thd, NULL, NULL, all_tables, NULL, &keys)) + { + goto wsrep_error_label; } } #endif /* WITH_WSREP */ diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 6c4fd8c950a..4e324989868 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1349,84 +1349,114 @@ static void wsrep_keys_free(wsrep_key_arr_t* key_arr) * @return 0 if parent table append was successful, non-zero otherwise. */ -bool -wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* keys) +bool wsrep_append_fk_parent_table(THD *thd, TABLE_LIST *tables, + wsrep::key_array *keys) { - bool fail= false; - TABLE_LIST *table; + assert(wsrep_thd_is_local(thd)); - for (table= tables; table; table= table->next_local) + bool fail= false; + Open_table_context ot_ctx(thd, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL); + + for (TABLE_LIST *table= tables; table; table= table->next_local) + { + if (!table->table) { - if (is_temporary_table(table)) + TABLE_LIST *save_next_global= table->next_global; + TABLE_LIST::enum_open_strategy save_open_strategy= table->open_strategy; + table->open_strategy= TABLE_LIST::OPEN_IF_EXISTS; + + Diagnostics_area *da= thd->get_stmt_da(); + Warning_info tmp_wi(thd->query_id, false, true); + da->push_warning_info(&tmp_wi); + + if (open_table(thd, table, &ot_ctx)) { - WSREP_DEBUG("Temporary table %s.%s already opened query=%s", table->db.str, - table->table_name.str, wsrep_thd_query(thd)); - return false; - } - } - - thd->release_transactional_locks(); - uint counter; - MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); - - if (open_tables(thd, &tables, &counter, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL)) - { - WSREP_DEBUG("Unable to open table for FK checks for %s", wsrep_thd_query(thd)); - fail= true; - goto exit; - } - - for (table= tables; table; table= table->next_local) - { - if (!is_temporary_table(table) && table->table) - { - FOREIGN_KEY_INFO *f_key_info; - List f_key_list; - - table->table->file->get_foreign_key_list(thd, &f_key_list); - List_iterator_fast it(f_key_list); - while ((f_key_info=it++)) + if (da->is_error() && da->sql_errno() == ER_UNKNOWN_STORAGE_ENGINE) { - WSREP_DEBUG("appended fkey %s", f_key_info->referenced_table->str); - keys->push_back(wsrep_prepare_key_for_toi(f_key_info->referenced_db->str, - f_key_info->referenced_table->str, - wsrep::key::shared)); + thd->get_stmt_da()->reset_diagnostics_area(); + } + else + { + fail= true; } } + + da->pop_warning_info(); + table->next_global= save_next_global; + table->open_strategy= save_open_strategy; + + if (fail) + { + WSREP_DEBUG("Unable to open table for FK checks for %s", + wsrep_thd_query(thd)); + goto exit; + } } + if (table->table && !is_temporary_table(table)) + { + FOREIGN_KEY_INFO *f_key_info; + List f_key_list; + + table->table->file->get_foreign_key_list(thd, &f_key_list); + List_iterator_fast it(f_key_list); + while ((f_key_info= it++)) + { + WSREP_DEBUG("appended fkey %s", f_key_info->referenced_table->str); + keys->push_back(wsrep_prepare_key_for_toi( + f_key_info->referenced_db->str, f_key_info->referenced_table->str, + wsrep::key::shared)); + } + } + } + exit: - DEBUG_SYNC(thd, "wsrep_append_fk_toi_keys_before_close_tables"); + DEBUG_SYNC(thd, "wsrep_append_fk_toi_keys_before_close_tables"); - /* close the table and release MDL locks */ - close_thread_tables(thd); - thd->mdl_context.rollback_to_savepoint(mdl_savepoint); - for (table= tables; table; table= table->next_local) + /* close the table and release MDL locks */ + close_thread_tables(thd); + thd->mdl_context.rollback_to_savepoint(ot_ctx.start_of_statement_svp()); + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + table->table= NULL; + table->mdl_request.ticket= NULL; + } + + /* + Reopen temporary tables if necessary. + DROP TABLE pre-opens temporary tables, but the corresponding + command does not have the CF_PREOPEN_TMP_TABLES flag set. + */ + const bool preopen_tmp_tables= + thd->lex->sql_command == SQLCOM_DROP_TABLE || + (sql_command_flags[thd->lex->sql_command] & CF_PREOPEN_TMP_TABLES); + + if (preopen_tmp_tables && thd->open_temporary_tables(tables)) + { + WSREP_INFO("Unable to reopen temporary tables after FK checks"); + fail= true; + } + + /* + MDEV-32938: Check if DDL operation has been killed before. + + It may be that during collecting foreign keys this operation gets + BF-aborted by another already-running TOI operation because it got MDL + locks on the same table for checking foreign keys. After + `close_thread_tables()` has been called it's safe to assume that no-one can + BF-abort this operation as it's not holding any MDL locks any more. + */ + if (!fail) + { + mysql_mutex_lock(&thd->LOCK_thd_kill); + if (thd->killed) { - table->table= NULL; - table->next_global= NULL; - table->mdl_request.ticket= NULL; + fail= true; } + mysql_mutex_unlock(&thd->LOCK_thd_kill); + } - /* - MDEV-32938: Check if DDL operation has been killed before. - - It may be that during collecting foreign keys this operation gets BF-aborted - by another already-running TOI operation because it got MDL locks on the same - table for checking foreign keys. - After `close_thread_tables()` has been called it's safe to assume that no-one - can BF-abort this operation as it's not holding any MDL locks any more. - */ - if (!fail) - { - mysql_mutex_lock(&thd->LOCK_thd_kill); - if (thd->killed) - { - fail= true; - } - mysql_mutex_unlock(&thd->LOCK_thd_kill); - } - return fail; + return fail; } bool wsrep_reload_ssl() @@ -3526,3 +3556,15 @@ void wsrep_commit_empty(THD* thd, bool all) } DBUG_VOID_RETURN; } + +bool wsrep_table_list_has_non_temp_tables(THD *thd, TABLE_LIST *tables) +{ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + if (!thd->find_temporary_table(table)) + { + return true; + } + } + return false; +} diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index d67f1fdf479..02d1d7fd248 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -576,6 +576,13 @@ wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table, void wsrep_wait_ready(THD *thd); void wsrep_ready_set(bool ready_value); + +/** + * Returns true if the given list of tables contains at least one + * non-temporary table. + */ +bool wsrep_table_list_has_non_temp_tables(THD *thd, TABLE_LIST *tables); + #else /* !WITH_WSREP */ /* These macros are needed to compile MariaDB without WSREP support From 50cf189717a3fce90a9f2407ed57e59c108f91ef Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Fri, 24 Jan 2025 16:59:46 +0100 Subject: [PATCH 074/118] MDEV-35018 addendum: improved warnings handling Fixed regression after original MDEV-35018 fix related to warnings appearing when running MDEV-26266 test and other possible problems with warnings. --- sql/wsrep_mysqld.cc | 50 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 4e324989868..5792158a5fc 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1342,6 +1342,42 @@ static void wsrep_keys_free(wsrep_key_arr_t* key_arr) key_arr->keys_len= 0; } +class Unknown_storage_engine_handler : public Internal_error_handler +{ +public: + Unknown_storage_engine_handler() + : m_handled_errors(0), m_unhandled_errors(0) + {} + + bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + Sql_condition::enum_warning_level *level, + const char* msg, + Sql_condition ** cond_hdl) override + { + *cond_hdl= NULL; + if (sql_errno == ER_UNKNOWN_STORAGE_ENGINE) + { + m_handled_errors++; + } + else if (*level == Sql_condition::WARN_LEVEL_ERROR) + { + m_unhandled_errors++; + } + return FALSE; + } + + bool safely_trapped_errors() + { + return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); + } + +private: + int m_handled_errors; + int m_unhandled_errors; +}; + /*! * @param thd thread * @param tables list of tables @@ -1365,15 +1401,16 @@ bool wsrep_append_fk_parent_table(THD *thd, TABLE_LIST *tables, TABLE_LIST::enum_open_strategy save_open_strategy= table->open_strategy; table->open_strategy= TABLE_LIST::OPEN_IF_EXISTS; - Diagnostics_area *da= thd->get_stmt_da(); - Warning_info tmp_wi(thd->query_id, false, true); - da->push_warning_info(&tmp_wi); + Unknown_storage_engine_handler no_storage_engine; + thd->push_internal_handler(&no_storage_engine); if (open_table(thd, table, &ot_ctx)) { - if (da->is_error() && da->sql_errno() == ER_UNKNOWN_STORAGE_ENGINE) + if (no_storage_engine.safely_trapped_errors()) { - thd->get_stmt_da()->reset_diagnostics_area(); + Diagnostics_area *da= thd->get_stmt_da(); + da->reset_diagnostics_area(); + da->clear_warning_info(thd->query_id); } else { @@ -1381,7 +1418,8 @@ bool wsrep_append_fk_parent_table(THD *thd, TABLE_LIST *tables, } } - da->pop_warning_info(); + thd->pop_internal_handler(); + table->next_global= save_next_global; table->open_strategy= save_open_strategy; From 552cba92de9952a9a07360a6791d2f63bc06470c Mon Sep 17 00:00:00 2001 From: sjaakola Date: Tue, 31 Dec 2024 08:04:15 +0200 Subject: [PATCH 075/118] MDEV-35710 support for threadpool When client connections use threadpool, i.e. configuration has: thread_handling = pool-of-threads it turned out that during wsrep replication shutdown, not all client connections could be closed. Reason was that some client threads has stmt_da in state DA_EOF, and this state was earlier used to detect if client connection was issuing SHUTDOWN command. To fix this, the connection executing SHUTDOWN is now detected by looking at the actual command being executed: thd->get_command() == COM_SHUTDOWN During replication shutdown, all other connections but the SHUTDOWN executor, are terminated. This commit has new mtr test galera.galera_threadpool, which opens a number of threadpool client connections, and then restarts the node to verify that connections in threadpool are terminated during shutdown. Signed-off-by: Julius Goryavsky --- .../suite/galera/r/galera_threadpool.result | 36 ++++++++++ .../suite/galera/t/galera_threadpool.cnf | 17 +++++ .../suite/galera/t/galera_threadpool.test | 67 +++++++++++++++++++ sql/wsrep_mysqld.cc | 19 ++++-- 4 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suite/galera/r/galera_threadpool.result create mode 100644 mysql-test/suite/galera/t/galera_threadpool.cnf create mode 100644 mysql-test/suite/galera/t/galera_threadpool.test diff --git a/mysql-test/suite/galera/r/galera_threadpool.result b/mysql-test/suite/galera/r/galera_threadpool.result new file mode 100644 index 00000000000..e89e243621a --- /dev/null +++ b/mysql-test/suite/galera/r/galera_threadpool.result @@ -0,0 +1,36 @@ +connection node_2; +connection node_1; +connection node_1; +connection node_2; +connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2c, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2d, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2e, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connection node_2a; +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY, f2 char) ENGINE=InnoDB; +INSERT INTO t1 VALUES (0,'a'); +INSERT INTO t1 VALUES (1,'a'); +connection node_2b; +SELECT * FROM t1; +f1 f2 +0 a +1 a +connection node_2c; +INSERT INTO t1 VALUES (2,'c'); +connection node_2d; +BEGIN; +SELECT * FROM t1; +f1 f2 +0 a +1 a +2 c +connection node_2e; +BEGIN; +UPDATE t1 SET f2='e' WHERE f1=0; +connection node_2; +connection node_1; +connection node_2; +connection node_1; +connection node_2; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_threadpool.cnf b/mysql-test/suite/galera/t/galera_threadpool.cnf new file mode 100644 index 00000000000..c1a1e6a81aa --- /dev/null +++ b/mysql-test/suite/galera/t/galera_threadpool.cnf @@ -0,0 +1,17 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep-node-name="node1" +log_bin=binlog +log_slave_updates=ON +wsrep_sst_method=rsync +thread_handling = pool-of-threads + +[mysqld.2] +wsrep-node-name="node2" +log_bin=binlog +log_slave_updates=ON +wsrep_sst_method=rsync +thread_handling = pool-of-threads + + diff --git a/mysql-test/suite/galera/t/galera_threadpool.test b/mysql-test/suite/galera/t/galera_threadpool.test new file mode 100644 index 00000000000..78b26e6e89f --- /dev/null +++ b/mysql-test/suite/galera/t/galera_threadpool.test @@ -0,0 +1,67 @@ +# +# Tests for threadpool support +# +--source include/galera_cluster.inc + +--let $node_1 = node_1 +--let $node_2 = node_2 + +--source ../galera/include/auto_increment_offset_save.inc + +# +# start connections in node 2, and execute some SQL statements +# leave also open transactions in the node +# +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_2c, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_2d, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_2e, 127.0.0.1, root, , test, $NODE_MYPORT_2 + +--connection node_2a +CREATE TABLE t1 (f1 INTEGER NOT NULL PRIMARY KEY, f2 char) ENGINE=InnoDB; +INSERT INTO t1 VALUES (0,'a'); +INSERT INTO t1 VALUES (1,'a'); + +--connection node_2b +SELECT * FROM t1; + +--connection node_2c +INSERT INTO t1 VALUES (2,'c'); + +--connection node_2d +BEGIN; +SELECT * FROM t1; + +--connection node_2e +BEGIN; +UPDATE t1 SET f2='e' WHERE f1=0; + +# +# Shut down node 2, all open connections should be closed +# +--connection node_2 +--source include/shutdown_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +# And restart the node +--connection node_2 +let $restart_noprint=2; +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +--source include/start_mysqld.inc + +--connection node_1 +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + +--connection node_2 + +DROP TABLE t1; + +# +# Restore auto increment variables. +# +--source ../galera/include/auto_increment_offset_restore.inc diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 5792158a5fc..eea5ade5e3d 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2925,8 +2925,6 @@ static inline bool is_committing_connection(THD *thd) static my_bool have_client_connections(THD *thd, void*) { - DBUG_PRINT("quit",("Informing thread %lld that it's time to die", - (longlong) thd->thread_id)); if (is_client_connection(thd)) { if (thd->killed == KILL_CONNECTION || @@ -2980,13 +2978,18 @@ static my_bool kill_all_threads(THD *thd, THD *caller_thd) /* We skip slave threads & scheduler on this first loop through. */ if (is_client_connection(thd) && thd != caller_thd) { - if (thd->get_stmt_da()->is_eof()) + /* the connection executing SHUTDOWN, should do clean exit, + not aborting here */ + if (thd->get_command() == COM_SHUTDOWN) { + WSREP_DEBUG("leaving SHUTDOWN executing connection alive, thread: %lld", + (longlong) thd->thread_id); return 0; } - + /* replaying connection is killed by signal */ if (is_replaying_connection(thd)) { + WSREP_DEBUG("closing connection is replaying %lld", (longlong) thd->thread_id); thd->set_killed(KILL_CONNECTION_HARD); return 0; } @@ -2995,7 +2998,7 @@ static my_bool kill_all_threads(THD *thd, THD *caller_thd) { /* replicated transactions must be skipped */ WSREP_DEBUG("closing connection %lld", (longlong) thd->thread_id); - /* instead of wsrep_close_thread() we do now soft kill by THD::awake */ + /* instead of wsrep_close_thread() we do now hard kill by THD::awake */ thd->awake(KILL_CONNECTION_HARD); return 0; } @@ -3036,8 +3039,10 @@ void wsrep_close_client_connections(my_bool wait_to_end, THD* except_caller_thd) */ server_threads.iterate(kill_remaining_threads, except_caller_thd); - DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", THD_count::value())); - WSREP_DEBUG("waiting for client connections to close: %u", THD_count::value()); + DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", + THD_count::value())); + WSREP_DEBUG("waiting for client connections to close: %u", + THD_count::value()); while (wait_to_end && server_threads.iterate(have_client_connections)) { From d598ee3cf952e528a8b42261959360de637add2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 26 Sep 2024 08:43:45 +0300 Subject: [PATCH 076/118] MDEV-32780 : galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() Test changes only because assertion reported is not reproducable anymore. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/disabled.def | 3 --- mysql-test/suite/galera/t/galera_as_slave_replay.test | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 5b92b282ece..fcaf38a3d7b 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -9,6 +9,3 @@ # Do not use any TAB characters for whitespace. # ############################################################################## - -galera_as_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() -galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep::transaction::before_rollback() diff --git a/mysql-test/suite/galera/t/galera_as_slave_replay.test b/mysql-test/suite/galera/t/galera_as_slave_replay.test index 73fd7b3ff29..f6dd3f89f3e 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_replay.test +++ b/mysql-test/suite/galera/t/galera_as_slave_replay.test @@ -10,6 +10,7 @@ --source include/have_debug.inc --source include/have_debug_sync.inc --source include/galera_have_debug_sync.inc +--source include/log_bin.inc --connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 @@ -87,7 +88,7 @@ SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; INSERT INTO test.t1 VALUES (2, 'b'); # -# send the update from master, this will succeed here, beceuase of async replication. +# send the update from master, this will succeed here, because of async replication. # async replication will apply this in node 2 and pause before commit phase, --connection node_3 --error 0 From d77b9a4925c971364707d435028add41e8015173 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Sat, 25 Jan 2025 11:05:29 -0700 Subject: [PATCH 077/118] =?UTF-8?q?MDEV-34355:=20rpl.rpl=5Fsemi=5Fsync=5Fn?= =?UTF-8?q?o=5Fmissed=5Fack=5Fafter=5Fadd=5Fslave=20=E2=80=98server=5F3=20?= =?UTF-8?q?should=20have=20sent=E2=80=A6=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MDEV-35477 incorrectly reverted the original test fix of MDEV-34355, thinking it superseded that fix. It is still needed though. Pasting the content of the original patchโ€™s commit message, as it is still relevant (and the method to reproduce the test failure still works). โ€œโ€โ€ The problem is that the test could query the status variable Rpl_semi_sync_slave_send_ack before the slave actually updated it. This would result in an immediate --die assertion killing the rest of the test. The bottom of this commit message has a small patch that can be applied to reproduce the test failure. This patch fixes the test failure by waiting for the variable to be updated before querying its value. diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc index 9ddd4c5c8d7..60538079fce 100644 --- a/sql/semisync_slave.cc +++ b/sql/semisync_slave.cc @@ -303,7 +303,10 @@ int Repl_semi_sync_slave::slave_reply(Master_info *mi) reply_res= DBUG_EVALUATE_IF("semislave_failed_net_flush", 1, net_flush(net)); if (!reply_res) + { + sleep(1); rpl_semi_sync_slave_send_ack++; + } } DBUG_RETURN(reply_res); } โ€œโ€โ€ --- .../rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test b/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test index 9d8f87b4345..1a7b3abfde0 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test @@ -86,6 +86,10 @@ if (`SELECT $slave1_sent_ack`) --connection server_3 --echo # Verifying server_3 did send ACK +--let $status_var= Rpl_semi_sync_slave_send_ack +--let $status_var_comparsion= > +--let $status_var_value= 0 +--source include/wait_for_status_var.inc --let $slave2_sent_ack= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_slave_send_ack', Value, 1) if (`SELECT NOT $slave2_sent_ack`) { From 47f87c5f88beccd1a450f96108a93462b35d7c73 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Fri, 24 Jan 2025 17:08:04 +0100 Subject: [PATCH 078/118] MDEV-20281 "[ERROR] Failed to write to mysql.slow_log:" without error reason Add "backup" (in case of absence issued by error) reasons for failed logging. --- mysql-test/main/slowlog_integrity.result | 108 ++++++++++++++++++++++ mysql-test/main/slowlog_integrity.test | 113 +++++++++++++++++++++++ sql/log.cc | 65 +++++++++++-- 3 files changed, 280 insertions(+), 6 deletions(-) create mode 100644 mysql-test/main/slowlog_integrity.result create mode 100644 mysql-test/main/slowlog_integrity.test diff --git a/mysql-test/main/slowlog_integrity.result b/mysql-test/main/slowlog_integrity.result new file mode 100644 index 00000000000..f65fbf49c03 --- /dev/null +++ b/mysql-test/main/slowlog_integrity.result @@ -0,0 +1,108 @@ +# +# MDEV-20281 "[ERROR] Failed to write to mysql.slow_log:" without +# error reason +# +call mtr.add_suppression("Failed to write to mysql.slow_log:"); +SET @old_slow_query_log= @@global.slow_query_log; +SET @old_log_output= @@global.log_output; +SET @old_long_query_time= @@long_query_time; +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; +SET SESSION long_query_time= 0; +select 1 from dual; +1 +1 +show create table mysql.slow_log; +Table Create Table +slow_log CREATE TABLE `slow_log` ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `rows_affected` bigint(20) unsigned NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='Slow log' +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= "FILE"; +SET GLOBAL slow_query_log= OFF; +drop table mysql.slow_log; +# one field missing +CREATE TABLE mysql.slow_log ( +`start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), +`user_host` mediumtext NOT NULL, +`query_time` time(6) NOT NULL, +`lock_time` time(6) NOT NULL, +`rows_sent` bigint(20) unsigned NOT NULL, +`rows_examined` bigint(20) unsigned NOT NULL, +`db` varchar(512) NOT NULL, +`last_insert_id` int(11) NOT NULL, +`insert_id` int(11) NOT NULL, +`server_id` int(10) unsigned NOT NULL, +`sql_text` mediumtext NOT NULL, +`thread_id` bigint(21) unsigned NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='Slow log'; +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; +SET SESSION long_query_time= 0; +select 1 from dual; +1 +1 +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= "FILE"; +SET GLOBAL slow_query_log= OFF; +drop table mysql.slow_log; +# crazy types +CREATE TABLE mysql.slow_log ( +`start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), +`user_host` ENUM('apple','orange','pear') NOT NULL, +`query_time` ENUM('apple','orange','pear') NOT NULL, +`lock_time` ENUM('apple','orange','pear') NOT NULL, +`rows_sent` ENUM('apple','orange','pear') NOT NULL, +`rows_examined` ENUM('apple','orange','pear') NOT NULL, +`db` ENUM('apple','orange','pear') NOT NULL, +`last_insert_id` ENUM('apple','orange','pear') NOT NULL, +`insert_id` ENUM('apple','orange','pear') NOT NULL, +`server_id` ENUM('apple','orange','pear') NOT NULL, +`sql_text` ENUM('apple','orange','pear') NOT NULL, +`thread_id` ENUM('apple','orange','pear') NOT NULL, +`rows_affected` ENUM('apple','orange','pear') NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='Slow log'; +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; +SET SESSION long_query_time= 0; +select 1 from dual; +1 +1 +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= "FILE"; +SET GLOBAL slow_query_log= OFF; +drop table mysql.slow_log; +# restore normal slow log table +CREATE TABLE mysql.slow_log ( +`start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), +`user_host` mediumtext NOT NULL, +`query_time` time(6) NOT NULL, +`lock_time` time(6) NOT NULL, +`rows_sent` bigint(20) unsigned NOT NULL, +`rows_examined` bigint(20) unsigned NOT NULL, +`db` varchar(512) NOT NULL, +`last_insert_id` int(11) NOT NULL, +`insert_id` int(11) NOT NULL, +`server_id` int(10) unsigned NOT NULL, +`sql_text` mediumtext NOT NULL, +`thread_id` bigint(21) unsigned NOT NULL, +`rows_affected` bigint(20) unsigned NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='Slow log'; +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= @old_log_output; +SET @@global.slow_query_log= @old_slow_query_log; +FOUND 2 /incorrect number of fields in the log table/ in mysqld.1.err +FOUND 2 /Can't write data \(possible incorrect log table structure\)/ in mysqld.1.err +# End of 10.5 tests diff --git a/mysql-test/main/slowlog_integrity.test b/mysql-test/main/slowlog_integrity.test new file mode 100644 index 00000000000..8db3a5ee881 --- /dev/null +++ b/mysql-test/main/slowlog_integrity.test @@ -0,0 +1,113 @@ +source include/not_embedded.inc; + +--echo # +--echo # MDEV-20281 "[ERROR] Failed to write to mysql.slow_log:" without +--echo # error reason +--echo # + + +call mtr.add_suppression("Failed to write to mysql.slow_log:"); + +--disable_ps_protocol +SET @old_slow_query_log= @@global.slow_query_log; +SET @old_log_output= @@global.log_output; +SET @old_long_query_time= @@long_query_time; +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; +SET SESSION long_query_time= 0; + +select 1 from dual; + +show create table mysql.slow_log; + +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= "FILE"; +SET GLOBAL slow_query_log= OFF; + +drop table mysql.slow_log; + +--echo # one field missing +CREATE TABLE mysql.slow_log ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='Slow log'; + +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; +SET SESSION long_query_time= 0; + +select 1 from dual; + +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= "FILE"; +SET GLOBAL slow_query_log= OFF; + +drop table mysql.slow_log; + +--echo # crazy types +CREATE TABLE mysql.slow_log ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` ENUM('apple','orange','pear') NOT NULL, + `query_time` ENUM('apple','orange','pear') NOT NULL, + `lock_time` ENUM('apple','orange','pear') NOT NULL, + `rows_sent` ENUM('apple','orange','pear') NOT NULL, + `rows_examined` ENUM('apple','orange','pear') NOT NULL, + `db` ENUM('apple','orange','pear') NOT NULL, + `last_insert_id` ENUM('apple','orange','pear') NOT NULL, + `insert_id` ENUM('apple','orange','pear') NOT NULL, + `server_id` ENUM('apple','orange','pear') NOT NULL, + `sql_text` ENUM('apple','orange','pear') NOT NULL, + `thread_id` ENUM('apple','orange','pear') NOT NULL, + `rows_affected` ENUM('apple','orange','pear') NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='Slow log'; + +SET GLOBAL log_output= "TABLE"; +SET GLOBAL slow_query_log= ON; +SET SESSION long_query_time= 0; + +select 1 from dual; + +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= "FILE"; +SET GLOBAL slow_query_log= OFF; + +drop table mysql.slow_log; + +--echo # restore normal slow log table +CREATE TABLE mysql.slow_log ( + `start_time` timestamp(6) NOT NULL DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6), + `user_host` mediumtext NOT NULL, + `query_time` time(6) NOT NULL, + `lock_time` time(6) NOT NULL, + `rows_sent` bigint(20) unsigned NOT NULL, + `rows_examined` bigint(20) unsigned NOT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(10) unsigned NOT NULL, + `sql_text` mediumtext NOT NULL, + `thread_id` bigint(21) unsigned NOT NULL, + `rows_affected` bigint(20) unsigned NOT NULL +) ENGINE=CSV DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='Slow log'; +SET @@long_query_time= @old_long_query_time; +SET @@global.log_output= @old_log_output; +SET @@global.slow_query_log= @old_slow_query_log; +--enable_ps_protocol + +--let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN=incorrect number of fields in the log table +--source include/search_pattern_in_file.inc +--let SEARCH_PATTERN=Can't write data \(possible incorrect log table structure\) +--source include/search_pattern_in_file.inc + +--echo # End of 10.5 tests diff --git a/sql/log.cc b/sql/log.cc index 32a1436f9a6..e459e3a5b52 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -694,6 +694,7 @@ bool Log_to_csv_event_handler:: { TABLE_LIST table_list; TABLE *table; + const char *cause= 0; bool result= TRUE; bool need_close= FALSE; bool need_pop= FALSE; @@ -728,13 +729,19 @@ bool Log_to_csv_event_handler:: need_pop= TRUE; if (!(table= open_log_table(thd, &table_list, &open_tables_backup))) + { + cause= "can't open file"; goto err; + } need_close= TRUE; if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || table->file->ha_rnd_init_with_error(0)) + { + cause= "can't initialize table handler"; goto err; + } need_rnd_end= TRUE; @@ -753,12 +760,20 @@ bool Log_to_csv_event_handler:: /* check that all columns exist */ if (table->s->fields < 6) + { + cause= "incorrect number of fields in the log table"; goto err; + } DBUG_ASSERT(table->field[0]->type() == MYSQL_TYPE_TIMESTAMP); - table->field[0]->store_timestamp( - hrtime_to_my_time(event_time), hrtime_sec_part(event_time)); + if (table->field[0]->store_timestamp(hrtime_to_my_time(event_time), + hrtime_sec_part(event_time))) + { + cause= "Can't write data (possible incorrect log table structure)"; + goto err; + } + /* do a write */ if (table->field[1]->store(user_host, user_host_len, client_cs) || @@ -766,7 +781,10 @@ bool Log_to_csv_event_handler:: table->field[3]->store((longlong) global_system_variables.server_id, TRUE) || table->field[4]->store(command_type, command_type_len, client_cs)) + { + cause= "Can't write data (possible incorrect log table structure)"; goto err; + } /* A positive return value in store() means truncation. @@ -774,7 +792,10 @@ bool Log_to_csv_event_handler:: */ table->field[5]->flags|= FIELDFLAG_HEX_ESCAPE; if (table->field[5]->store(sql_text, sql_text_len, client_cs) < 0) + { + cause= "Can't write data (possible incorrect log table structure)"; goto err; + } /* mark all fields as not null */ table->field[1]->set_notnull(); @@ -790,14 +811,22 @@ bool Log_to_csv_event_handler:: } if (table->file->ha_write_row(table->record[0])) + { + cause= "Can't write record"; goto err; + } result= FALSE; err: if (result && !thd->killed) + { + const char *msg= error_handler.message(); + if (!msg || !msg[0]) + msg= cause; sql_print_error("Failed to write to mysql.general_log: %s", - error_handler.message()); + msg); + } if (need_rnd_end) { @@ -850,6 +879,8 @@ bool Log_to_csv_event_handler:: { TABLE_LIST table_list; TABLE *table; + const char *cause= 0; + const char *msg; bool result= TRUE; bool need_close= FALSE; bool need_rnd_end= FALSE; @@ -874,13 +905,19 @@ bool Log_to_csv_event_handler:: TL_WRITE_CONCURRENT_INSERT); if (!(table= open_log_table(thd, &table_list, &open_tables_backup))) + { + cause= "can't open file"; goto err; + } need_close= TRUE; if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || table->file->ha_rnd_init_with_error(0)) + { + cause= "can't initialize table handler"; goto err; + } need_rnd_end= TRUE; @@ -891,12 +928,19 @@ bool Log_to_csv_event_handler:: /* check that all columns exist */ if (table->s->fields < 13) + { + cause= "incorrect number of fields in the log table"; goto err; + } + + // It can be used in 13 places below so assign it here + cause= "Can't write data (possible incorrect log table structure)"; /* store the time and user values */ DBUG_ASSERT(table->field[0]->type() == MYSQL_TYPE_TIMESTAMP); - table->field[0]->store_timestamp( - hrtime_to_my_time(current_time), hrtime_sec_part(current_time)); + if(table->field[0]->store_timestamp(hrtime_to_my_time(current_time), + hrtime_sec_part(current_time))) + goto err; if (table->field[1]->store(user_host, user_host_len, client_cs)) goto err; @@ -976,9 +1020,13 @@ bool Log_to_csv_event_handler:: (longlong) thd->get_stmt_da()->affected_rows() : 0, TRUE)) goto err; + cause= 0; // just for safety if (table->file->ha_write_row(table->record[0])) + { + cause= "Can't write record"; goto err; + } result= FALSE; @@ -986,8 +1034,13 @@ err: thd->pop_internal_handler(); if (result && !thd->killed) + { + msg= error_handler.message(); + if (!msg || !msg[0]) + msg= cause; sql_print_error("Failed to write to mysql.slow_log: %s", - error_handler.message()); + msg); + } if (need_rnd_end) { From cb5dd76959859e465828672dedff6c7ee0811a06 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Sat, 25 Jan 2025 09:58:56 -0700 Subject: [PATCH 079/118] MDEV-35938: rpl.rpl_parallel_gco_wait_kill fails - "Can't initialize replace ..." Test rpl.rpl_parallel_gco_wait_kill has a race condition where it identifies that SQL using its state as "Slave has read all relay log", and immediately tries to save the thread id of the SQL thread by querying for threads with that same state. However, the state of the SQL thread may change in-between this time, leading to the query that saves the SQL thread finding no thread id that matches that state. Commit 3ee6f69d49a58422f994f51a0bd7a0cb1242a3dd aimed to fix this in 10.11+ by simplifying the query string to "%relay log%"; however, it could still fail (though less often). This commit instead changes the query to find the SQL thread from using some state, to using the command "Slave_SQL", which will not change --- mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test b/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test index d918b2ea692..f4d9777f75e 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_gco_wait_kill.test @@ -297,7 +297,7 @@ SET GLOBAL slave_parallel_threads=10; # Find the thread id of the driver SQL thread that we want to kill. --let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Slave has read all relay log%' --source include/wait_condition.inc ---let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Slave has read all relay log%'` +--let $thd_id= `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND LIKE 'Slave_SQL'` SET @old_max_queued= @@GLOBAL.slave_parallel_max_queued; SET GLOBAL slave_parallel_max_queued=9000; From e33064e0fcf991ec2d0535396a6061dad90c2a3e Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Thu, 16 Jan 2025 01:44:06 +0100 Subject: [PATCH 080/118] MDEV-27769 Assertion failed in Field::ptr_in_record upon UPDATE in ORACLE mode table->move_fields has some limitations: 1. It cannot be used in cascade 2. It should always have a restoring pair In this case, an error has occurred before the field ptr was restored, returning from the function in that state. Even in case of an error, the table can be reused afterwards and table->field[i]->ptr is not reset in between. The solution is to restore the field pointers immanently whenever they've been deviated. Also add an assertion that ensures that table fields are restored after the use in close_thread_tables. --- .../main/simultaneous_assignment.result | 12 ++++ mysql-test/main/simultaneous_assignment.test | 16 +++++ .../suite/compat/oracle/r/update.result | 16 +++++ mysql-test/suite/compat/oracle/t/update.test | 19 ++++++ sql/sql_base.cc | 58 ++++++++++++++----- 5 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 mysql-test/suite/compat/oracle/r/update.result create mode 100644 mysql-test/suite/compat/oracle/t/update.test diff --git a/mysql-test/main/simultaneous_assignment.result b/mysql-test/main/simultaneous_assignment.result index 67cb58ba6af..2c01eb1c6c2 100644 --- a/mysql-test/main/simultaneous_assignment.result +++ b/mysql-test/main/simultaneous_assignment.result @@ -220,3 +220,15 @@ INDEXES Indexes TRANSACTIONS Transactions TRIGGERS Triggers DROP TABLE ft2; +# +# MDEV-27769 Assertion failed in Field::ptr_in_record upon UPDATE +# (duplicate) MDEV-35404 Assertion failed in Field::ptr_in_record +# +CREATE TABLE t (s geometry, t text); +INSERT INTO t () VALUES (); +UPDATE t SET t = '', s = 0; +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +UPDATE t SET t = '', s = 0; +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +ALTER TABLE t force; +DROP TABLE t; diff --git a/mysql-test/main/simultaneous_assignment.test b/mysql-test/main/simultaneous_assignment.test index aea454855f5..5b1badcaad1 100644 --- a/mysql-test/main/simultaneous_assignment.test +++ b/mysql-test/main/simultaneous_assignment.test @@ -205,3 +205,19 @@ UPDATE ft2 SET copy = UPPER(copy), copy2= copy; SELECT * FROM ft2; DROP TABLE ft2; + +--echo # +--echo # MDEV-27769 Assertion failed in Field::ptr_in_record upon UPDATE +--echo # (duplicate) MDEV-35404 Assertion failed in Field::ptr_in_record +--echo # +CREATE TABLE t (s geometry, t text); + +INSERT INTO t () VALUES (); +--error ER_CANT_CREATE_GEOMETRY_OBJECT +UPDATE t SET t = '', s = 0; +--error ER_CANT_CREATE_GEOMETRY_OBJECT +UPDATE t SET t = '', s = 0; + +ALTER TABLE t force; + +DROP TABLE t; diff --git a/mysql-test/suite/compat/oracle/r/update.result b/mysql-test/suite/compat/oracle/r/update.result new file mode 100644 index 00000000000..d7585e8e61d --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/update.result @@ -0,0 +1,16 @@ +SET @save_sql_mode=@@global.sql_mode; +SET sql_mode=ORACLE; +SET GLOBAL sql_mode='ORACLE'; +# MDEV-27769 Assertion failed in Field::ptr_in_record upon UPDATE +CREATE TABLE t (s geometry, t text) engine innodb; +Warnings: +Warning 1286 Unknown storage engine 'innodb' +Warning 1266 Using storage engine MyISAM for table 't' +INSERT IGNORE INTO t () VALUES (); +UPDATE IGNORE t SET t= '', s = 0; +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +UPDATE IGNORE t SET t= '', s = 0; +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +ALTER TABLE t force; +DROP TABLE t; +SET GLOBAL sql_mode=@save_sql_mode; diff --git a/mysql-test/suite/compat/oracle/t/update.test b/mysql-test/suite/compat/oracle/t/update.test new file mode 100644 index 00000000000..389a27f3dbd --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/update.test @@ -0,0 +1,19 @@ +SET @save_sql_mode=@@global.sql_mode; +SET sql_mode=ORACLE; +SET GLOBAL sql_mode='ORACLE'; + + +--echo # MDEV-27769 Assertion failed in Field::ptr_in_record upon UPDATE +CREATE TABLE t (s geometry, t text) engine innodb; +INSERT IGNORE INTO t () VALUES (); +--error ER_CANT_CREATE_GEOMETRY_OBJECT +UPDATE IGNORE t SET t= '', s = 0; +--error ER_CANT_CREATE_GEOMETRY_OBJECT +UPDATE IGNORE t SET t= '', s = 0; + +ALTER TABLE t force; + +DROP TABLE t; + +# Test cleanup +SET GLOBAL sql_mode=@save_sql_mode; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index bb73dcef975..149cd541341 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -760,6 +760,22 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, } } +static inline bool check_field_pointers(const TABLE *table) +{ + for (Field **pf= table->field; *pf; pf++) + { + Field *f= *pf; + if (f->ptr < table->record[0] || f->ptr > table->record[0] + + table->s->reclength) + return false; + if (f->null_ptr && + (f->null_ptr < table->record[0] || f->null_ptr > table->record[0] + + table->s->reclength)) + return false; + } + return true; +} + /* Close all tables used by the current substatement, or all tables @@ -809,6 +825,8 @@ int close_thread_tables(THD *thd) DBUG_PRINT("tcache", ("table: '%s' query_id: %lu", table->s->table_name.str, (ulong) table->query_id)); + DBUG_SLOW_ASSERT(check_field_pointers(table)); + if (thd->locked_tables_mode) { #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -8465,6 +8483,24 @@ err_no_arena: } +static void unwind_stored_field_offsets(const List &fields, Field *end) +{ + for (Item &item_field: fields) + { + Field *f= item_field.field_for_view_update()->field; + if (f == end) + break; + + if (f->stored_in_db()) + { + TABLE *table= f->table; + f->move_field_offset((my_ptrdiff_t) (table->record[0] - + table->record[1])); + } + } +} + + /****************************************************************************** ** Fill a record with data (for INSERT or UPDATE) ** Returns : 1 if some field has wrong type @@ -8520,7 +8556,7 @@ fill_record(THD *thd, TABLE *table_arg, List &fields, List &values, if (!(field= fld->field_for_view_update())) { my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name.str); - goto err; + goto err_unwind_fields; } value=v++; DBUG_ASSERT(value); @@ -8548,7 +8584,7 @@ fill_record(THD *thd, TABLE *table_arg, List &fields, List &values, unlikely(value->save_in_field(rfield, 0) < 0) && !ignore_errors) { my_message(ER_UNKNOWN_ERROR, ER_THD(thd, ER_UNKNOWN_ERROR), MYF(0)); - goto err; + goto err_unwind_fields; } /* In sql MODE_SIMULTANEOUS_ASSIGNMENT, @@ -8563,20 +8599,7 @@ fill_record(THD *thd, TABLE *table_arg, List &fields, List &values, } if (update && thd->variables.sql_mode & MODE_SIMULTANEOUS_ASSIGNMENT) - { - // restore fields pointers on record[0] - f.rewind(); - while ((fld= f++)) - { - rfield= fld->field_for_view_update()->field; - if (rfield->stored_in_db()) - { - table= rfield->table; - rfield->move_field_offset((my_ptrdiff_t) (table->record[0] - - table->record[1])); - } - } - } + unwind_stored_field_offsets(fields, NULL); if (update) table_arg->evaluate_update_default_function(); @@ -8594,6 +8617,9 @@ fill_record(THD *thd, TABLE *table_arg, List &fields, List &values, thd->abort_on_warning= save_abort_on_warning; thd->no_errors= save_no_errors; DBUG_RETURN(thd->is_error()); +err_unwind_fields: + if (update && thd->variables.sql_mode & MODE_SIMULTANEOUS_ASSIGNMENT) + unwind_stored_field_offsets(fields, rfield); err: DBUG_PRINT("error",("got error")); thd->abort_on_warning= save_abort_on_warning; From ecaedbe299fe11372c36319f9b732b81e9f54883 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Sat, 12 Oct 2024 21:32:18 +0200 Subject: [PATCH 081/118] MDEV-33658 1/2 Refactoring: extract Key length initialization mysql_prepare_create_table: Extract a Key initialization part that relates to length calculation and long unique index designation. append_system_key_parts call also moves there. Move this initialization before the duplicate elimination. Extract WITHOUT OVERPLAPS check into a separate function. It had to be moved earlier in the code to preserve the order of the error checks, as in the tests. --- .../r/binlog_spurious_ddl_errors.result | 2 +- .../binlog/t/binlog_spurious_ddl_errors.test | 2 +- .../suite/innodb/r/innodb-wl5522-1.result | 2 + mysql-test/suite/innodb_gis/r/1.result | 2 + .../suite/innodb_gis/r/point_basic.result | 4 +- mysql-test/suite/innodb_gis/t/1.test | 4 +- .../innodb_zip/r/index_large_prefix_8k.result | 3 + sql/sql_class.cc | 3 +- sql/sql_class.h | 5 +- sql/sql_table.cc | 586 ++++++++++-------- 10 files changed, 362 insertions(+), 251 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result b/mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result index 798bd8ab853..39c0bd52fac 100644 --- a/mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result +++ b/mysql-test/suite/binlog/r/binlog_spurious_ddl_errors.result @@ -38,7 +38,7 @@ CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE; ALTER TABLE t_stmt ADD COLUMN b INT; CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1); CREATE INDEX i ON t_stmt(a); -ERROR 42000: Too many key parts specified; max 0 parts allowed +ERROR 42000: Specified key was too long; max key length is 0 bytes CREATE TABLE t_stmt_new ENGINE = EXAMPLE SELECT * FROM t_stmt; ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-based logging DROP TABLE t_stmt; diff --git a/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test b/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test index 29a860764a9..5a015c2b8eb 100644 --- a/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test +++ b/mysql-test/suite/binlog/t/binlog_spurious_ddl_errors.test @@ -75,7 +75,7 @@ ALTER TABLE t_stmt ADD COLUMN b INT; CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1); ---error ER_TOO_MANY_KEY_PARTS +--error ER_TOO_LONG_KEY CREATE INDEX i ON t_stmt(a); --error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-1.result b/mysql-test/suite/innodb/r/innodb-wl5522-1.result index 42c0631dd29..72d7268244f 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-1.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-1.result @@ -659,6 +659,8 @@ NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 15000 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 16000 ALTER TABLE testdb_wl5522.t1 ADD INDEX idx1 (col_1); ALTER TABLE testdb_wl5522.t1 ADD INDEX idx6 (col_1(255)); +Warnings: +Note 1831 Duplicate index `idx6`. This is deprecated and will be disallowed in a future release ALTER TABLE testdb_wl5522.t1 ADD INDEX idx10 (col_10(255)); SELECT col_1 = REPEAT("col1_00001",10), diff --git a/mysql-test/suite/innodb_gis/r/1.result b/mysql-test/suite/innodb_gis/r/1.result index 909051cc54e..9522ab1d41f 100644 --- a/mysql-test/suite/innodb_gis/r/1.result +++ b/mysql-test/suite/innodb_gis/r/1.result @@ -1075,6 +1075,8 @@ col1 POINT, col2 POINT ); CREATE SPATIAL INDEX idx0 ON t2 (col1, col2); +ERROR 42000: Key column 'col1' doesn't exist in table +CREATE SPATIAL INDEX idx0 ON t2 (col0, col2); ERROR HY000: Incorrect arguments to SPATIAL INDEX CREATE TABLE t4 ( col0 INTEGER NOT NULL, diff --git a/mysql-test/suite/innodb_gis/r/point_basic.result b/mysql-test/suite/innodb_gis/r/point_basic.result index bda5ae59238..fd7c8ac180e 100644 --- a/mysql-test/suite/innodb_gis/r/point_basic.result +++ b/mysql-test/suite/innodb_gis/r/point_basic.result @@ -1562,7 +1562,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p); ERROR HY000: Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed") show warnings; Level Code Message -Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. +Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is only prefix index in the referenced table where the referenced columns appear as the first columns. Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint for `child` ALTER TABLE parent DROP INDEX idx1; @@ -1570,7 +1570,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p); Got one of the listed errors show warnings; Level Code Message -Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. +Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is only prefix index in the referenced table where the referenced columns appear as the first columns. Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed") Warning 1215 Cannot add foreign key constraint for `child` ALTER TABLE child DROP INDEX idx2; diff --git a/mysql-test/suite/innodb_gis/t/1.test b/mysql-test/suite/innodb_gis/t/1.test index 411cb10602b..711bc971945 100644 --- a/mysql-test/suite/innodb_gis/t/1.test +++ b/mysql-test/suite/innodb_gis/t/1.test @@ -839,8 +839,10 @@ CREATE TABLE t3 ( ); # --error ER_TOO_MANY_KEY_PARTS ---error ER_WRONG_ARGUMENTS +--error ER_KEY_COLUMN_DOES_NOT_EXITS CREATE SPATIAL INDEX idx0 ON t2 (col1, col2); +--error ER_WRONG_ARGUMENTS +CREATE SPATIAL INDEX idx0 ON t2 (col0, col2); CREATE TABLE t4 ( diff --git a/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result b/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result index 925bd3f8f9c..4451b149406 100644 --- a/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result +++ b/mysql-test/suite/innodb_zip/r/index_large_prefix_8k.result @@ -171,9 +171,11 @@ Note 1071 Specified key was too long; max key length is 1536 bytes create index idx3 on worklog5743_8(a2(3072)); Warnings: Note 1071 Specified key was too long; max key length is 1536 bytes +Note 1831 Duplicate index `idx3`. This is deprecated and will be disallowed in a future release show warnings; Level Code Message Note 1071 Specified key was too long; max key length is 1536 bytes +Note 1831 Duplicate index `idx3`. This is deprecated and will be disallowed in a future release create index idx4 on worklog5743_8(a1, a2(1533)); ERROR 42000: Specified key was too long; max key length is 1536 bytes show warnings; @@ -355,6 +357,7 @@ Note 1071 Specified key was too long; max key length is 1536 bytes create index idx2 on worklog5743(a(3072)); Warnings: Note 1071 Specified key was too long; max key length is 1536 bytes +Note 1831 Duplicate index `idx2`. This is deprecated and will be disallowed in a future release SET sql_mode= default; show create table worklog5743; Table Create Table diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 66f689c5312..e6ff4d87690 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -176,7 +176,8 @@ Key::Key(const Key &rhs, MEM_ROOT *mem_root) name(rhs.name), option_list(rhs.option_list), generated(rhs.generated), invisible(false), - without_overlaps(rhs.without_overlaps), old(rhs.old), period(rhs.period) + without_overlaps(rhs.without_overlaps), old(rhs.old), length(rhs.length), + period(rhs.period) { list_copy_and_replace_each_value(columns, mem_root); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 03860e5ff4e..6dcc406e294 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -424,6 +424,7 @@ public: bool invisible; bool without_overlaps; bool old; + uint length; Lex_ident period; Key(enum Keytype type_par, const LEX_CSTRING *name_arg, @@ -431,7 +432,7 @@ public: :DDL_options(ddl_options), type(type_par), key_create_info(default_key_create_info), name(*name_arg), option_list(NULL), generated(generated_arg), - invisible(false), without_overlaps(false), old(false) + invisible(false), without_overlaps(false), old(false), length(0) { key_create_info.algorithm= algorithm_arg; } @@ -442,7 +443,7 @@ public: :DDL_options(ddl_options), type(type_par), key_create_info(*key_info_arg), columns(*cols), name(*name_arg), option_list(create_opt), generated(generated_arg), - invisible(false), without_overlaps(false), old(false) + invisible(false), without_overlaps(false), old(false), length(0) {} Key(const Key &rhs, MEM_ROOT *mem_root); virtual ~Key() = default; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 2162850172b..c7ee3f83647 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3558,6 +3558,303 @@ key_add_part_check_null(const handler *file, KEY *key_info, } +static +my_bool key_check_without_overlaps(THD *thd, HA_CREATE_INFO *create_info, + Alter_info *alter_info, + Key &key) +{ + DBUG_ENTER("key_check_without_overlaps"); + if (!key.without_overlaps) + DBUG_RETURN(FALSE); + // append_system_key_parts is already called, so we should check all the + // columns except the last two. + const auto &period_start= create_info->period_info.period.start; + const auto &period_end= create_info->period_info.period.end; + List_iterator part_it_forwarded(key.columns); + List_iterator part_it(key.columns); + part_it_forwarded++; + part_it_forwarded++; + while (part_it_forwarded++) + { + Key_part_spec *key_part= part_it++; + + if (period_start.streq(key_part->field_name) + || period_end.streq(key_part->field_name)) + { + my_error(ER_KEY_CONTAINS_PERIOD_FIELDS, MYF(0), key.name.str, + key_part->field_name.str); + DBUG_RETURN(TRUE); + } + } + + if (key.key_create_info.algorithm == HA_KEY_ALG_HASH || + key.key_create_info.algorithm == HA_KEY_ALG_LONG_HASH) + + { + my_error(ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS, MYF(0), key.name.str); + DBUG_RETURN(TRUE); + } + for (Key &key2: alter_info->key_list) + { + if (key2.type != Key::FOREIGN_KEY) + continue; + DBUG_ASSERT(&key != &key2); + const Foreign_key &fk= (Foreign_key&)key2; + if (fk.update_opt != FK_OPTION_CASCADE) + continue; + for (Key_part_spec& kp: key.columns) + { + for (Key_part_spec& kp2: fk.columns) + { + if (kp.field_name.streq(kp2.field_name)) + { + my_error(ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS, MYF(0), key.name.str); + DBUG_RETURN(TRUE); + } + } + } + } + create_info->period_info.unique_keys++; + + DBUG_RETURN(FALSE); +} + +static +my_bool init_key_part_spec(THD *thd, Alter_info *alter_info, + const handler *file, + const Key &key, Key_part_spec &kp, + uint max_key_length, uint max_key_part_length, + bool *is_hash_field_needed) +{ + DBUG_ENTER("init_key_part_spec"); + + const Lex_ident &field_name= kp.field_name; + Create_field *column= NULL; + + for (Create_field &c: alter_info->create_list) + if (c.field_name.streq(field_name)) + column= &c; + + /* + Either field is not present or field visibility is > INVISIBLE_USER + */ + if (!column || (column->invisible > INVISIBLE_USER && !kp.generated)) + { + my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), field_name.str); + DBUG_RETURN(TRUE); + } + + if (DBUG_EVALUATE_IF("test_invisible_index", 0, 1) + && column->invisible > INVISIBLE_USER + && !(column->flags & VERS_SYSTEM_FIELD) && !key.invisible) + { + my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str); + DBUG_RETURN(TRUE); + } + + const Type_handler *type_handler= column->type_handler(); + switch(key.type) + { + case Key::FULLTEXT: + if (type_handler->Key_part_spec_init_ft(&kp, *column)) + { + my_error(ER_BAD_FT_COLUMN, MYF(0), field_name.str); + DBUG_RETURN(-1); + } + break; + + case Key::SPATIAL: + if (type_handler->Key_part_spec_init_spatial(&kp, *column)) + DBUG_RETURN(TRUE); + break; + + case Key::PRIMARY: + if (column->vcol_info) + { + my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0)); + DBUG_RETURN(TRUE); + } + if (type_handler->Key_part_spec_init_primary(&kp, *column, file)) + DBUG_RETURN(TRUE); + break; + + case Key::MULTIPLE: + if (type_handler->Key_part_spec_init_multiple(&kp, *column, file)) + DBUG_RETURN(TRUE); + break; + + case Key::FOREIGN_KEY: + if (type_handler->Key_part_spec_init_foreign(&kp, *column, file)) + DBUG_RETURN(TRUE); + break; + + case Key::UNIQUE: + if (type_handler->Key_part_spec_init_unique(&kp, *column, file, + is_hash_field_needed)) + DBUG_RETURN(TRUE); + break; + } + + uint key_part_length= type_handler->calc_key_length(*column); + + if (kp.length) + { + if (f_is_blob(column->pack_flag)) + { + key_part_length= MY_MIN(kp.length, + blob_length_by_type(column->real_field_type()) + * column->charset->mbmaxlen); + if (key_part_length > max_key_length || + key_part_length > max_key_part_length) + { + if (key.type == Key::MULTIPLE) + { + key_part_length= MY_MIN(max_key_length, max_key_part_length); + /* not a critical problem */ + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY), + key_part_length); + /* Align key length to multibyte char boundary */ + key_part_length-= key_part_length % column->charset->mbmaxlen; + } + } + } + // Catch invalid use of partial keys + else if (!f_is_geom(column->pack_flag) && + // is the key partial? + kp.length != key_part_length && + // is prefix length bigger than field length? + (kp.length > key_part_length || + // can the field have a partial key? + !type_handler->type_can_have_key_part() || + // a packed field can't be used in a partial key + f_is_packed(column->pack_flag) || + // does the storage engine allow prefixed search? + ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) && + // and is this a 'unique' key? + (key.type == Key::PRIMARY || key.type == Key::UNIQUE)))) + { + my_message(ER_WRONG_SUB_KEY, ER_THD(thd, ER_WRONG_SUB_KEY), MYF(0)); + DBUG_RETURN(TRUE); + } + else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS)) + key_part_length= kp.length; + } + else if (key_part_length == 0 && (column->flags & NOT_NULL_FLAG) && + !*is_hash_field_needed) + { + my_error(ER_WRONG_KEY_COLUMN, MYF(0), file->table_type(), field_name.str); + DBUG_RETURN(TRUE); + } + if (key_part_length > max_key_part_length && key.type != Key::FULLTEXT) + { + if (key.type == Key::MULTIPLE) + { + key_part_length= max_key_part_length; + /* not a critical problem */ + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY), + key_part_length); + /* Align key length to multibyte char boundary */ + key_part_length-= key_part_length % column->charset->mbmaxlen; + } + else if (key.type != Key::UNIQUE) + { + key_part_length= MY_MIN(max_key_length, max_key_part_length); + my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length); + DBUG_RETURN(TRUE); + } + } + + if (key.type == Key::UNIQUE && key_part_length > MY_MIN(max_key_length, + max_key_part_length)) + *is_hash_field_needed= true; + + /* We can not store key_part_length more than 2^16 - 1 in frm. */ + if (*is_hash_field_needed && kp.length > UINT_MAX16) + { + my_error(ER_TOO_LONG_KEYPART, MYF(0), UINT_MAX16); + DBUG_RETURN(TRUE); + } + + kp.length= key_part_length; + + DBUG_RETURN(FALSE); +} + + +/** + @brief Initialize the key length and algorithm (if long hash). + + This function does: + 1. Append system key parts (versioning, periods) + 2. Call Type_handler key_part initialization function. + 3. Determine the length of each key_part. + 4. Calculate the total Key length. + 5. Determine if the key is long unique based on its length + smd result from type handler. It'll be saved in + key_create_info.algorithm as HA_KEY_ALG_LONG_HASH. + + @return FALSE OK + @return TRUE error + */ +static +my_bool init_key_info(THD *thd, Alter_info *alter_info, + HA_CREATE_INFO *create_info, + const handler *file) +{ + DBUG_ENTER("init_key_info"); + uint max_key_length= file->max_key_length(); + uint max_key_part_length= file->max_key_part_length(); + + for (Key &key: alter_info->key_list) + { + if (key.type == Key::FOREIGN_KEY) + continue; + + int parts_added= append_system_key_parts(thd, create_info, &key); + if (parts_added < 0) + DBUG_RETURN(true); + + bool is_hash_field_needed= false; + for (Key_part_spec &kp: key.columns) + { + if (init_key_part_spec(thd, alter_info, file, key, kp, + max_key_length, max_key_part_length, + &is_hash_field_needed)) + DBUG_RETURN(TRUE); + + key.length+= kp.length; + if (key.length > max_key_length && key.type == Key::UNIQUE) + is_hash_field_needed= true; // for case "a BLOB UNIQUE" + + if (key.length > max_key_length && key.type != Key::FULLTEXT && + !is_hash_field_needed) + { + my_error(ER_TOO_LONG_KEY, MYF(0), max_key_length); + DBUG_RETURN(TRUE); + } + + KEY_CREATE_INFO *key_cinfo= &key.key_create_info; + + if (is_hash_field_needed) + { + if (key_cinfo->algorithm == HA_KEY_ALG_UNDEF) + key_cinfo->algorithm= HA_KEY_ALG_LONG_HASH; + + if (key_cinfo->algorithm != HA_KEY_ALG_HASH && + key_cinfo->algorithm != HA_KEY_ALG_LONG_HASH) + { + my_error(ER_TOO_LONG_KEY, MYF(0), max_key_length); + DBUG_RETURN(TRUE); + } + } + } + } + DBUG_RETURN(FALSE); +} + + /* Preparation for table creation @@ -3592,7 +3889,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, { const char *key_name; Create_field *sql_field,*dup_field; - uint field,null_fields,max_key_length; + uint field,null_fields; ulong record_offset= 0; KEY_PART_INFO *key_part_info; int field_no,dup_no; @@ -3603,7 +3900,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, int select_field_count= C_CREATE_SELECT(create_table_mode); bool tmp_table= create_table_mode == C_ALTER_TABLE; const bool create_simple= thd->lex->create_simple(); - bool is_hash_field_needed= false; const Column_derived_attributes dattr(create_info->default_table_charset); const Column_bulk_alter_attributes battr(create_info->alter_table_convert_to_charset); @@ -3639,7 +3935,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, create_info->versioned()); null_fields= 0; create_info->varchar= 0; - max_key_length= file->max_key_length(); /* Handle creation of sequences */ if (create_info->sequence) @@ -3838,6 +4133,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, /* special marker for keys to be ignored */ static char ignore_key[1]; + if (init_key_info(thd, alter_info, create_info, file)) + DBUG_RETURN(TRUE); + /* Calculate number of key segements */ *key_count= 0; @@ -3967,10 +4265,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, key_info->name.length= strlen(key_name); key->name= key_info->name; - int parts_added= append_system_key_parts(thd, create_info, key); - if (parts_added < 0) - DBUG_RETURN(true); - key_parts += parts_added; key_info++; } tmp=file->max_keys(); @@ -3989,11 +4283,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, key_number=0; for (; (key=key_iterator++) ; key_number++) { - uint key_length=0; Create_field *auto_increment_key= 0; Key_part_spec *column; - is_hash_field_needed= false; + bool is_hash_field_needed= key->key_create_info.algorithm + == HA_KEY_ALG_LONG_HASH; if (key->name.str == ignore_key) { /* ignore redundant keys */ @@ -4004,6 +4298,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, break; } + if (key_check_without_overlaps(thd, create_info, alter_info, *key)) + DBUG_RETURN(true); + switch (key->type) { case Key::MULTIPLE: key_info->flags= 0; @@ -4034,10 +4331,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (key->generated) key_info->flags|= HA_GENERATED_KEY; + key_info->key_length= key->length; key_info->user_defined_key_parts=(uint8) key->columns.elements; key_info->key_part=key_part_info; key_info->usable_key_parts= key_number; key_info->algorithm= key->key_create_info.algorithm; + key_info->without_overlaps= key->without_overlaps; key_info->option_list= key->option_list; extend_option_list(thd, create_info->db_type, !key->old, &key_info->option_list, create_info->db_type->index_options); @@ -4121,37 +4420,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, CHARSET_INFO *ft_key_charset=0; // for FULLTEXT for (uint column_nr=0 ; (column=cols++) ; column_nr++) { - Key_part_spec *dup_column; - it.rewind(); field=0; while ((sql_field=it++) && lex_string_cmp(scs, &column->field_name, &sql_field->field_name)) field++; - /* - Either field is not present or field visibility is > INVISIBLE_USER - */ - if (!sql_field || (sql_field->invisible > INVISIBLE_USER && - !column->generated)) - { - my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str); - DBUG_RETURN(TRUE); - } - if (sql_field->invisible > INVISIBLE_USER && - !(sql_field->flags & VERS_SYSTEM_FIELD) && - !key->invisible && DBUG_EVALUATE_IF("test_invisible_index", 0, 1)) - { - my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str); - DBUG_RETURN(TRUE); - } - while ((dup_column= cols2++) != column) - { - if (!lex_string_cmp(scs, &column->field_name, &dup_column->field_name)) - { - my_error(ER_DUP_FIELDNAME, MYF(0), column->field_name.str); - DBUG_RETURN(TRUE); - } - } if (sql_field->compression_method()) { @@ -4161,12 +4434,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } cols2.rewind(); - switch(key->type) { - + switch(key->type) + { case Key::FULLTEXT: - if (sql_field->type_handler()->Key_part_spec_init_ft(column, - *sql_field) || - (ft_key_charset && sql_field->charset != ft_key_charset)) + if (ft_key_charset && sql_field->charset != ft_key_charset) { my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str); DBUG_RETURN(-1); @@ -4174,64 +4445,46 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ft_key_charset= sql_field->charset; break; - case Key::SPATIAL: - if (sql_field->type_handler()->Key_part_spec_init_spatial(column, - *sql_field) || - sql_field->check_vcol_for_key(thd)) - DBUG_RETURN(TRUE); - if (!(sql_field->flags & NOT_NULL_FLAG)) - { - my_message(ER_SPATIAL_CANT_HAVE_NULL, - ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0)); - DBUG_RETURN(TRUE); - } - break; - case Key::PRIMARY: - if (sql_field->vcol_info) - { - my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0)); - DBUG_RETURN(TRUE); - } - if (sql_field->type_handler()->Key_part_spec_init_primary(column, - *sql_field, - file)) - DBUG_RETURN(TRUE); if (!(sql_field->flags & NOT_NULL_FLAG)) { - /* Implicitly set primary key fields to NOT NULL for ISO conf. */ + /* Implicitly set primary key fields to NOT NULL for ISO conformance. */ sql_field->flags|= NOT_NULL_FLAG; sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL; null_fields--; } break; - case Key::MULTIPLE: - if (sql_field->type_handler()->Key_part_spec_init_multiple(column, - *sql_field, - file) || - sql_field->check_vcol_for_key(thd) || - key_add_part_check_null(file, key_info, sql_field, column)) - DBUG_RETURN(TRUE); - break; - - case Key::FOREIGN_KEY: - if (sql_field->type_handler()->Key_part_spec_init_foreign(column, - *sql_field, - file) || - sql_field->check_vcol_for_key(thd) || - key_add_part_check_null(file, key_info, sql_field, column)) - DBUG_RETURN(TRUE); - break; - case Key::UNIQUE: - if (sql_field->type_handler()->Key_part_spec_init_unique(column, - *sql_field, file, - &is_hash_field_needed) || - sql_field->check_vcol_for_key(thd) || - key_add_part_check_null(file, key_info, sql_field, column)) + case Key::MULTIPLE: + case Key::FOREIGN_KEY: + if (key_add_part_check_null(file, key_info, sql_field, column)) + DBUG_RETURN(TRUE); + if (sql_field->check_vcol_for_key(thd)) DBUG_RETURN(TRUE); break; + + case Key::SPATIAL: + if (!(sql_field->flags & NOT_NULL_FLAG)) + { + my_message(ER_SPATIAL_CANT_HAVE_NULL, + ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0)); + DBUG_RETURN(TRUE); + } + if (sql_field->check_vcol_for_key(thd)) + DBUG_RETURN(TRUE); + break; + } + + for (const Key_part_spec &kp2: key->columns) + { + if (column == &kp2) + break; + if (kp2.field_name.streq(column->field_name)) + { + my_error(ER_DUP_FIELDNAME, MYF(0), column->field_name.str); + DBUG_RETURN(TRUE); + } } if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) @@ -4246,111 +4499,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, key_part_info->fieldnr= field; key_part_info->offset= (uint16) sql_field->offset; key_part_info->key_type=sql_field->pack_flag; - uint key_part_length= sql_field->type_handler()-> - calc_key_length(*sql_field); - - if (column->length) - { - if (f_is_blob(sql_field->pack_flag)) - { - key_part_length= MY_MIN(column->length, - blob_length_by_type(sql_field->real_field_type()) - * sql_field->charset->mbmaxlen); - if (key_part_length > max_key_length || - key_part_length > file->max_key_part_length()) - { - if (key->type == Key::MULTIPLE) - { - key_part_length= MY_MIN(max_key_length, file->max_key_part_length()); - /* not a critical problem */ - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY), - key_part_length); - /* Align key length to multibyte char boundary */ - key_part_length-= key_part_length % sql_field->charset->mbmaxlen; - } - } - } - // Catch invalid use of partial keys - else if (!f_is_geom(sql_field->pack_flag) && - // is the key partial? - column->length != key_part_length && - // is prefix length bigger than field length? - (column->length > key_part_length || - // can the field have a partial key? - !sql_field->type_handler()->type_can_have_key_part() || - // a packed field can't be used in a partial key - f_is_packed(sql_field->pack_flag) || - // does the storage engine allow prefixed search? - ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) && - // and is this a 'unique' key? - (key_info->flags & HA_NOSAME)))) - { - my_message(ER_WRONG_SUB_KEY, ER_THD(thd, ER_WRONG_SUB_KEY), MYF(0)); - DBUG_RETURN(TRUE); - } - else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS)) - key_part_length= column->length; - } - else if (key_part_length == 0 && (sql_field->flags & NOT_NULL_FLAG) && - !is_hash_field_needed) - { - my_error(ER_WRONG_KEY_COLUMN, MYF(0), file->table_type(), - column->field_name.str); - DBUG_RETURN(TRUE); - } - if (key_part_length > file->max_key_part_length() && - key->type != Key::FULLTEXT) - { - if (key->type == Key::MULTIPLE) - { - key_part_length= file->max_key_part_length(); - /* not a critical problem */ - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY), - key_part_length); - /* Align key length to multibyte char boundary */ - key_part_length-= key_part_length % sql_field->charset->mbmaxlen; - } - else - { - if (key->type != Key::UNIQUE) - { - key_part_length= MY_MIN(max_key_length, file->max_key_part_length()); - my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length); - DBUG_RETURN(TRUE); - } - } - } - - if (key->type == Key::UNIQUE - && key_part_length > MY_MIN(max_key_length, - file->max_key_part_length())) - is_hash_field_needed= true; - - /* We can not store key_part_length more then 2^16 - 1 in frm */ - if (is_hash_field_needed && column->length > UINT_MAX16) - { - my_error(ER_TOO_LONG_KEYPART, MYF(0), UINT_MAX16); - DBUG_RETURN(TRUE); - } - else - key_part_info->length= (uint16) key_part_length; + key_part_info->length= column->length; /* Use packed keys for long strings on the first column */ if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) && !((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) && - (key_part_length >= KEY_DEFAULT_PACK_LENGTH) && + (column->length >= KEY_DEFAULT_PACK_LENGTH) && !is_hash_field_needed) { key_info->flags|= sql_field->type_handler()->KEY_pack_flags(column_nr); } /* Check if the key segment is partial, set the key flag accordingly */ - if (key_part_length != sql_field->type_handler()-> + if (column->length != sql_field->type_handler()-> calc_key_length(*sql_field) && - key_part_length != sql_field->type_handler()->max_octet_length()) + column->length != sql_field->type_handler()->max_octet_length()) key_info->flags|= HA_KEY_HAS_PART_KEY_SEG; - key_length+= key_part_length; key_part_info++; } if (!key_info->name.str || check_column_name(key_info->name.str)) @@ -4360,15 +4523,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, } if (key->type == Key::UNIQUE && !(key_info->flags & HA_NULL_PART_KEY)) unique_key=1; - key_info->key_length=(uint16) key_length; - if (key_info->key_length > max_key_length && key->type == Key::UNIQUE) - is_hash_field_needed= true; // for case "a BLOB UNIQUE" - if (key_length > max_key_length && key->type != Key::FULLTEXT && - !is_hash_field_needed) - { - my_error(ER_TOO_LONG_KEY, MYF(0), max_key_length); - DBUG_RETURN(TRUE); - } /* Check long unique keys */ if (is_hash_field_needed) @@ -4380,12 +4534,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, key_info->name.str); DBUG_RETURN(TRUE); } - if (key_info->algorithm != HA_KEY_ALG_UNDEF && - key_info->algorithm != HA_KEY_ALG_HASH ) - { - my_error(ER_TOO_LONG_KEY, MYF(0), max_key_length); - DBUG_RETURN(TRUE); - } } if (is_hash_field_needed || (key_info->algorithm == HA_KEY_ALG_HASH && @@ -4425,40 +4573,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, // Check if a duplicate index is defined. check_duplicate_key(thd, key, key_info, &alter_info->key_list); - key_info->without_overlaps= key->without_overlaps; - if (key_info->without_overlaps) - { - if (key_info->algorithm == HA_KEY_ALG_HASH || - key_info->algorithm == HA_KEY_ALG_LONG_HASH) - - { -without_overlaps_err: - my_error(ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS, MYF(0), key_info->name.str); - DBUG_RETURN(true); - } - key_iterator2.rewind(); - while ((key2 = key_iterator2++)) - { - if (key2->type != Key::FOREIGN_KEY) - continue; - DBUG_ASSERT(key != key2); - Foreign_key *fk= (Foreign_key*) key2; - if (fk->update_opt != FK_OPTION_CASCADE) - continue; - for (Key_part_spec& kp: key->columns) - { - for (Key_part_spec& kp2: fk->columns) - { - if (!lex_string_cmp(scs, &kp.field_name, &kp2.field_name)) - { - goto without_overlaps_err; - } - } - } - } - create_info->period_info.unique_keys++; - } - key_info++; } @@ -4886,20 +5000,6 @@ static int append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info, my_error(ER_PERIOD_NOT_FOUND, MYF(0), key->period.str); return -1; } - - const auto &period_start= create_info->period_info.period.start; - const auto &period_end= create_info->period_info.period.end; - List_iterator part_it(key->columns); - while (Key_part_spec *key_part= part_it++) - { - if (period_start.streq(key_part->field_name) - || period_end.streq(key_part->field_name)) - { - my_error(ER_KEY_CONTAINS_PERIOD_FIELDS, MYF(0), key->name.str, - key_part->field_name.str); - return -1; - } - } const auto &period= create_info->period_info.period; key->columns.push_back(new (thd->mem_root) Key_part_spec(&period.end, 0, true)); From e7cc1a30470f650481d7ba069e122e95548c7a47 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Sun, 13 Oct 2024 19:28:51 +0200 Subject: [PATCH 082/118] MDEV-33658 2/2 Cannot add a foreign key on a table with a matching long UNIQUE Cannot add a foreign key on a table with a long UNIQUE multi-column index, that contains a foreign key as a prefix. Check that index algorithms match during the "generated" keys duplicate removal. --- mysql-test/main/long_unique_bugs.result | 21 +++++++++++++++++++++ mysql-test/main/long_unique_bugs.test | 15 +++++++++++++++ sql/sql_class.cc | 12 +++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/long_unique_bugs.result b/mysql-test/main/long_unique_bugs.result index 5ee8b65fbf6..6da1a1978e8 100644 --- a/mysql-test/main/long_unique_bugs.result +++ b/mysql-test/main/long_unique_bugs.result @@ -741,6 +741,27 @@ insert into t1 select seq from seq_1_to_100; alter table t1 add partition (partition p3 values less than (maxvalue)); alter table t1 force; drop table t1; +# +# MDEV-33658 cannot add a foreign key on a table with a long UNIQUE +# multi-column index, that contains a foreign key as a prefix. +# +create table a (id int primary key) engine = innodb; +create table b (id int, +long_text varchar(1000), +constraint unique_b unique key (id, long_text) +) engine=innodb default charset utf8mb4; +alter table b add constraint b_fk_id foreign key (id) references a (id); +show create table b; +Table Create Table +b CREATE TABLE `b` ( + `id` int(11) DEFAULT NULL, + `long_text` varchar(1000) DEFAULT NULL, + UNIQUE KEY `unique_b` (`id`,`long_text`) USING HASH, + KEY `b_fk_id` (`id`), + CONSTRAINT `b_fk_id` FOREIGN KEY (`id`) REFERENCES `a` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci +drop table b; +drop table a; # veirfy that duplicate has unique is detected create table t1 (a blob unique); alter table t1 add constraint constraint_1 unique (a); diff --git a/mysql-test/main/long_unique_bugs.test b/mysql-test/main/long_unique_bugs.test index 3fbe2a6b777..7f487d4947f 100644 --- a/mysql-test/main/long_unique_bugs.test +++ b/mysql-test/main/long_unique_bugs.test @@ -721,6 +721,21 @@ alter table t1 force; drop table t1; +--echo # +--echo # MDEV-33658 cannot add a foreign key on a table with a long UNIQUE +--echo # multi-column index, that contains a foreign key as a prefix. +--echo # +create table a (id int primary key) engine = innodb; +create table b (id int, + long_text varchar(1000), + constraint unique_b unique key (id, long_text) + ) engine=innodb default charset utf8mb4; + +alter table b add constraint b_fk_id foreign key (id) references a (id); +show create table b; +drop table b; +drop table a; + --echo # veirfy that duplicate has unique is detected create table t1 (a blob unique); alter table t1 add constraint constraint_1 unique (a); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index e6ff4d87690..e49c920abed 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -204,7 +204,7 @@ Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root) /* Test if a foreign key (= generated key) is a prefix of the given key - (ignoring key name, key type and order of columns) + (ignoring key name and type, but minding the algorithm) NOTES: This is only used to test if an index for a FOREIGN KEY exists @@ -219,6 +219,16 @@ Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root) bool is_foreign_key_prefix(Key *a, Key *b) { + ha_key_alg a_alg= a->key_create_info.algorithm; + ha_key_alg b_alg= b->key_create_info.algorithm; + + // The real algorithm in InnoDB will be BTREE if none was given by user. + a_alg= a_alg == HA_KEY_ALG_UNDEF ? HA_KEY_ALG_BTREE : a_alg; + b_alg= b_alg == HA_KEY_ALG_UNDEF ? HA_KEY_ALG_BTREE : b_alg; + + if (a_alg != b_alg) + return false; + /* Ensure that 'a' is the generated key */ if (a->generated) { From 765458c93cd52f83f5dbb725124bbee24c903041 Mon Sep 17 00:00:00 2001 From: Nikita Malyavin Date: Tue, 17 Nov 2020 04:59:41 +0100 Subject: [PATCH 083/118] fix my_error usage --- sql/item_strfunc.cc | 10 +++++----- sql/sql_acl.cc | 2 +- sql/wsrep_mysqld.cc | 7 +++++-- storage/innobase/handler/ha_innodb.cc | 5 ++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 0e9c01c7a7e..ae936d0703d 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -5327,7 +5327,7 @@ String *Item_func_wsrep_last_written_gtid::val_str_ascii(String *str) { if (gtid_str.alloc(WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1)) { - my_error(ER_OUTOFMEMORY, WSREP_MAX_WSREP_SERVER_GTID_STR_LEN); + my_error(ER_OUTOFMEMORY, MYF(0), WSREP_MAX_WSREP_SERVER_GTID_STR_LEN); null_value= TRUE; return 0; } @@ -5352,7 +5352,7 @@ String *Item_func_wsrep_last_seen_gtid::val_str_ascii(String *str) { if (gtid_str.alloc(WSREP_MAX_WSREP_SERVER_GTID_STR_LEN+1)) { - my_error(ER_OUTOFMEMORY, WSREP_MAX_WSREP_SERVER_GTID_STR_LEN); + my_error(ER_OUTOFMEMORY, MYF(0), WSREP_MAX_WSREP_SERVER_GTID_STR_LEN); null_value= TRUE; return 0; } @@ -5397,7 +5397,7 @@ longlong Item_func_wsrep_sync_wait_upto::val_int() if (!(gtid_list= gtid_parse_string_to_list(gtid_str->ptr(), gtid_str->length(), &count))) { - my_error(ER_INCORRECT_GTID_STATE, MYF(0), func_name()); + my_error(ER_INCORRECT_GTID_STATE, MYF(0)); null_value= TRUE; return 0; } @@ -5409,12 +5409,12 @@ longlong Item_func_wsrep_sync_wait_upto::val_int() wait_gtid_ret= wsrep_gtid_server.wait_gtid_upto(gtid_list[0].seq_no, timeout); if ((wait_gtid_ret == ETIMEDOUT) || (wait_gtid_ret == ETIME)) { - my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0), func_name()); + my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); ret= 0; } else if (wait_gtid_ret == ENOMEM) { - my_error(ER_OUTOFMEMORY, MYF(0), func_name()); + my_error(ER_OUTOFMEMORY, MYF(0), sizeof(std::pair)); ret= 0; } } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index c7f2a8d3d46..a7e9ea7d6f7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3345,7 +3345,7 @@ end: switch (result) { case ER_INVALID_CURRENT_USER: - my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename); + my_error(ER_INVALID_CURRENT_USER, MYF(0)); break; case ER_INVALID_ROLE: /* Role doesn't exist at all */ diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index eea5ade5e3d..8c2a2bda31b 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2468,8 +2468,11 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table, if (!thd->is_error()) { - my_error(ER_LOCK_DEADLOCK, MYF(0), "WSREP replication failed. Check " - "your wsrep connection state and retry the query."); + push_warning_printf(thd, Sql_state_errno_level::WARN_LEVEL_ERROR, + ER_LOCK_DEADLOCK, + "WSREP replication failed. Check " + "your wsrep connection state and retry the query."); + my_error(ER_LOCK_DEADLOCK, MYF(0)); } } rc= -1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 68e3f6c7b56..890cdbaf429 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -9530,8 +9530,7 @@ ha_innobase::ft_init_ext( /* If tablespace is discarded, we should return here */ if (!ft_table->space) { - my_error(ER_TABLESPACE_MISSING, MYF(0), table->s->db.str, - table->s->table_name.str); + my_error(ER_TABLESPACE_MISSING, MYF(0), ft_table->name.m_name); return(NULL); } @@ -13892,7 +13891,7 @@ ha_innobase::rename_table( error = DB_ERROR; } else if (error == DB_LOCK_WAIT_TIMEOUT) { - my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0), to); + my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); error = DB_LOCK_WAIT; } From dffe3d1fb24f33047c53feae4ff2f4cb429ee31c Mon Sep 17 00:00:00 2001 From: Galina Shalygina Date: Sun, 26 Jan 2025 20:39:38 -0800 Subject: [PATCH 084/118] MDEV-35910 Conditions with SP local variables are not pushed into derived table This bug prevented building conditions that could be pushed into a derived table if the derived table was used in a query of a stored procedure and the conditions contained local variables of the procedure. This could lead to a slow execution of the procedure. Also in some cases the bug prevented building conditions that could be pushed from the HAVING condition into the WHERE condition of a query if the conditions to be built used local variables of a stored procedure. To failure to build such pushable conditions was due to lack of a proper implementation of the virtual method to copy items for the objects of the class Item_splocal. Approved by Igor Babaev who had to change the original fix that just added the regular copying of the nodes of the Item_splocal class to take into account the wrappers do_get_copy() and do_build_clone() introduced after the fix had been prepared. He also changed the test case to demonstrate that the fix was really needed for pushdown from HAVING into WHERE. --- mysql-test/main/sp.result | 176 ++++++++++++++++++++++++++++++++++++++ mysql-test/main/sp.test | 88 +++++++++++++++++++ sql/item.h | 5 +- 3 files changed, 267 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result index 1b3405e47b1..204af23f09f 100644 --- a/mysql-test/main/sp.result +++ b/mysql-test/main/sp.result @@ -8974,3 +8974,179 @@ DROP PROCEDURE p1; DROP PROCEDURE p2; # End of 10.4 tests # +# +# MDEV-35910: Pushdown of conditions with local SP variables +# into materialized derived table +# Pushdown of conditions with local variables from HAVING +# into WHERE +# +CREATE TABLE t1( +pk INT PRIMARY KEY AUTO_INCREMENT, +a INT, +b INT +); +INSERT INTO t1(a,b) VALUES (1, 2), (3, 2), (4, 5); +INSERT INTO t1(a,b) VALUES (3, 7), (4, 1), (3, 4); +CREATE PROCEDURE pushdownDerivedSp() +BEGIN +DECLARE localA INT DEFAULT 1; +DECLARE localB INT DEFAULT 2; +SELECT dt.a +FROM ( +SELECT t1.a, MIN(t1.b) as minB +FROM t1 +GROUP BY t1.a +) AS dt +WHERE dt.minB = localB AND dt.a = localA + localB; +END$$ +CREATE PROCEDURE explainPushdownDerivedSp() +BEGIN +DECLARE localA INT DEFAULT 1; +DECLARE localB INT DEFAULT 2; +EXPLAIN format=json SELECT dt.a +FROM ( +SELECT t1.a, MIN(t1.b) as minB +FROM t1 +GROUP BY t1.a +) AS dt +WHERE dt.minB = localB AND dt.a = localA + localB; +END$$ +CREATE PROCEDURE pushdownFromHavingSp() +BEGIN +DECLARE localA INT DEFAULT 1; +DECLARE localB INT DEFAULT 2; +SELECT t1.a, SUM(b) +FROM t1 +GROUP BY t1.a +HAVING t1.a > localA AND SUM(b) > 10 OR t1.a <= localB AND SUM(b) <= 2; +END$$ +CREATE PROCEDURE explainPushdownFromHavingSp() +BEGIN +DECLARE localA INT DEFAULT 1; +DECLARE localB INT DEFAULT 2; +EXPLAIN format=json +SELECT t1.a, SUM(b) +FROM t1 +GROUP BY t1.a +HAVING t1.a > localA AND SUM(b) > 10 OR t1.a <= localB AND SUM(b) <= 2; +END$$ +CALL pushdownDerivedSp(); +a +3 +set statement optimizer_switch='condition_pushdown_for_derived=off' +for CALL pushdownDerivedSp(); +a +3 +CALL explainPushdownDerivedSp(); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 6, + "filtered": 100, + "attached_condition": "dt.minB = (localB@1) and dt.a = (localA@0 + localB@1)", + "materialized": { + "query_block": { + "select_id": 2, + "having_condition": "minB = (localB@1)", + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 6, + "filtered": 100, + "attached_condition": "t1.a = (localA@0 + localB@1)" + } + } + } + } + } +} +set statement optimizer_switch='condition_pushdown_for_derived=off' for +CALL explainPushdownDerivedSp(); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 6, + "filtered": 100, + "attached_condition": "dt.minB = (localB@1) and dt.a = (localA@0 + localB@1)", + "materialized": { + "query_block": { + "select_id": 2, + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 6, + "filtered": 100 + } + } + } + } + } + } + } +} +CALL pushdownFromHavingSp(); +a SUM(b) +1 2 +3 13 +set statement optimizer_switch='condition_pushdown_from_having=off' for +CALL pushdownFromHavingSp(); +a SUM(b) +1 2 +3 13 +CALL explainPushdownFromHavingSp(); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "having_condition": "t1.a > (localA@0) and sum(t1.b) > 10 or t1.a <= (localB@1) and sum(t1.b) <= 2", + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 6, + "filtered": 100, + "attached_condition": "t1.a > (localA@0) or t1.a <= (localB@1)" + } + } + } + } +} +set statement optimizer_switch='condition_pushdown_from_having=off' for +CALL explainPushdownFromHavingSp(); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "having_condition": "t1.a > (localA@0) and sum(t1.b) > 10 or t1.a <= (localB@1) and sum(t1.b) <= 2", + "filesort": { + "sort_key": "t1.a", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 6, + "filtered": 100 + } + } + } + } +} +DROP PROCEDURE pushdownDerivedSp; +DROP PROCEDURE explainPushdownDerivedSp; +DROP PROCEDURE pushdownFromHavingSp; +DROP PROCEDURE explainPushdownFromHavingSp; +DROP TABLE t1; +# End of 10.5 tests diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test index c1e107b69e1..7799e34210a 100644 --- a/mysql-test/main/sp.test +++ b/mysql-test/main/sp.test @@ -10593,3 +10593,91 @@ DROP PROCEDURE p2; --echo # End of 10.4 tests --echo # +--echo # +--echo # MDEV-35910: Pushdown of conditions with local SP variables +--echo # into materialized derived table +--echo # Pushdown of conditions with local variables from HAVING +--echo # into WHERE +--echo # + +CREATE TABLE t1( + pk INT PRIMARY KEY AUTO_INCREMENT, + a INT, + b INT +); +INSERT INTO t1(a,b) VALUES (1, 2), (3, 2), (4, 5); +INSERT INTO t1(a,b) VALUES (3, 7), (4, 1), (3, 4); + +DELIMITER $$; +CREATE PROCEDURE pushdownDerivedSp() +BEGIN + DECLARE localA INT DEFAULT 1; + DECLARE localB INT DEFAULT 2; + SELECT dt.a + FROM ( + SELECT t1.a, MIN(t1.b) as minB + FROM t1 + GROUP BY t1.a + ) AS dt + WHERE dt.minB = localB AND dt.a = localA + localB; +END$$ + +CREATE PROCEDURE explainPushdownDerivedSp() +BEGIN + DECLARE localA INT DEFAULT 1; + DECLARE localB INT DEFAULT 2; + EXPLAIN format=json SELECT dt.a + FROM ( + SELECT t1.a, MIN(t1.b) as minB + FROM t1 + GROUP BY t1.a + ) AS dt + WHERE dt.minB = localB AND dt.a = localA + localB; +END$$ + +CREATE PROCEDURE pushdownFromHavingSp() +BEGIN + DECLARE localA INT DEFAULT 1; + DECLARE localB INT DEFAULT 2; + SELECT t1.a, SUM(b) + FROM t1 + GROUP BY t1.a + HAVING t1.a > localA AND SUM(b) > 10 OR t1.a <= localB AND SUM(b) <= 2; +END$$ + +CREATE PROCEDURE explainPushdownFromHavingSp() +BEGIN + DECLARE localA INT DEFAULT 1; + DECLARE localB INT DEFAULT 2; + EXPLAIN format=json + SELECT t1.a, SUM(b) + FROM t1 + GROUP BY t1.a + HAVING t1.a > localA AND SUM(b) > 10 OR t1.a <= localB AND SUM(b) <= 2; +END$$ + +DELIMITER ;$$ + +CALL pushdownDerivedSp(); +set statement optimizer_switch='condition_pushdown_for_derived=off' +for CALL pushdownDerivedSp(); + +CALL explainPushdownDerivedSp(); +set statement optimizer_switch='condition_pushdown_for_derived=off' for +CALL explainPushdownDerivedSp(); + +CALL pushdownFromHavingSp(); +set statement optimizer_switch='condition_pushdown_from_having=off' for +CALL pushdownFromHavingSp(); + +CALL explainPushdownFromHavingSp(); +set statement optimizer_switch='condition_pushdown_from_having=off' for +CALL explainPushdownFromHavingSp(); + +DROP PROCEDURE pushdownDerivedSp; +DROP PROCEDURE explainPushdownDerivedSp; +DROP PROCEDURE pushdownFromHavingSp; +DROP PROCEDURE explainPushdownFromHavingSp; +DROP TABLE t1; + +--echo # End of 10.5 tests diff --git a/sql/item.h b/sql/item.h index a146107508f..ce02b0edda1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3099,8 +3099,9 @@ public: bool append_for_log(THD *thd, String *str) override; - Item *do_get_copy(THD *) const override { return nullptr; } - Item *do_build_clone(THD *thd) const override { return nullptr; } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } /* Override the inherited create_field_for_create_select(), From 831f5bc66f8d2147edd7991caf69e34058566b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Jan 2025 12:08:30 +0200 Subject: [PATCH 085/118] MDEV-33978 P_S.THREADS is not showing all server threads page_encrypt_thread_key: The key for fil_crypt_thread(). All other InnoDB threads should already have been registered for performance_schema ever since commit a2f510fccff23e5011486c240587b8f1a98ecacc --- mysql-test/suite/perfschema/r/threads_innodb.result | 1 + mysql-test/suite/perfschema/t/threads_innodb.opt | 1 + storage/innobase/fil/fil0crypt.cc | 9 +++++++++ storage/innobase/handler/ha_innodb.cc | 1 + storage/innobase/include/srv0srv.h | 1 + 5 files changed, 13 insertions(+) create mode 100644 mysql-test/suite/perfschema/t/threads_innodb.opt diff --git a/mysql-test/suite/perfschema/r/threads_innodb.result b/mysql-test/suite/perfschema/r/threads_innodb.result index d79420f6fb5..abfedb57644 100644 --- a/mysql-test/suite/perfschema/r/threads_innodb.result +++ b/mysql-test/suite/perfschema/r/threads_innodb.result @@ -6,4 +6,5 @@ WHERE name LIKE 'thread/innodb/%' GROUP BY name; name type processlist_user processlist_host processlist_db processlist_command processlist_time processlist_state processlist_info parent_thread_id role instrumented thread/innodb/page_cleaner_thread BACKGROUND NULL NULL NULL NULL NULL NULL NULL NULL NULL YES +thread/innodb/page_encrypt_thread BACKGROUND NULL NULL NULL NULL NULL NULL NULL NULL NULL YES thread/innodb/thread_pool_thread BACKGROUND NULL NULL NULL NULL NULL NULL NULL NULL NULL YES diff --git a/mysql-test/suite/perfschema/t/threads_innodb.opt b/mysql-test/suite/perfschema/t/threads_innodb.opt new file mode 100644 index 00000000000..bd33f76701e --- /dev/null +++ b/mysql-test/suite/perfschema/t/threads_innodb.opt @@ -0,0 +1 @@ +--innodb-encryption-threads=2 diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index bfaaaafc359..28078747318 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2007,10 +2007,18 @@ static void fil_crypt_complete_rotate_space(rotate_thread_t* state) mysql_mutex_unlock(&crypt_data->mutex); } +#ifdef UNIV_PFS_THREAD +mysql_pfs_key_t page_encrypt_thread_key; +#endif /* UNIV_PFS_THREAD */ + /** A thread which monitors global key state and rotates tablespaces accordingly */ static void fil_crypt_thread() { + my_thread_init(); +#ifdef UNIV_PFS_THREAD + pfs_register_thread(page_encrypt_thread_key); +#endif /* UNIV_PFS_THREAD */ mysql_mutex_lock(&fil_crypt_threads_mutex); rotate_thread_t thr(srv_n_fil_crypt_threads_started++); pthread_cond_signal(&fil_crypt_cond); /* signal that we started */ @@ -2088,6 +2096,7 @@ wait_for_work: pthread_cond_signal(&fil_crypt_cond); /* signal that we stopped */ mysql_mutex_unlock(&fil_crypt_threads_mutex); + my_thread_end(); #ifdef UNIV_PFS_THREAD pfs_delete_thread(); #endif diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 4dd7a9405dd..bb7594cf1a0 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -624,6 +624,7 @@ performance schema instrumented if "UNIV_PFS_THREAD" is defined */ static PSI_thread_info all_innodb_threads[] = { PSI_KEY(page_cleaner_thread), + PSI_KEY(page_encrypt_thread), PSI_KEY(trx_rollback_clean_thread), PSI_KEY(thread_pool_thread) }; diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 5fbf2a3d4f2..7195b062e70 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -462,6 +462,7 @@ extern ulong srv_buf_dump_status_frequency; # ifdef UNIV_PFS_THREAD extern mysql_pfs_key_t page_cleaner_thread_key; +extern mysql_pfs_key_t page_encrypt_thread_key; extern mysql_pfs_key_t trx_rollback_clean_thread_key; extern mysql_pfs_key_t thread_pool_thread_key; From 746471b8d86de9c53ec87b576f8fbef0768e6c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 27 Jan 2025 12:11:47 +0200 Subject: [PATCH 086/118] MDEV-33978 P_S.THREADS is not showing all server threads page_encrypt_thread_key: The key for fil_crypt_thread(). All other InnoDB threads should already have been registered for performance_schema ever since commit a2f510fccff23e5011486c240587b8f1a98ecacc --- mysql-test/suite/perfschema/r/threads_innodb.result | 1 + mysql-test/suite/perfschema/t/threads_innodb.opt | 1 + storage/innobase/fil/fil0crypt.cc | 9 +++++++++ storage/innobase/handler/ha_innodb.cc | 1 + storage/innobase/include/srv0srv.h | 1 + 5 files changed, 13 insertions(+) create mode 100644 mysql-test/suite/perfschema/t/threads_innodb.opt diff --git a/mysql-test/suite/perfschema/r/threads_innodb.result b/mysql-test/suite/perfschema/r/threads_innodb.result index d79420f6fb5..abfedb57644 100644 --- a/mysql-test/suite/perfschema/r/threads_innodb.result +++ b/mysql-test/suite/perfschema/r/threads_innodb.result @@ -6,4 +6,5 @@ WHERE name LIKE 'thread/innodb/%' GROUP BY name; name type processlist_user processlist_host processlist_db processlist_command processlist_time processlist_state processlist_info parent_thread_id role instrumented thread/innodb/page_cleaner_thread BACKGROUND NULL NULL NULL NULL NULL NULL NULL NULL NULL YES +thread/innodb/page_encrypt_thread BACKGROUND NULL NULL NULL NULL NULL NULL NULL NULL NULL YES thread/innodb/thread_pool_thread BACKGROUND NULL NULL NULL NULL NULL NULL NULL NULL NULL YES diff --git a/mysql-test/suite/perfschema/t/threads_innodb.opt b/mysql-test/suite/perfschema/t/threads_innodb.opt new file mode 100644 index 00000000000..bd33f76701e --- /dev/null +++ b/mysql-test/suite/perfschema/t/threads_innodb.opt @@ -0,0 +1 @@ +--innodb-encryption-threads=2 diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index fce308bcc81..7433e957d0a 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -80,6 +80,10 @@ static uint n_fil_crypt_iops_allocated = 0; #define DEBUG_KEYROTATION_THROTTLING 0 +#ifdef UNIV_PFS_THREAD +mysql_pfs_key_t page_encrypt_thread_key; +#endif /* UNIV_PFS_THREAD */ + /** Statistics variables */ static fil_crypt_stat_t crypt_stat; static ib_mutex_t crypt_stat_mutex; @@ -2145,6 +2149,10 @@ extern "C" UNIV_INTERN os_thread_ret_t DECLARE_THREAD(fil_crypt_thread)(void*) { + my_thread_init(); +#ifdef UNIV_PFS_THREAD + pfs_register_thread(page_encrypt_thread_key); +#endif /* UNIV_PFS_THREAD */ mutex_enter(&fil_crypt_threads_mutex); uint thread_no = srv_n_fil_crypt_threads_started; srv_n_fil_crypt_threads_started++; @@ -2242,6 +2250,7 @@ DECLARE_THREAD(fil_crypt_thread)(void*) /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ + my_thread_end(); return os_thread_exit(); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 890cdbaf429..e0d7e91c10b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -579,6 +579,7 @@ performance schema instrumented if "UNIV_PFS_THREAD" is defined */ static PSI_thread_info all_innodb_threads[] = { PSI_KEY(page_cleaner_thread), + PSI_KEY(page_encrypt_thread), PSI_KEY(trx_rollback_clean_thread), PSI_KEY(thread_pool_thread) }; diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 75718a92a10..fd615742ba3 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -469,6 +469,7 @@ extern ulong srv_buf_dump_status_frequency; # ifdef UNIV_PFS_THREAD extern mysql_pfs_key_t page_cleaner_thread_key; +extern mysql_pfs_key_t page_encrypt_thread_key; extern mysql_pfs_key_t trx_rollback_clean_thread_key; extern mysql_pfs_key_t thread_pool_thread_key; From c0b11e75fff9ea513cd6cccfe47837678cedb473 Mon Sep 17 00:00:00 2001 From: Hemant Dangi Date: Wed, 8 Jan 2025 13:22:46 +0530 Subject: [PATCH 087/118] MDEV-34218: Mariadb Galera cluster fails when replicating from Mysql 5.7 on use of DDL Issue: Mariadb Galera cluster fails to replicate from Mysql 5.7 when configured with MASTER_USE_GTID=no option for CHANGE MASTER. HOST: mysql, mysql 5.7.44 binlog_format=ROW HOST: m1, mariadb 10.6 GALERA NODE replicating from HOST mysql, Using_Gtid: No (log file and position) HOST: m2 mariadb 10.6 GALERA NODE HOST: m3 mariadb 10.6 GALERA NODE Error on m1: 2024-05-22 16:11:07 1 [ERROR] WSREP: Vote 0 (success) on 78cebda7-1876-11ef-896b-8a58fca50d36:2565 is inconsistent with group. Leaving cluster. Error on m2 and m3: 2024-05-22 16:11:06 2 [ERROR] Error in Log_event::read_log_event(): 'Found invalid event in binary log', data_len: 42, event_type: -94 2024-05-22 16:11:06 2 [ERROR] WSREP: applier could not read binlog event, seqno: 2565, len: 482 It fails in Gtid_log_event::is_valid() check on secondary node when sequence number sent from primary is 0. On primary for applier or slave thread sequence number is set to 0, when both thd->variables.gtid_seq_no and thd->variables.wsrep_gtid_seq_no have value 0. Solution: Skip adding Gtid Event on primary for applier or slave thread when both thd->variables.gtid_seq_no and thd->variables.wsrep_gtid_seq_no have value 0. Signed-off-by: Julius Goryavsky --- sql/wsrep_mysqld.cc | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 8c2a2bda31b..ae52e319e3f 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1863,11 +1863,18 @@ int wsrep_to_buf_helper( domain_id= wsrep_gtid_server.domain_id; server_id= wsrep_gtid_server.server_id; } - Gtid_log_event gtid_event(thd, seqno, domain_id, true, - LOG_EVENT_SUPPRESS_USE_F, true, 0); - gtid_event.server_id= server_id; - if (!gtid_event.is_valid()) ret= 0; - ret= writer.write(>id_event); + /* + * Ignore if both thd->variables.gtid_seq_no and + * thd->variables.wsrep_gtid_seq_no are not set. + */ + if (seqno) + { + Gtid_log_event gtid_event(thd, seqno, domain_id, true, + LOG_EVENT_SUPPRESS_USE_F, true, 0); + gtid_event.server_id= server_id; + if (!gtid_event.is_valid()) ret= 0; + ret= writer.write(>id_event); + } } /* It's local DDL so in case of possible gtid seqno (SET gtid_seq_no=X) From 6e3274e814d743d6337e1836101568be561e8b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 19 Nov 2024 14:16:48 +0200 Subject: [PATCH 088/118] MENT-31857 post-fix: fix for timeouts in the galera_as_slave_ctas test Caused by MDEV-31857 enable --ssl-verify-server-cert by default in the internal client. Fixed by disabling master_ssl_verify_server_cert because account is passwordless. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/t/galera_as_slave_ctas.test | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera/t/galera_as_slave_ctas.test b/mysql-test/suite/galera/t/galera_as_slave_ctas.test index eced636c600..0ef4c3f5986 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_ctas.test +++ b/mysql-test/suite/galera/t/galera_as_slave_ctas.test @@ -34,11 +34,13 @@ CREATE TABLE target AS SELECT * FROM source; --connection node_1 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target'; ---source include/wait_condition.inc +--let $wait_condition_on_error_output = SELECT * FROM INFORMATION_SCHEMA.TABLES +--source include/wait_condition_with_debug.inc --connection node_2 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'target'; ---source include/wait_condition.inc +--let $wait_condition_on_error_output = SELECT * FROM INFORMATION_SCHEMA.TABLES +--source include/wait_condition_with_debug.inc # # test phase two, issue CTAS with populated source table From 0ddaefcc76844e94867bcbfa4dc9613e95ec3ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 20 Nov 2024 16:17:50 +0200 Subject: [PATCH 089/118] galera fix : MW-402 galera test fails sporadically Test was using after certification sync point when it was intended to use before certification sync point. This caused sporadic failures. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MW-369.result | 56 +++++++++---------- mysql-test/suite/galera/r/MW-402.result | 54 ++++++++++-------- mysql-test/suite/galera/t/MW-369.inc | 12 ++-- mysql-test/suite/galera/t/MW-402.combinations | 5 ++ mysql-test/suite/galera/t/MW-402.test | 8 ++- 5 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 mysql-test/suite/galera/t/MW-402.combinations diff --git a/mysql-test/suite/galera/r/MW-369.result b/mysql-test/suite/galera/r/MW-369.result index b4fb8668e74..4c487c57030 100644 --- a/mysql-test/suite/galera/r/MW-369.result +++ b/mysql-test/suite/galera/r/MW-369.result @@ -18,12 +18,12 @@ INSERT INTO c VALUES (1, 1); connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; @@ -58,12 +58,12 @@ UPDATE c SET f2 = 1 WHERE f1 = 1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; @@ -96,12 +96,12 @@ DELETE FROM c WHERE f1 = 1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; @@ -130,12 +130,12 @@ INSERT INTO c VALUES (1, 0);; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; @@ -168,12 +168,12 @@ UPDATE c SET f2 = 1 WHERE f1 = 1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; @@ -211,12 +211,12 @@ INSERT INTO cf (f1, p_id) VALUES (20, 1); connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; @@ -249,12 +249,12 @@ INSERT INTO cg VALUES (1, 1, 0); connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; diff --git a/mysql-test/suite/galera/r/MW-402.result b/mysql-test/suite/galera/r/MW-402.result index e936b83553d..925d208f5c6 100644 --- a/mysql-test/suite/galera/r/MW-402.result +++ b/mysql-test/suite/galera/r/MW-402.result @@ -21,16 +21,17 @@ DELETE FROM p WHERE f1 = 1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET DEBUG_SYNC = 'RESET'; connection node_2; SELECT * FROM p; f1 f2 @@ -59,16 +60,17 @@ UPDATE p set f1=11 WHERE f1 = 1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET DEBUG_SYNC = 'RESET'; connection node_2; SELECT * FROM p; f1 f2 @@ -99,16 +101,17 @@ UPDATE p set f1=11 WHERE f1 = 1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET DEBUG_SYNC = 'RESET'; connection node_2; SELECT * FROM p; f1 f2 @@ -130,16 +133,17 @@ UPDATE c SET p_id=2 where f1=1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET DEBUG_SYNC = 'RESET'; connection node_2; SELECT * FROM p; f1 f2 @@ -174,15 +178,16 @@ DELETE FROM p1 WHERE f1 = 1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; +SET DEBUG_SYNC = 'RESET'; connection node_2; SELECT * FROM p1; f1 f2 @@ -219,16 +224,17 @@ DELETE FROM p1 WHERE f1=1; connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; connection node_1; -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; COMMIT; connection node_1a; -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; connection node_1; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SET DEBUG_SYNC = 'RESET'; connection node_2; SELECT * FROM p1; f1 f2 diff --git a/mysql-test/suite/galera/t/MW-369.inc b/mysql-test/suite/galera/t/MW-369.inc index f080d99fe7e..3b0a32bdd9d 100644 --- a/mysql-test/suite/galera/t/MW-369.inc +++ b/mysql-test/suite/galera/t/MW-369.inc @@ -14,7 +14,7 @@ # node_2 # $mw_369_child_query - will be blocked on node_1 in wsrep_apply_cb # node_1: -# COMMIT; - will be blocked on node_1 in wsrep_after_certification +# COMMIT; - will be blocked on node_1 in after_wsrep_before_prepare # # The $mw_369_child_query is always expected to succeed. The caller is # responsible for checking if the final COMMIT on connection node_1 @@ -49,14 +49,14 @@ SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_cb"; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; --connection node_1 -SET DEBUG_SYNC = "wsrep_after_certification SIGNAL after_certification_reached WAIT_FOR continue_after_certification"; +SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification"; --send COMMIT # # Wait until both sync points have been reached # --connection node_1a -SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; +SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached"; # # both threads are now parked in sync points, signal them to continue @@ -66,13 +66,13 @@ SET SESSION DEBUG_SYNC = "now WAIT_FOR after_certification_reached"; --let $wait_condition_on_error_output = SELECT STATE FROM INFORMATION_SCHEMA.PROCESSLIST --source include/wait_condition_with_debug.inc -SET DEBUG_SYNC = 'now SIGNAL continue_after_certification'; +SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification'; --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'debug sync point:%' --let $wait_condition_on_error_output = SELECT STATE FROM INFORMATION_SCHEMA.PROCESSLIST --source include/wait_condition_with_debug.inc -SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; +SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'debug sync point:%' --let $wait_condition_on_error_output = SELECT STATE FROM INFORMATION_SCHEMA.PROCESSLIST @@ -80,3 +80,5 @@ SET DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb'; SET GLOBAL DEBUG_DBUG = ""; SET DEBUG_SYNC = 'RESET'; + + diff --git a/mysql-test/suite/galera/t/MW-402.combinations b/mysql-test/suite/galera/t/MW-402.combinations new file mode 100644 index 00000000000..def4dda7def --- /dev/null +++ b/mysql-test/suite/galera/t/MW-402.combinations @@ -0,0 +1,5 @@ +[binlogon] +log-bin +log-slave-updates=ON + +[binlogoff] diff --git a/mysql-test/suite/galera/t/MW-402.test b/mysql-test/suite/galera/t/MW-402.test index f84752e1b25..8b954a19405 100644 --- a/mysql-test/suite/galera/t/MW-402.test +++ b/mysql-test/suite/galera/t/MW-402.test @@ -2,7 +2,6 @@ --source include/have_innodb.inc --source include/have_debug.inc --source include/have_debug_sync.inc ---source include/galera_have_debug_sync.inc # # we must open connection node_1a here, MW-369.inc will use it later @@ -36,6 +35,7 @@ INSERT INTO c VALUES (1, 1, 0); --connection node_1 --error ER_LOCK_DEADLOCK --reap +SET DEBUG_SYNC = 'RESET'; --connection node_2 SELECT * FROM p; @@ -72,6 +72,7 @@ INSERT INTO c VALUES (1, 1, 0); --connection node_1 --error ER_LOCK_DEADLOCK --reap +SET DEBUG_SYNC = 'RESET'; --connection node_2 SELECT * FROM p; @@ -112,6 +113,7 @@ INSERT INTO c VALUES (1, 1, 0); --connection node_1 --error ER_LOCK_DEADLOCK --reap +SET DEBUG_SYNC = 'RESET'; # same as previous, but statements in different order --connection node_2 @@ -128,7 +130,7 @@ SELECT * FROM c; --connection node_1 --error ER_LOCK_DEADLOCK --reap - +SET DEBUG_SYNC = 'RESET'; --connection node_2 SELECT * FROM p; @@ -172,6 +174,7 @@ INSERT INTO c VALUES (1, 1, 1, 0); # Commit succeeds --connection node_1 --reap +SET DEBUG_SYNC = 'RESET'; --connection node_2 SELECT * FROM p1; @@ -217,6 +220,7 @@ INSERT INTO c VALUES (1, 1, 1, 0); --connection node_1 --error ER_LOCK_DEADLOCK --reap +SET DEBUG_SYNC = 'RESET'; --connection node_2 SELECT * FROM p1; From 2cfad396ee1a7ab270f91b5986beba7e323be6ba Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Fri, 24 Jan 2025 02:22:01 +0100 Subject: [PATCH 090/118] galera tests: more informative messages about the number of variables --- mysql-test/include/galera_variables_ok.inc | 13 ++++++++++--- mysql-test/include/galera_variables_ok_debug.inc | 12 ++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/mysql-test/include/galera_variables_ok.inc b/mysql-test/include/galera_variables_ok.inc index c9a54724c17..d10bf1fd36e 100644 --- a/mysql-test/include/galera_variables_ok.inc +++ b/mysql-test/include/galera_variables_ok.inc @@ -1,9 +1,16 @@ --disable_query_log ---let $galera_variables_ok = `SELECT COUNT(*) = 50 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep%'` +let $_galera_variables_delta=$galera_variables_delta; +if (!$_galera_variables_delta) { +--let $galera_variables_delta=0 +} ---if (!$galera_variables_ok) { - --skip Galera number of variables has changed! +--let $galera_variables_expected=`SELECT 50 + $galera_variables_delta` + +--let $galera_variables_count=`SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep%'` + +--if ($galera_variables_count != $galera_variables_expected) { + --skip Galera number of variables has changed! ($galera_variables_count instead of $galera_variables_expected) } --enable_query_log diff --git a/mysql-test/include/galera_variables_ok_debug.inc b/mysql-test/include/galera_variables_ok_debug.inc index e420b3af6c3..495b850c871 100644 --- a/mysql-test/include/galera_variables_ok_debug.inc +++ b/mysql-test/include/galera_variables_ok_debug.inc @@ -1,9 +1,5 @@ ---disable_query_log +# Now the number of variables for the release and debug versions +# of the library is equal to each other... +--let $galera_variables_delta=0 ---let $galera_variables_ok = `SELECT COUNT(*) = 51 FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME LIKE 'wsrep%'` - ---if (!$galera_variables_ok) { - --skip Galera number of variables has changed! -} - ---enable_query_log +--source include/galera_variables_ok.inc From e53ffdee965b8d056faa15fd4e6513577b830438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 19 Dec 2024 15:03:10 +0200 Subject: [PATCH 091/118] MDEV-35804 : galera_ddl_fk_conflict test failed due to timeout Test case changes only. Use better wait_conditions. Signed-off-by: Julius Goryavsky --- .../suite/galera/r/galera_ddl_fk_conflict.result | 3 +++ mysql-test/suite/galera/t/galera_ddl_fk_conflict.cnf | 11 +++++++++++ mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc | 10 ++++++++-- mysql-test/suite/galera/t/galera_ddl_fk_conflict.test | 2 ++ 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/galera/t/galera_ddl_fk_conflict.cnf diff --git a/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result index 904c5eb1a82..226aebde69e 100644 --- a/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result +++ b/mysql-test/suite/galera/r/galera_ddl_fk_conflict.result @@ -3,6 +3,7 @@ connection node_1; connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1a; SET SESSION wsrep_sync_wait=0; +FLUSH STATUS; connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1; connection node_1b; SET SESSION wsrep_sync_wait=0; @@ -17,6 +18,7 @@ SET SESSION wsrep_sync_wait=0; ###################################################################### connection node_1; SET SESSION wsrep_sync_wait=0; +FLUSH STATUS; CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); @@ -156,6 +158,7 @@ DROP TABLE p1, p2; ###################################################################### connection node_1; SET SESSION wsrep_sync_wait=0; +FLUSH STATUS; CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.cnf b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.cnf new file mode 100644 index 00000000000..2975070498e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.cnf @@ -0,0 +1,11 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep-debug=1 +loose-galera-ddl-fk-conflict=1 + +[mysqld.2] +wsrep-debug=1 +loose-galera-ddl-fk-conflict=1 + + diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc index 6964446a363..f9fad92ac62 100644 --- a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.inc @@ -39,6 +39,7 @@ --connection node_1 SET SESSION wsrep_sync_wait=0; +FLUSH STATUS; CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30)); INSERT INTO p1 VALUES (1, 'INITIAL VALUE'); @@ -108,6 +109,7 @@ BEGIN; --connection node_1a --source include/galera_wait_sync_point.inc --source include/galera_clear_sync_point.inc + --let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` --connection node_1 @@ -116,7 +118,8 @@ UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; --connection node_1a --let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' ---source include/wait_condition.inc +--let $wait_condition_on_error_output = SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition_with_debug.inc --let $galera_sync_point = apply_monitor_slave_enter_sync --source include/galera_signal_sync_point.inc @@ -166,6 +169,8 @@ BEGIN; --source include/galera_wait_sync_point.inc --source include/galera_clear_sync_point.inc --let $expected_cert_failures = `SELECT VARIABLE_VALUE+2 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'` +--let $wait_condition_on_error_output = SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition_with_debug.inc --connection node_1 UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1; @@ -177,7 +182,8 @@ UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2; --connection node_1a --let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' ---source include/wait_condition.inc +--let $wait_condition_on_error_output = SELECT VARIABLE_VALUE FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures' +--source include/wait_condition_with_debug.inc --let $galera_sync_point = apply_monitor_slave_enter_sync --source include/galera_signal_sync_point.inc diff --git a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test index b98c6daa73b..a8fb6614e41 100644 --- a/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test +++ b/mysql-test/suite/galera/t/galera_ddl_fk_conflict.test @@ -6,11 +6,13 @@ --source include/have_innodb.inc --source include/have_debug_sync.inc --source include/galera_have_debug_sync.inc +--source include/force_restart.inc # sync point controlling session --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 --connection node_1a SET SESSION wsrep_sync_wait=0; +FLUSH STATUS; # secondary conflicting DML victim session --connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1 From acf7b000ff3adbf87b1595f36d62e9b53ac0161d Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Fri, 24 Jan 2025 19:31:00 +0100 Subject: [PATCH 092/118] fixes for galera_as_slave replication tests --- mysql-test/suite/galera/r/galera_slave_replay.result | 3 +++ mysql-test/suite/galera/t/MDEV-28053.test | 2 +- mysql-test/suite/galera/t/MDEV-6860.test | 2 +- mysql-test/suite/galera/t/galera_as_master.test | 2 +- mysql-test/suite/galera/t/galera_as_slave.test | 2 +- mysql-test/suite/galera/t/galera_as_slave_autoinc.test | 2 +- mysql-test/suite/galera/t/galera_as_slave_ctas.test | 2 +- mysql-test/suite/galera/t/galera_as_slave_nonprim.test | 1 - .../suite/galera/t/galera_as_slave_parallel_retry.test | 1 - mysql-test/suite/galera/t/galera_as_slave_replay.cnf | 1 - mysql-test/suite/galera/t/galera_as_slave_replay.test | 8 +++----- .../suite/galera/t/galera_gtid_slave_sst_rsync.test | 2 +- .../suite/galera/t/galera_query_cache_invalidate.test | 2 +- mysql-test/suite/galera/t/galera_slave_replay.test | 7 +++++-- 14 files changed, 19 insertions(+), 18 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_slave_replay.result b/mysql-test/suite/galera/r/galera_slave_replay.result index 8fb7e1ab099..263e1a675d5 100644 --- a/mysql-test/suite/galera/r/galera_slave_replay.result +++ b/mysql-test/suite/galera/r/galera_slave_replay.result @@ -94,3 +94,6 @@ DROP TABLE t1; connection node_3; DROP TABLE t1; RESET MASTER; +connection node_1; +disconnect node_2a; +disconnect node_3; diff --git a/mysql-test/suite/galera/t/MDEV-28053.test b/mysql-test/suite/galera/t/MDEV-28053.test index 85cb20c7e10..f3d7a775454 100644 --- a/mysql-test/suite/galera/t/MDEV-28053.test +++ b/mysql-test/suite/galera/t/MDEV-28053.test @@ -37,7 +37,7 @@ while ($counter) { --connection node_2 --disable_query_log --disable_result_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; START SLAVE; --eval SELECT MASTER_GTID_WAIT('$gtid', 600) --enable_result_log diff --git a/mysql-test/suite/galera/t/MDEV-6860.test b/mysql-test/suite/galera/t/MDEV-6860.test index 3a8c98f317f..e254dbceeeb 100644 --- a/mysql-test/suite/galera/t/MDEV-6860.test +++ b/mysql-test/suite/galera/t/MDEV-6860.test @@ -4,7 +4,7 @@ --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3, MASTER_USE_GTID=slave_pos; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3, MASTER_USE_GTID=slave_pos; --enable_query_log START SLAVE; diff --git a/mysql-test/suite/galera/t/galera_as_master.test b/mysql-test/suite/galera/t/galera_as_master.test index a5554a735fe..4bdbc24635a 100644 --- a/mysql-test/suite/galera/t/galera_as_master.test +++ b/mysql-test/suite/galera/t/galera_as_master.test @@ -9,7 +9,7 @@ --connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_1; --enable_query_log START SLAVE; diff --git a/mysql-test/suite/galera/t/galera_as_slave.test b/mysql-test/suite/galera/t/galera_as_slave.test index da92437b118..1e2e5b2ea7b 100644 --- a/mysql-test/suite/galera/t/galera_as_slave.test +++ b/mysql-test/suite/galera/t/galera_as_slave.test @@ -13,7 +13,7 @@ --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; diff --git a/mysql-test/suite/galera/t/galera_as_slave_autoinc.test b/mysql-test/suite/galera/t/galera_as_slave_autoinc.test index ce4c87e2bee..69c16baeb08 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_autoinc.test +++ b/mysql-test/suite/galera/t/galera_as_slave_autoinc.test @@ -13,7 +13,7 @@ --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; diff --git a/mysql-test/suite/galera/t/galera_as_slave_ctas.test b/mysql-test/suite/galera/t/galera_as_slave_ctas.test index 0ef4c3f5986..32301a3d0d3 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_ctas.test +++ b/mysql-test/suite/galera/t/galera_as_slave_ctas.test @@ -16,7 +16,7 @@ SELECT @@wsrep_on; --connection node_1 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; diff --git a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test index e22f0240a59..600d64e5a81 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test +++ b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test @@ -15,7 +15,6 @@ # we open the node_4 connection here --connect node_4, 127.0.0.1, root, , test, $NODE_MYPORT_4 - --connection node_2 --disable_query_log --eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$NODE_MYPORT_4, MASTER_USER='root'; diff --git a/mysql-test/suite/galera/t/galera_as_slave_parallel_retry.test b/mysql-test/suite/galera/t/galera_as_slave_parallel_retry.test index 0d499f22fcd..e106c5f08c3 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_parallel_retry.test +++ b/mysql-test/suite/galera/t/galera_as_slave_parallel_retry.test @@ -38,7 +38,6 @@ SET debug_sync = 'now SIGNAL signal.wsrep_retry_event_group'; --let $wait_condition = SELECT COUNT(*) = 1 FROM t1; --source include/wait_condition.inc - --connection node_1 SET debug_sync = 'RESET'; diff --git a/mysql-test/suite/galera/t/galera_as_slave_replay.cnf b/mysql-test/suite/galera/t/galera_as_slave_replay.cnf index c20c65f86d9..5ae8b0b1ba7 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_replay.cnf +++ b/mysql-test/suite/galera/t/galera_as_slave_replay.cnf @@ -10,4 +10,3 @@ wsrep-debug=1 [mysqld.2] wsrep_restart_slave=1 wsrep-debug=1 - diff --git a/mysql-test/suite/galera/t/galera_as_slave_replay.test b/mysql-test/suite/galera/t/galera_as_slave_replay.test index f6dd3f89f3e..20455f2843c 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_replay.test +++ b/mysql-test/suite/galera/t/galera_as_slave_replay.test @@ -16,7 +16,6 @@ --connection node_2a --source include/galera_cluster.inc -#--source suite/galera/include/galera_have_debug_sync.inc ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; @@ -33,12 +32,11 @@ RESET MASTER; # --let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` - # -# nodes 1 and 2 form a galera cluster, node 2 operates as slave for native MariaDB naster in node 3 +# nodes 1 and 2 form a galera cluster, node 2 operates as slave for native MariaDB master in node 3 # --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3; --enable_query_log START SLAVE; @@ -81,7 +79,7 @@ SET SESSION wsrep_sync_wait = 0; SET GLOBAL debug_dbug = "d,sync.wsrep_apply_cb"; # -# now inject a conflicting insert from node 3, it will replicate with +# now inject a conflicting insert from node 1, it will replicate with # earlier seqno (than async transaction) and pause before applying in node 2 # --connection node_1 diff --git a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test index 148bbc2b460..0f68a02426e 100644 --- a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test +++ b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test @@ -16,7 +16,7 @@ --echo #Connection 2 --connection node_2 --disable_query_log ---eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3,master_use_gtid=slave_pos; +--eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_USER='root', MASTER_PORT=$NODE_MYPORT_3, master_use_gtid=slave_pos; --enable_query_log START SLAVE; --sleep 1 diff --git a/mysql-test/suite/galera/t/galera_query_cache_invalidate.test b/mysql-test/suite/galera/t/galera_query_cache_invalidate.test index c5c5f69dc27..67069577011 100644 --- a/mysql-test/suite/galera/t/galera_query_cache_invalidate.test +++ b/mysql-test/suite/galera/t/galera_query_cache_invalidate.test @@ -29,7 +29,7 @@ call mtr.add_suppression("WSREP: Ignoring server id .* for non bootstrap node"); --connection node_3 --replace_result $NODE_MYPORT_1 NODE_MYPORT_1 ---eval CHANGE MASTER TO master_host='127.0.0.1', master_user='root', master_port=$NODE_MYPORT_1, master_use_gtid=current_pos; +--eval CHANGE MASTER TO master_host='127.0.0.1', master_user='root', MASTER_PORT=$NODE_MYPORT_1, master_use_gtid=current_pos START SLAVE; --source include/wait_for_slave_to_start.inc diff --git a/mysql-test/suite/galera/t/galera_slave_replay.test b/mysql-test/suite/galera/t/galera_slave_replay.test index 6680e66ffa1..d289cfb3bd2 100644 --- a/mysql-test/suite/galera/t/galera_slave_replay.test +++ b/mysql-test/suite/galera/t/galera_slave_replay.test @@ -32,7 +32,6 @@ RESET MASTER; # --let $wsrep_local_replays_old = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_replays'` - # # nodes 1 and 2 form a galera cluster, node 2 operates as slave for native MariaDB master in node 3 # @@ -134,7 +133,7 @@ SELECT * FROM t1; SET DEBUG_SYNC = "RESET"; #******************************************************************************** -# test phase 2 +# test phase 2 #******************************************************************************** --echo # @@ -197,3 +196,7 @@ DROP TABLE t1; --connection node_3 DROP TABLE t1; RESET MASTER; + +--connection node_1 +--disconnect node_2a +--disconnect node_3 From 0a5d6cf4789a0dbbaa5e970201fb9773a9608a2d Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Sat, 25 Jan 2025 12:43:12 +0100 Subject: [PATCH 093/118] galera: disable problematic test (galera_sequences) --- mysql-test/suite/galera/disabled.def | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index fcaf38a3d7b..3d3ef86f04a 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -9,3 +9,5 @@ # Do not use any TAB characters for whitespace. # ############################################################################## + +galera_sequences : MDEV-35934/MDEV-33850 For Galera, create sequence with low cache got signal 6 error: [ERROR] WSREP: FSM: no such a transition REPLICATING -> COMMITTED From 5af1f69a849d16f07f01fe4b8cfa0b3d5b700571 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Sat, 25 Jan 2025 16:53:47 +0100 Subject: [PATCH 094/118] MDEV-26266 addendum: more stable test This test must be performed on newly launched nodes and then a restart must be performed. --- mysql-test/suite/galera/t/MDEV-26266.cnf | 6 ++++++ mysql-test/suite/galera/t/MDEV-26266.test | 2 ++ 2 files changed, 8 insertions(+) create mode 100644 mysql-test/suite/galera/t/MDEV-26266.cnf diff --git a/mysql-test/suite/galera/t/MDEV-26266.cnf b/mysql-test/suite/galera/t/MDEV-26266.cnf new file mode 100644 index 00000000000..53eeb9c82bc --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-26266.cnf @@ -0,0 +1,6 @@ +!include ../galera_2nodes.cnf + +[mysqld] +# We want both nodes to restart before this test, +# so let's add a dummy parameter here: +loose-MDEV-26266 diff --git a/mysql-test/suite/galera/t/MDEV-26266.test b/mysql-test/suite/galera/t/MDEV-26266.test index 7167e029cb5..8560cb3c7b6 100644 --- a/mysql-test/suite/galera/t/MDEV-26266.test +++ b/mysql-test/suite/galera/t/MDEV-26266.test @@ -10,6 +10,8 @@ # --source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/force_restart.inc SET SESSION query_prealloc_size=8192; SET max_session_mem_used=50000; From 331975c5c50102029caf58c4501e32227e403fb4 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Sat, 25 Jan 2025 19:38:41 +0100 Subject: [PATCH 095/118] galera: disable problematic test (galera_nbo_master_non_prim_failure) --- mysql-test/suite/galera_3nodes/disabled.def | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mysql-test/suite/galera_3nodes/disabled.def b/mysql-test/suite/galera_3nodes/disabled.def index c52df019c65..bb9d7cbd7b8 100644 --- a/mysql-test/suite/galera_3nodes/disabled.def +++ b/mysql-test/suite/galera_3nodes/disabled.def @@ -11,6 +11,4 @@ ############################################################################## galera_2_cluster : MDEV-32631 galera_2_cluster: before_rollback(): Assertion `0' failed -galera_ipv6_rsync : MDEV-34842 Can't connect to server on '::1' (115) -galera_ipv6_rsync_section : MDEV-34842 Can't connect to server on '::1' (115) -galera_ipv6_mariabackup_section : MDEV-34842 Can't connect to server on '::1' (115) +galera_nbo_master_phase_two_crash : MENT-2215 Test failure on galera_3nodes.galera_nbo_master_non_prim_failure From 779ae4c511fcc9a5a4719841cd4f9c8acd4ff407 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Sat, 25 Jan 2025 21:01:58 +0100 Subject: [PATCH 096/118] wsrep mtr tests: fix for MDEV-23081 failure Sometimes a database can be created with --log-bin but then the .combinations file causes a switch to start without --log-bin causing a failure on recovery. This commit fixes this issue. --- mysql-test/suite/wsrep/disabled.def | 2 -- mysql-test/suite/wsrep/t/MDEV-23081.test | 14 +++++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/wsrep/disabled.def b/mysql-test/suite/wsrep/disabled.def index f4145211680..fcaf38a3d7b 100644 --- a/mysql-test/suite/wsrep/disabled.def +++ b/mysql-test/suite/wsrep/disabled.def @@ -9,5 +9,3 @@ # Do not use any TAB characters for whitespace. # ############################################################################## - - diff --git a/mysql-test/suite/wsrep/t/MDEV-23081.test b/mysql-test/suite/wsrep/t/MDEV-23081.test index 04305b22b24..6cd7d6dd037 100644 --- a/mysql-test/suite/wsrep/t/MDEV-23081.test +++ b/mysql-test/suite/wsrep/t/MDEV-23081.test @@ -7,6 +7,11 @@ --source include/have_wsrep_provider.inc --source include/have_debug_sync.inc +--let $log_bin=1 +if (`select not @@log_bin`) { +--let $log_bin=0 +} + CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; # @@ -40,7 +45,14 @@ SET DEBUG_SYNC = "now WAIT_FOR before_commit_order_reached_1"; # and restart it with wsrep-on=OFF # let $restart_noprint=2; ---let $restart_parameters=--wsrep-on=OFF +if ($log_bin == 0) { +# The database could have been created with --log-bin +# and so let's add this parameter explicitly: +--let $restart_parameters=--wsrep-on=OFF --loose-innodb --loose-log-bin +} +if ($log_bin == 1) { +--let $restart_parameters=--wsrep-on=OFF --loose-innodb +} --source include/start_mysqld.inc # From 862d1be2e6b3dce7b8b7acebad1c4e86da594f4e Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Sun, 26 Jan 2025 05:26:26 +0100 Subject: [PATCH 097/118] MDEV-25718 addendum: stabilization of test success (especially for 11.4+) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added DEBUG_SYNC_ะก("ha_write_row_end") in the WSREP branch, and added a new status to the list of pending statuses in the mtr test. --- mysql-test/suite/galera_sr/t/MDEV-25718.test | 2 +- sql/handler.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera_sr/t/MDEV-25718.test b/mysql-test/suite/galera_sr/t/MDEV-25718.test index 037cd300709..147b62fe145 100644 --- a/mysql-test/suite/galera_sr/t/MDEV-25718.test +++ b/mysql-test/suite/galera_sr/t/MDEV-25718.test @@ -43,7 +43,7 @@ SET SESSION wsrep_sync_wait = 0; SET debug_sync = "now SIGNAL write_row_continue"; # Let's give the INSERT some time, to make sure it does rollback ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = "INSERT INTO t1 VALUES (1)" AND (STATE = "Freeing items" OR STATE = 'Rollback'); +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = "INSERT INTO t1 VALUES (1)" AND (STATE = 'Freeing items' OR STATE = 'Rollback' OR STATE = 'Query end'); --let $wait_condition_on_error_output = SELECT INFO, STATE FROM INFORMATION_SCHEMA.PROCESSLIST --source include/wait_condition_with_debug.inc diff --git a/sql/handler.cc b/sql/handler.cc index c3aa1c64906..7e30968cb1d 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7375,6 +7375,7 @@ int handler::ha_write_row(const uchar *buf) ht->flags & HTON_WSREP_REPLICATION && !error && (error= wsrep_after_row(ha_thd()))) { + DEBUG_SYNC_C("ha_write_row_end"); DBUG_RETURN(error); } #endif /* WITH_WSREP */ From 479a5832f0dc4a146702f3adbca34ee051c39080 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Wed, 28 Aug 2024 04:12:10 +0200 Subject: [PATCH 098/118] galera fix: MSAN reports use-of-uninitialized-value on binlog_encryption This commit fixes a bug in MSAN verification in debug builds related to the member of a lex->definer structure field that may be uninitialized for some SET statements. The bug is caused by debug output in a wsrep-specific insert and does not affect server functionality. --- sql/log_event_server.cc | 7 +++++-- sql/service_wsrep.cc | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 9f7fea18075..603bd2f6e78 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -1728,8 +1728,11 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, DBUG_PRINT("query",("%s", thd->query())); #ifdef WITH_WSREP - WSREP_DEBUG("Query_log_event thread=%llu for query=%s", - thd_get_thread_id(thd), wsrep_thd_query(thd)); + if (WSREP(thd)) + { + WSREP_DEBUG("Query_log_event thread=%llu for query=%s", + thd_get_thread_id(thd), wsrep_thd_query(thd)); + } #endif if (unlikely(!(expected_error= error_code)) || diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index d1e0260d53c..16bb2783cfb 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -82,8 +82,7 @@ extern "C" const char *wsrep_thd_query(const THD *thd) case SQLCOM_REVOKE: return "REVOKE"; case SQLCOM_SET_OPTION: - if (thd->lex->definer) - return "SET PASSWORD"; + return "SET OPTION"; /* fallthrough */ default: { From c43db43a7cea2dca028093e10012e5ab8293172f Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Thu, 22 Feb 2024 09:17:29 +0100 Subject: [PATCH 099/118] MENT-2038 Assert WSREP(thd) fails in wsrep_restore_kill_after_commit Fix wrong assertion: function wsrep_restore_kill_after_commit() asserts `WSREP(thd)`, however for the caller (wsrep_after_statement()) it is enough that the THD has an active transaction. Fixed the assertion accordingly. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera_sr/r/MENT-2038.result | 7 +++++++ mysql-test/suite/galera_sr/t/MENT-2038.test | 12 ++++++++++++ sql/wsrep_thd.cc | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera_sr/r/MENT-2038.result create mode 100644 mysql-test/suite/galera_sr/t/MENT-2038.test diff --git a/mysql-test/suite/galera_sr/r/MENT-2038.result b/mysql-test/suite/galera_sr/r/MENT-2038.result new file mode 100644 index 00000000000..bbd7c568925 --- /dev/null +++ b/mysql-test/suite/galera_sr/r/MENT-2038.result @@ -0,0 +1,7 @@ +connection node_2; +connection node_1; +SET SESSION wsrep_on=OFF; +BEGIN; +BEGIN; +COMMIT; +SET SESSION wsrep_on=ON; diff --git a/mysql-test/suite/galera_sr/t/MENT-2038.test b/mysql-test/suite/galera_sr/t/MENT-2038.test new file mode 100644 index 00000000000..311b0d3a36f --- /dev/null +++ b/mysql-test/suite/galera_sr/t/MENT-2038.test @@ -0,0 +1,12 @@ +# +# MENT-2038: Assertion `(thd && (WSREP_PROVIDER_EXISTS_ && thd->variables.wsrep_on))' +# failed in void wsrep_restore_kill_after_commit(THD*) +# + +--source include/galera_cluster.inc + +SET SESSION wsrep_on=OFF; +BEGIN; +BEGIN; # If bug is present, assertion triggers during implicit commit +COMMIT; +SET SESSION wsrep_on=ON; diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 1c51d05c56a..2c2e3a0e44d 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -496,7 +496,7 @@ void wsrep_backup_kill_for_commit(THD *thd) void wsrep_restore_kill_after_commit(THD *thd) { - DBUG_ASSERT(WSREP(thd)); + DBUG_ASSERT(wsrep_is_active(thd)); mysql_mutex_assert_owner(&thd->LOCK_thd_kill); thd->killed= thd->wsrep_abort_by_kill; my_free(thd->killed_err); From 50d49493db079609bdae00da040ebc47b3f276dc Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Wed, 6 Mar 2024 03:40:37 +0100 Subject: [PATCH 100/118] galera: fixes for mtr test for performance schema --- mysql-test/suite/galera/t/galera_performance_schema.test | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/t/galera_performance_schema.test b/mysql-test/suite/galera/t/galera_performance_schema.test index d54555ea301..531c45ea3c5 100644 --- a/mysql-test/suite/galera/t/galera_performance_schema.test +++ b/mysql-test/suite/galera/t/galera_performance_schema.test @@ -5,6 +5,9 @@ --source include/galera_cluster.inc --source include/have_perfschema.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc + use performance_schema; --vertical_results @@ -22,6 +25,7 @@ insert into t1 values (1),(2); use performance_schema; select name from mutex_instances where name like 'wait/synch/mutex/sql/LOCK_wsrep%' order by name; select name from cond_instances where name like 'wait/synch/cond/sql/COND_wsrep%' order by name; + # Whenever a node fails to apply an event on a slave node, the database server creates a # special binary log file of the event in the data directory. The naming convention the # node uses for the filename is GRA_*.log. @@ -55,4 +59,3 @@ CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query" use test; drop table t1; drop table t2; - From 0018df2b553e302a97a85e3f6120c2f5126fe758 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Tue, 5 Dec 2023 01:40:57 +0100 Subject: [PATCH 101/118] galera fix: Assertion `WSREP(thd)` failed in wsrep_restore_kill_after_commit() Wsrep_commit_empty happens too early when wsrep is disabled. Let the cleanup happen at end of statement. Signed-off-by: Julius Goryavsky --- sql/handler.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/handler.cc b/sql/handler.cc index 7e30968cb1d..22bc363e88c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1660,7 +1660,7 @@ int ha_commit_trans(THD *thd, bool all) thd->m_transaction_psi= NULL; } #ifdef WITH_WSREP - if (wsrep_is_active(thd) && is_real_trans && !error) + if (WSREP(thd) && wsrep_is_active(thd) && is_real_trans && !error) wsrep_commit_empty(thd, all); #endif /* WITH_WSREP */ From bcb87f5ccb554d755d1ff3e548d911bba893849b Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Mon, 27 Jan 2025 23:07:23 +0100 Subject: [PATCH 102/118] fix for galera_query_cache_invalidate test results --- mysql-test/suite/galera/r/galera_query_cache_invalidate.result | 1 - mysql-test/suite/galera/t/galera_query_cache_invalidate.test | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_query_cache_invalidate.result b/mysql-test/suite/galera/r/galera_query_cache_invalidate.result index 078920da3f2..b45f8ee01b7 100644 --- a/mysql-test/suite/galera/r/galera_query_cache_invalidate.result +++ b/mysql-test/suite/galera/r/galera_query_cache_invalidate.result @@ -7,7 +7,6 @@ call mtr.add_suppression("WSREP: Ignoring server id .* for non bootstrap node"); connection node_4; call mtr.add_suppression("WSREP: Ignoring server id .* for non bootstrap node"); connection node_3; -CHANGE MASTER TO master_host='127.0.0.1', master_user='root', master_port=NODE_MYPORT_1, master_use_gtid=current_pos;; START SLAVE; include/wait_for_slave_to_start.inc connection node_1; diff --git a/mysql-test/suite/galera/t/galera_query_cache_invalidate.test b/mysql-test/suite/galera/t/galera_query_cache_invalidate.test index 67069577011..b5560c54253 100644 --- a/mysql-test/suite/galera/t/galera_query_cache_invalidate.test +++ b/mysql-test/suite/galera/t/galera_query_cache_invalidate.test @@ -28,8 +28,9 @@ call mtr.add_suppression("WSREP: Ignoring server id .* for non bootstrap node"); --connection node_3 ---replace_result $NODE_MYPORT_1 NODE_MYPORT_1 +--disable_query_log --eval CHANGE MASTER TO master_host='127.0.0.1', master_user='root', MASTER_PORT=$NODE_MYPORT_1, master_use_gtid=current_pos +--enable_query_log START SLAVE; --source include/wait_for_slave_to_start.inc From b8b77177c27412777fe1763f28b344a3a260741a Mon Sep 17 00:00:00 2001 From: Dave Gosselin Date: Fri, 24 Jan 2025 08:21:48 -0500 Subject: [PATCH 103/118] MDEV-35964 fix cast warnings on mac in mysql_file.h Cast create_flags to mode_t when passing to my_create and my_create_with_symlink --- include/mysql/psi/mysql_file.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mysql/psi/mysql_file.h b/include/mysql/psi/mysql_file.h index fd3b29cc5c9..096815ed02d 100644 --- a/include/mysql/psi/mysql_file.h +++ b/include/mysql/psi/mysql_file.h @@ -1018,7 +1018,7 @@ inline_mysql_file_create( #ifdef HAVE_PSI_FILE_INTERFACE PSI_file_key key, const char *src_file, uint src_line, #endif - const char *filename, int create_flags, int access_flags, myf myFlags) + const char *filename, mode_t create_flags, int access_flags, myf myFlags) { File file; #ifdef HAVE_PSI_FILE_INTERFACE @@ -1344,7 +1344,7 @@ inline_mysql_file_create_with_symlink( #ifdef HAVE_PSI_FILE_INTERFACE PSI_file_key key, const char *src_file, uint src_line, #endif - const char *linkname, const char *filename, int create_flags, + const char *linkname, const char *filename, mode_t create_flags, int access_flags, myf flags) { File file; From 9a0ac0cdf7814241dbc8f3d95fa045f9fa6358e6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 24 Jan 2025 13:48:12 +0100 Subject: [PATCH 104/118] MDEV-35911 Assertion `marked_for_write_or_computed()' failed in bool Field_new_decimal::store_value(const my_decimal*, int*) disable the assert. also, use the same check for check_that_all_fields_are_given_values() as it's used in not_null_fields_have_null_values() - to avoid issuing the same warning twice. --- .../{trigger_null-8605.result => trigger_null.result} | 11 +++++++++++ .../{trigger_null-8605.test => trigger_null.test} | 10 ++++++++++ sql/field_conv.cc | 2 ++ sql/sql_insert.cc | 3 +-- 4 files changed, 24 insertions(+), 2 deletions(-) rename mysql-test/main/{trigger_null-8605.result => trigger_null.result} (96%) rename mysql-test/main/{trigger_null-8605.test => trigger_null.test} (97%) diff --git a/mysql-test/main/trigger_null-8605.result b/mysql-test/main/trigger_null.result similarity index 96% rename from mysql-test/main/trigger_null-8605.result rename to mysql-test/main/trigger_null.result index 6480fbf9a7e..91bae7e3b0e 100644 --- a/mysql-test/main/trigger_null-8605.result +++ b/mysql-test/main/trigger_null.result @@ -388,4 +388,15 @@ id rate 3 15 4 5 drop table t1; +# +# MDEV-35911 Assertion `marked_for_write_or_computed()' failed in bool Field_new_decimal::store_value(const my_decimal*, int*) +# +set sql_mode=''; +create table t1 (c fixed,c2 binary (1),c5 fixed not null); +create trigger tr1 before update on t1 for each row set @a=0; +insert into t1 (c) values (1); +Warnings: +Warning 1364 Field 'c5' doesn't have a default value +drop table t1; +set sql_mode=default; # End of 10.5 tests diff --git a/mysql-test/main/trigger_null-8605.test b/mysql-test/main/trigger_null.test similarity index 97% rename from mysql-test/main/trigger_null-8605.test rename to mysql-test/main/trigger_null.test index e33f17151bf..d3b74af49b3 100644 --- a/mysql-test/main/trigger_null-8605.test +++ b/mysql-test/main/trigger_null.test @@ -415,4 +415,14 @@ select * from t1; drop table t1; +--echo # +--echo # MDEV-35911 Assertion `marked_for_write_or_computed()' failed in bool Field_new_decimal::store_value(const my_decimal*, int*) +--echo # +set sql_mode=''; +create table t1 (c fixed,c2 binary (1),c5 fixed not null); +create trigger tr1 before update on t1 for each row set @a=0; +insert into t1 (c) values (1); +drop table t1; +set sql_mode=default; + --echo # End of 10.5 tests diff --git a/sql/field_conv.cc b/sql/field_conv.cc index dcbb6b39a31..a8c528d07fd 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -172,7 +172,9 @@ int convert_null_to_field_value_or_error(Field *field, uint err) return 0; } + MY_BITMAP *old_map= dbug_tmp_use_all_columns(field->table, &field->table->write_set); field->reset(); // Note: we ignore any potential failure of reset() here. + dbug_tmp_restore_column_map(&field->table->write_set, old_map); if (field == field->table->next_number_field) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0182ca0ee1b..26adcf3d228 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -950,8 +950,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, if (fields.elements || !value_count || table_list->view != 0) { - if (table->triggers && - table->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE)) + if (table->field != table->field_to_fill()) { /* BEFORE INSERT triggers exist, the check will be done later, per row */ } From caec03cb79ab5b39b9cf7bce784a4f8865234ebd Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 23 Jan 2025 23:32:02 +0100 Subject: [PATCH 105/118] MDEV-35907 debian-start script fails when using non-standard socket path consistently use --defaults-extra-file for all command-line tools --- debian/additions/debian-start | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/additions/debian-start b/debian/additions/debian-start index 2a8b61ddaff..27483c3a87c 100755 --- a/debian/additions/debian-start +++ b/debian/additions/debian-start @@ -17,11 +17,11 @@ if [ -f /etc/default/mariadb ]; then . /etc/default/mariadb fi -MARIADB="/usr/bin/mariadb --defaults-file=/etc/mysql/debian.cnf" -MYADMIN="/usr/bin/mariadb-admin --defaults-file=/etc/mysql/debian.cnf" +MARIADB="/usr/bin/mariadb --defaults-extra-file=/etc/mysql/debian.cnf" +MYADMIN="/usr/bin/mariadb-admin --defaults-extra-file=/etc/mysql/debian.cnf" # Don't run full mariadb-upgrade on every server restart, use --version-check to do it only once MYUPGRADE="/usr/bin/mariadb-upgrade --defaults-extra-file=/etc/mysql/debian.cnf --version-check --silent" -MYCHECK="/usr/bin/mariadb-check --defaults-file=/etc/mysql/debian.cnf" +MYCHECK="/usr/bin/mariadb-check --defaults-extra-file=/etc/mysql/debian.cnf" MYCHECK_SUBJECT="WARNING: mariadb-check has found corrupt tables" MYCHECK_PARAMS="--all-databases --fast --silent" MYCHECK_RCPT="${MYCHECK_RCPT:-root}" From c1933b46e4ca2722951fa6772a6964582da14826 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 25 Jan 2025 09:51:20 +0100 Subject: [PATCH 106/118] MDEV-33285 make the test deterministic need to clear old signals before waiting for new signals with the same name --- mysql-test/main/kill_debug.result | 1 + mysql-test/main/kill_debug.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/main/kill_debug.result b/mysql-test/main/kill_debug.result index 40047ef7eb7..1b61b8ae885 100644 --- a/mysql-test/main/kill_debug.result +++ b/mysql-test/main/kill_debug.result @@ -252,6 +252,7 @@ KILL QUERY id; SET debug_sync='now SIGNAL go'; connection default; ERROR 70100: Query execution was interrupted +SET debug_sync='RESET'; SET debug_sync='mysql_checksum_table_before_calculate_checksum SIGNAL parked WAIT_FOR go'; CHECKSUM TABLE t1; connection con1; diff --git a/mysql-test/main/kill_debug.test b/mysql-test/main/kill_debug.test index 0285fb48bd2..0fb6672cd60 100644 --- a/mysql-test/main/kill_debug.test +++ b/mysql-test/main/kill_debug.test @@ -338,6 +338,7 @@ connection default; error ER_QUERY_INTERRUPTED; reap; +SET debug_sync='RESET'; SET debug_sync='mysql_checksum_table_before_calculate_checksum SIGNAL parked WAIT_FOR go'; send CHECKSUM TABLE t1; connection con1; From 66cf3c6974c4a295687a78dc7bf5050db8bdbf2f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 25 Jan 2025 14:57:16 +0100 Subject: [PATCH 107/118] MDEV-35612 fix for system-versioning only ignore fully invisible fields --- mysql-test/main/partition_exchange.result | 8 ++++++++ mysql-test/main/partition_exchange.test | 14 +++++++++++--- sql/sql_table.cc | 4 ++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/mysql-test/main/partition_exchange.result b/mysql-test/main/partition_exchange.result index c9169c5c818..b856843877b 100644 --- a/mysql-test/main/partition_exchange.result +++ b/mysql-test/main/partition_exchange.result @@ -1353,3 +1353,11 @@ ERROR HY000: Tables have different definitions create or replace table tp (a int, b text, unique (b), unique(a, b)); alter table t exchange partition p0 with table tp; drop table t, tp; +create table t (a int, b int) with system versioning partition by list (a) (partition p0 values in (1,2)); +create table tp (a int, b int); +alter table t exchange partition p0 with table tp; +ERROR HY000: Tables have different definitions +create or replace table tp (a int, b int) with system versioning; +alter table t exchange partition p0 with table tp; +drop table t, tp; +# End of 10.5 tests diff --git a/mysql-test/main/partition_exchange.test b/mysql-test/main/partition_exchange.test index 767f682ea0d..5439f6411ab 100644 --- a/mysql-test/main/partition_exchange.test +++ b/mysql-test/main/partition_exchange.test @@ -594,9 +594,17 @@ create table t (a int, b text, unique (b), unique(a, b)) partition by list (a) ( create table tp (a int, b text, c int invisible, unique (b), unique(a, b)); --error ER_TABLES_DIFFERENT_METADATA alter table t exchange partition p0 with table tp; - create or replace table tp (a int, b text, unique (b), unique(a, b)); alter table t exchange partition p0 with table tp; - -# cleanup drop table t, tp; + +# same for system versioning: +create table t (a int, b int) with system versioning partition by list (a) (partition p0 values in (1,2)); +create table tp (a int, b int); # without system versioning +--error ER_TABLES_DIFFERENT_METADATA +alter table t exchange partition p0 with table tp; +create or replace table tp (a int, b int) with system versioning; +alter table t exchange partition p0 with table tp; +drop table t, tp; + +--echo # End of 10.5 tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c7ee3f83647..428b406c58c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7954,10 +7954,10 @@ bool mysql_compare_tables(TABLE *table, Alter_info *alter_info, /* Some very basic checks. */ uint fields= table->s->fields; - /* There is no field count on system-invisible fields, count them. */ + /* There is no field count on fully-invisible fields, count them. */ for (Field **f_ptr= table->field; *f_ptr; f_ptr++) { - if ((*f_ptr)->invisible >= INVISIBLE_SYSTEM) + if ((*f_ptr)->invisible >= INVISIBLE_FULL) fields--; } From fafa10dbc4f59b90f08fa67363e3c96aa2e34db3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 23 Jan 2025 12:21:32 +0100 Subject: [PATCH 108/118] update HeidiSQL to 12.10 also, switch to https --- win/packaging/heidisql.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win/packaging/heidisql.cmake b/win/packaging/heidisql.cmake index f745eeb060b..157e5517594 100644 --- a/win/packaging/heidisql.cmake +++ b/win/packaging/heidisql.cmake @@ -1,6 +1,6 @@ -SET(HEIDISQL_BASE_NAME "HeidiSQL_12.8_32_Portable") +SET(HEIDISQL_BASE_NAME "HeidiSQL_12.10_32_Portable") SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip") -SET(HEIDISQL_URL "http://www.heidisql.com/downloads/releases/${HEIDISQL_ZIP}") +SET(HEIDISQL_URL "https://www.heidisql.com/downloads/releases/${HEIDISQL_ZIP}") SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME}) IF(NOT EXISTS ${HEIDISQL_DOWNLOAD_DIR}/${HEIDISQL_ZIP}) From ffff702623e5a9d298161f5ea2e72109e301c384 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 23 Jan 2025 12:14:31 +0100 Subject: [PATCH 109/118] C/C 3.1.27 --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index 9a40079349c..7d930974c0c 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 9a40079349c44399fb8b620084862abed9c34052 +Subproject commit 7d930974c0c5588a8872f30b83d6bc429106f825 From 1fec4fc4f81b2a16ec887855ef3a1d05387bb9ea Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 14 Nov 2022 20:46:42 +0100 Subject: [PATCH 110/118] more C API methods in the service_sql for columnstore --- include/mariadb_capi_rename.h | 3 +++ include/mysql/plugin_audit.h.pp | 7 ++++-- include/mysql/plugin_auth.h.pp | 7 ++++-- include/mysql/plugin_data_type.h.pp | 7 ++++-- include/mysql/plugin_encryption.h.pp | 7 ++++-- include/mysql/plugin_ftparser.h.pp | 7 ++++-- include/mysql/plugin_function.h.pp | 7 ++++-- include/mysql/plugin_password_validation.h.pp | 7 ++++-- include/mysql/service_sql.h | 14 +++++++----- include/service_versions.h | 2 +- libmysqld/libmysql.c | 19 ---------------- sql-common/client.c | 22 +++++++++++++++++++ sql/sql_plugin_services.inl | 3 +++ 13 files changed, 73 insertions(+), 39 deletions(-) diff --git a/include/mariadb_capi_rename.h b/include/mariadb_capi_rename.h index 58e16fdc0c0..4f6750d4664 100644 --- a/include/mariadb_capi_rename.h +++ b/include/mariadb_capi_rename.h @@ -37,16 +37,19 @@ #define mysql_free_result MARIADB_ADD_PREFIX(mysql_free_result) #define mysql_get_socket MARIADB_ADD_PREFIX(mysql_get_socket) #define mysql_set_character_set MARIADB_ADD_PREFIX(mysql_set_character_set) +#define mysql_real_escape_string MARIADB_ADD_PREFIX(mysql_real_escape_string) #define mysql_get_server_version MARIADB_ADD_PREFIX(mysql_get_server_version) #define mysql_error MARIADB_ADD_PREFIX(mysql_error) #define mysql_errno MARIADB_ADD_PREFIX(mysql_errno) #define mysql_num_fields MARIADB_ADD_PREFIX(mysql_num_fields) #define mysql_num_rows MARIADB_ADD_PREFIX(mysql_num_rows) #define mysql_options4 MARIADB_ADD_PREFIX(mysql_options4) +#define mysql_fetch_fields MARIADB_ADD_PREFIX(mysql_fetch_fields) #define mysql_fetch_lengths MARIADB_ADD_PREFIX(mysql_fetch_lengths) #define mysql_fetch_row MARIADB_ADD_PREFIX(mysql_fetch_row) #define mysql_affected_rows MARIADB_ADD_PREFIX(mysql_affected_rows) #define mysql_store_result MARIADB_ADD_PREFIX(mysql_store_result) +#define mysql_use_result MARIADB_ADD_PREFIX(mysql_use_result) #define mysql_select_db MARIADB_ADD_PREFIX(mysql_select_db) #define mysql_get_ssl_cipher MARIADB_ADD_PREFIX(mysql_get_ssl_cipher) #define mysql_ssl_set MARIADB_ADD_PREFIX(mysql_ssl_set) diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index 6e3e003ad4d..07d3148ab8b 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -487,9 +487,12 @@ extern struct sql_service_st { int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + MYSQL_RES *(STDCALL *mysql_use_result_func)(MYSQL *mysql); + MYSQL_FIELD *(STDCALL *mysql_fetch_fields_func)(MYSQL_RES *res); + unsigned long (STDCALL *mysql_real_escape_string_func)(MYSQL *mysql, char *to, + const char *from, unsigned long length); my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); + const char *cert, const char *ca, const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); } diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index 7b5ce25a975..a291fcc7712 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -487,9 +487,12 @@ extern struct sql_service_st { int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + MYSQL_RES *(STDCALL *mysql_use_result_func)(MYSQL *mysql); + MYSQL_FIELD *(STDCALL *mysql_fetch_fields_func)(MYSQL_RES *res); + unsigned long (STDCALL *mysql_real_escape_string_func)(MYSQL *mysql, char *to, + const char *from, unsigned long length); my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); + const char *cert, const char *ca, const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); } diff --git a/include/mysql/plugin_data_type.h.pp b/include/mysql/plugin_data_type.h.pp index 290dafcccdb..2065abdc714 100644 --- a/include/mysql/plugin_data_type.h.pp +++ b/include/mysql/plugin_data_type.h.pp @@ -487,9 +487,12 @@ extern struct sql_service_st { int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + MYSQL_RES *(STDCALL *mysql_use_result_func)(MYSQL *mysql); + MYSQL_FIELD *(STDCALL *mysql_fetch_fields_func)(MYSQL_RES *res); + unsigned long (STDCALL *mysql_real_escape_string_func)(MYSQL *mysql, char *to, + const char *from, unsigned long length); my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); + const char *cert, const char *ca, const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); } diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp index d43cc1ef0df..866dbe4ad35 100644 --- a/include/mysql/plugin_encryption.h.pp +++ b/include/mysql/plugin_encryption.h.pp @@ -487,9 +487,12 @@ extern struct sql_service_st { int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + MYSQL_RES *(STDCALL *mysql_use_result_func)(MYSQL *mysql); + MYSQL_FIELD *(STDCALL *mysql_fetch_fields_func)(MYSQL_RES *res); + unsigned long (STDCALL *mysql_real_escape_string_func)(MYSQL *mysql, char *to, + const char *from, unsigned long length); my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); + const char *cert, const char *ca, const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); } diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index 0dea5f94a97..18f8f5829e0 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -487,9 +487,12 @@ extern struct sql_service_st { int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + MYSQL_RES *(STDCALL *mysql_use_result_func)(MYSQL *mysql); + MYSQL_FIELD *(STDCALL *mysql_fetch_fields_func)(MYSQL_RES *res); + unsigned long (STDCALL *mysql_real_escape_string_func)(MYSQL *mysql, char *to, + const char *from, unsigned long length); my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); + const char *cert, const char *ca, const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); } diff --git a/include/mysql/plugin_function.h.pp b/include/mysql/plugin_function.h.pp index 2e05f2720d5..6200cccab3d 100644 --- a/include/mysql/plugin_function.h.pp +++ b/include/mysql/plugin_function.h.pp @@ -487,9 +487,12 @@ extern struct sql_service_st { int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + MYSQL_RES *(STDCALL *mysql_use_result_func)(MYSQL *mysql); + MYSQL_FIELD *(STDCALL *mysql_fetch_fields_func)(MYSQL_RES *res); + unsigned long (STDCALL *mysql_real_escape_string_func)(MYSQL *mysql, char *to, + const char *from, unsigned long length); my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); + const char *cert, const char *ca, const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); } diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp index 3f8f6210ecf..6f79f5a534c 100644 --- a/include/mysql/plugin_password_validation.h.pp +++ b/include/mysql/plugin_password_validation.h.pp @@ -487,9 +487,12 @@ extern struct sql_service_st { int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + MYSQL_RES *(STDCALL *mysql_use_result_func)(MYSQL *mysql); + MYSQL_FIELD *(STDCALL *mysql_fetch_fields_func)(MYSQL_RES *res); + unsigned long (STDCALL *mysql_real_escape_string_func)(MYSQL *mysql, char *to, + const char *from, unsigned long length); my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); + const char *cert, const char *ca, const char *capath, const char *cipher); } *sql_service; MYSQL *mysql_real_connect_local(MYSQL *mysql); } diff --git a/include/mysql/service_sql.h b/include/mysql/service_sql.h index 0a3a2294fa1..a4a61cc0f47 100644 --- a/include/mysql/service_sql.h +++ b/include/mysql/service_sql.h @@ -68,9 +68,12 @@ extern struct sql_service_st { int (STDCALL *mysql_set_character_set_func)(MYSQL *mysql, const char *cs_name); unsigned int (STDCALL *mysql_num_fields_func)(MYSQL_RES *res); int (STDCALL *mysql_select_db_func)(MYSQL *mysql, const char *db); + MYSQL_RES *(STDCALL *mysql_use_result_func)(MYSQL *mysql); + MYSQL_FIELD *(STDCALL *mysql_fetch_fields_func)(MYSQL_RES *res); + unsigned long (STDCALL *mysql_real_escape_string_func)(MYSQL *mysql, char *to, + const char *from, unsigned long length); my_bool (STDCALL *mysql_ssl_set_func)(MYSQL *mysql, const char *key, - const char *cert, const char *ca, - const char *capath, const char *cipher); + const char *cert, const char *ca, const char *capath, const char *cipher); } *sql_service; #ifdef MYSQL_DYNAMIC_PLUGIN @@ -92,7 +95,10 @@ extern struct sql_service_st { #define mysql_set_character_set(M,C) sql_service->mysql_set_character_set_func(M,C) #define mysql_num_fields(R) sql_service->mysql_num_fields_func(R) #define mysql_select_db(M,D) sql_service->mysql_select_db_func(M,D) -#define mysql_ssl_set(M,K,C,A,P,H) sql_service->mysql_ssl_set_func(M,K,C,A,P,H) +#define mysql_use_result(M) sql_service->mysql_use_result_func(M) +#define mysql_fetch_fields(R) sql_service->mysql_fetch_fields_func(R) +#define mysql_real_escape_string(M,T,F,L) sql_service->mysql_real_escape_string_func(M,T,F,L) +#define mysql_ssl_set(M,K,C1,C2,C3,C4) sql_service->mysql_ssl_set_func(M,K,C1,C2,C3,C4) #else @@ -115,5 +121,3 @@ MYSQL *mysql_real_connect_local(MYSQL *mysql); #endif #endif /*MYSQL_SERVICE_SQL */ - - diff --git a/include/service_versions.h b/include/service_versions.h index cace4f37c69..af3e3d98785 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -43,6 +43,6 @@ #define VERSION_thd_wait 0x0100 #define VERSION_wsrep 0x0500 #define VERSION_json 0x0100 -#define VERSION_sql_service 0x0100 +#define VERSION_sql_service 0x0102 #define VERSION_thd_mdl 0x0100 #define VERSION_print_check_msg 0x0100 diff --git a/libmysqld/libmysql.c b/libmysqld/libmysql.c index 4fb5212d6e3..514a2c6e92d 100644 --- a/libmysqld/libmysql.c +++ b/libmysqld/libmysql.c @@ -1065,11 +1065,6 @@ MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr) return &(res)->fields[fieldnr]; } -MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res) -{ - return (res)->fields; -} - MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res) { return res->data_cursor; @@ -1213,15 +1208,6 @@ mysql_escape_string(char *to,const char *from,ulong length) return (uint) escape_string_for_mysql(default_charset_info, to, 0, from, length); } -ulong STDCALL -mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, - ulong length) -{ - if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) - return (uint) escape_quotes_for_mysql(mysql->charset, to, 0, from, length); - return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length); -} - void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name) { @@ -4936,11 +4922,6 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt) } -MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql) -{ - return (*mysql->methods->use_result)(mysql); -} - my_bool STDCALL mysql_read_query_result(MYSQL *mysql) { return (*mysql->methods->read_query_result)(mysql); diff --git a/sql-common/client.c b/sql-common/client.c index 476b655d6ef..b4120844920 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -4343,3 +4343,25 @@ int STDCALL mysql_cancel(MYSQL *mysql) return vio_shutdown(mysql->net.vio, SHUT_RDWR); return -1; } + + +MYSQL_RES *STDCALL mysql_use_result(MYSQL *mysql) +{ + return (*mysql->methods->use_result)(mysql); +} + + +MYSQL_FIELD *STDCALL mysql_fetch_fields(MYSQL_RES *res) +{ + return (res)->fields; +} + + +ulong STDCALL +mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, + ulong length) +{ + if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) + return (ulong) escape_quotes_for_mysql(mysql->charset, to, 0, from, length); + return (ulong) escape_string_for_mysql(mysql->charset, to, 0, from, length); +} diff --git a/sql/sql_plugin_services.inl b/sql/sql_plugin_services.inl index e560812260a..a0e9ecd8f4e 100644 --- a/sql/sql_plugin_services.inl +++ b/sql/sql_plugin_services.inl @@ -252,6 +252,9 @@ struct sql_service_st sql_service_handler= mysql_set_character_set, mysql_num_fields, mysql_select_db, + mysql_use_result, + mysql_fetch_fields, + mysql_real_escape_string, mysql_ssl_set }; From 7eded23be6597b4c485e8cad1538f2ae14541f91 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 23 Jan 2025 13:22:12 +0100 Subject: [PATCH 111/118] ColumnStore 5.6.9-1 --- storage/columnstore/columnstore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/columnstore/columnstore b/storage/columnstore/columnstore index f91c12c9df0..305fe27fa08 160000 --- a/storage/columnstore/columnstore +++ b/storage/columnstore/columnstore @@ -1 +1 @@ -Subproject commit f91c12c9df0597561b0d7f5cc6876e246d24763b +Subproject commit 305fe27fa085627000728bbaac750112365e3d55 From 3cfffb4de661fb70f27e514d9c0e4851813010f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 29 Jan 2025 09:04:50 +0200 Subject: [PATCH 112/118] MDEV-35962 CREATE INDEX fails to heal a FOREIGN KEY constraint commit_cache_norebuild(): Replace any newly added indexes in the attached foreign key constraints. --- mysql-test/suite/innodb/r/foreign_key.result | 29 ++++++++++++++++-- mysql-test/suite/innodb/t/foreign_key.test | 31 ++++++++++++++++++-- storage/innobase/handler/handler0alter.cc | 31 ++++++++++++++++++++ 3 files changed, 85 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 0404ab81c61..6c17504b5e0 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -164,9 +164,6 @@ DELETE FROM parent; ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE) ALTER TABLE child ADD INDEX(a); DELETE FROM parent; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`a`) REFERENCES `parent` (`a`) ON DELETE CASCADE) -ALTER TABLE child FORCE; -DELETE FROM parent; DROP TABLE child,parent; SELECT unique_constraint_name FROM information_schema.referential_constraints WHERE table_name = 't2'; @@ -1142,5 +1139,31 @@ DELETE FROM t2; DELETE FROM t1; DROP DATABASE `#mysql50##mysql50#d-b`; USE test; +# +# MDEV-35962 CREATE INDEX fails to heal a FOREIGN KEY constraint +# +CREATE TABLE t2 (b INT, FOREIGN KEY (b) REFERENCES t1(a)) ENGINE=InnoDB; +ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") +SET STATEMENT foreign_key_checks=0 FOR +CREATE TABLE t2 (b INT, FOREIGN KEY (b) REFERENCES t1(a)) ENGINE=InnoDB; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +SET STATEMENT foreign_key_checks=0 FOR +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`a`)) +ALTER TABLE t1 ADD KEY(a), ALGORITHM=NOCOPY; +INSERT INTO t2 VALUES (1); +DROP INDEX b ON t2; +ERROR HY000: Cannot drop index 'b': needed in a foreign key constraint +SET STATEMENT foreign_key_checks=0 FOR +DROP INDEX b ON t2; +DELETE FROM t2; +DELETE FROM t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`a`)) +ALTER TABLE t2 ADD KEY(b), ALGORITHM=NOCOPY; +DELETE FROM t1; +DROP TABLE t2, t1; # End of 10.6 tests SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index e31320ee810..23e9bf8fc82 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -142,9 +142,6 @@ INSERT INTO child SET a=1; --error ER_ROW_IS_REFERENCED_2 DELETE FROM parent; ALTER TABLE child ADD INDEX(a); ---error ER_ROW_IS_REFERENCED_2 -DELETE FROM parent; -ALTER TABLE child FORCE; DELETE FROM parent; DROP TABLE child,parent; @@ -1205,6 +1202,34 @@ DELETE FROM t1; DROP DATABASE `#mysql50##mysql50#d-b`; USE test; +--echo # +--echo # MDEV-35962 CREATE INDEX fails to heal a FOREIGN KEY constraint +--echo # + +--error ER_CANT_CREATE_TABLE +CREATE TABLE t2 (b INT, FOREIGN KEY (b) REFERENCES t1(a)) ENGINE=InnoDB; +SET STATEMENT foreign_key_checks=0 FOR +CREATE TABLE t2 (b INT, FOREIGN KEY (b) REFERENCES t1(a)) ENGINE=InnoDB; +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +SET STATEMENT foreign_key_checks=0 FOR +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO t2 VALUES (1); +ALTER TABLE t1 ADD KEY(a), ALGORITHM=NOCOPY; +INSERT INTO t2 VALUES (1); +--error ER_DROP_INDEX_FK +DROP INDEX b ON t2; +SET STATEMENT foreign_key_checks=0 FOR +DROP INDEX b ON t2; +DELETE FROM t2; +--error ER_ROW_IS_REFERENCED_2 +DELETE FROM t1; +ALTER TABLE t2 ADD KEY(b), ALGORITHM=NOCOPY; +DELETE FROM t1; +DROP TABLE t2, t1; + --echo # End of 10.6 tests SET GLOBAL innodb_stats_persistent = @save_stats_persistent; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index a967259a2ab..04e57c83f10 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -11036,6 +11036,37 @@ commit_cache_norebuild( dict_index_remove_from_cache(index->table, index); } + if (ctx->num_to_add_index) { + for (dict_foreign_t* foreign: ctx->new_table->foreign_set) { + if (foreign->foreign_table == ctx->new_table + && !foreign->foreign_index) { + foreign->foreign_index = + dict_foreign_find_index( + foreign->foreign_table, + nullptr, + foreign->foreign_col_names, + foreign->n_fields, nullptr, + /*check_charsets=*/TRUE, + /*check_null=*/FALSE, + nullptr, nullptr, nullptr); + } + } + for (dict_foreign_t* foreign: ctx->new_table->referenced_set) { + if (foreign->referenced_table == ctx->new_table + && !foreign->referenced_index) { + foreign->referenced_index = + dict_foreign_find_index( + foreign->referenced_table, + nullptr, + foreign->referenced_col_names, + foreign->n_fields, nullptr, + /*check_charsets=*/TRUE, + /*check_null=*/FALSE, + nullptr, nullptr, nullptr); + } + } + } + fts_clear_all(ctx->old_table); if (!ctx->is_instant()) { From d5e7bce14be521e59224d200434655d5edf34292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 29 Jan 2025 10:42:01 +0200 Subject: [PATCH 113/118] MDEV-35966 galera.galera_as_master crashes in debug builds innobase_commit(): When Galera is used with SET SQL_LOG_BIN=OFF, some debug assertions that had been added in commit ddd7d5d8e34c3edd7ebf4790eec2c4e4d9141e94 (MDEV-24035) would fail. Let us relax those assertions for Galera transactions, to allow an implicit commit after an internally executed XA PREPARE. Note that trx_undo_report_row_operation() only allows undo log records to be added to ACTIVE transactions (not after XA PREPARE). Hence, this relaxation should be safe with respect to writes. --- storage/innobase/handler/ha_innodb.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index bb7594cf1a0..612a4f640b4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4677,9 +4677,10 @@ innobase_commit( ut_ad("invalid state" == 0); /* fall through */ case TRX_STATE_PREPARED: - ut_ad(commit_trx); + ut_ad(commit_trx || trx->is_wsrep()); ut_ad(thd_test_options(thd, OPTION_NOT_AUTOCOMMIT - | OPTION_BEGIN)); + | OPTION_BEGIN) + || trx->is_wsrep()); /* fall through */ case TRX_STATE_ACTIVE: /* Transaction is deregistered only in a commit or a From 03d2328785db2ec1467a9c465712b2c559bcd6e6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 27 Jan 2025 19:22:20 +0100 Subject: [PATCH 114/118] MDEV-35944 DELETE fails to notice transaction abort, violating ACID Process errors of read_record(). Also, add an assert that Marko requested --- mysql-test/main/delete_innodb.result | 27 +++++++++++++++++++ mysql-test/main/delete_innodb.test | 39 +++++++++++++++++++++++++++ sql/sql_delete.cc | 18 +++++-------- storage/innobase/handler/ha_innodb.cc | 1 + 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/mysql-test/main/delete_innodb.result b/mysql-test/main/delete_innodb.result index b9f4c8bdaf5..ebee36d6ce7 100644 --- a/mysql-test/main/delete_innodb.result +++ b/mysql-test/main/delete_innodb.result @@ -24,3 +24,30 @@ SELECT * FROM t1; c1 SET sort_buffer_size=@save_sort_buffer_size; DROP TABLE t1; +# +# MDEV-35944 DELETE fails to notice transaction abort, violating ACID +# +CREATE TABLE t1 (id INT PRIMARY KEY, col_varchar VARCHAR(8)) ENGINE=InnoDB; +INSERT INTO t1 (id) VALUES (1),(2); +CREATE TABLE t2 (id INT, f INT, s DATE, e DATE, PERIOD FOR p(s,e), PRIMARY KEY(id, p WITHOUT OVERLAPS)) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,0,'2000-01-01','2000-01-02'); +CREATE TABLE t3 (id INT, f BLOB, UNIQUE(f)) ENGINE=InnoDB; +connection default; +SET innodb_lock_wait_timeout=1; +START TRANSACTION; +DELETE FROM t1; +connect con1,localhost,root,,; +START TRANSACTION; +UPDATE t2 SET f = 20; +connection default; +DELETE FROM t2 FOR PORTION OF p FROM '2000-01-01' TO '2000-01-02'; +connection con1; +INSERT INTO t3 (id) VALUES (1), (2); +UPDATE t1 SET col_varchar = 'bar'; +COMMIT; +connection default; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +COMMIT; +UPDATE t3 SET f = 'foo' ORDER BY f LIMIT 1; +DROP TABLE t1, t2, t3; +# End of 10.5 tests diff --git a/mysql-test/main/delete_innodb.test b/mysql-test/main/delete_innodb.test index c5c5c5d0172..e654b8fe691 100644 --- a/mysql-test/main/delete_innodb.test +++ b/mysql-test/main/delete_innodb.test @@ -20,3 +20,42 @@ SELECT * FROM t1; SET sort_buffer_size=@save_sort_buffer_size; DROP TABLE t1; + +--echo # +--echo # MDEV-35944 DELETE fails to notice transaction abort, violating ACID +--echo # + +CREATE TABLE t1 (id INT PRIMARY KEY, col_varchar VARCHAR(8)) ENGINE=InnoDB; +INSERT INTO t1 (id) VALUES (1),(2); +CREATE TABLE t2 (id INT, f INT, s DATE, e DATE, PERIOD FOR p(s,e), PRIMARY KEY(id, p WITHOUT OVERLAPS)) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,0,'2000-01-01','2000-01-02'); +CREATE TABLE t3 (id INT, f BLOB, UNIQUE(f)) ENGINE=InnoDB; + +--connection default +SET innodb_lock_wait_timeout=1; +START TRANSACTION; +DELETE FROM t1; + +--connect (con1,localhost,root,,) +START TRANSACTION; +UPDATE t2 SET f = 20; + +--connection default +--send + DELETE FROM t2 FOR PORTION OF p FROM '2000-01-01' TO '2000-01-02'; + +--connection con1 +INSERT INTO t3 (id) VALUES (1), (2); +UPDATE t1 SET col_varchar = 'bar'; +COMMIT; + +--connection default +--error ER_LOCK_DEADLOCK +--reap +COMMIT; +UPDATE t3 SET f = 'foo' ORDER BY f LIMIT 1; + +# Cleanup +DROP TABLE t1, t2, t3; + +--echo # End of 10.5 tests diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 2e77e32aed9..dc7b3fc00c4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -773,27 +773,21 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, MEM_STRIP_BUF_SIZE); THD_STAGE_INFO(thd, stage_searching_rows_for_update); - while (!(error=info.read_record()) && !thd->killed && - ! thd->is_error()) + while (!(error=info.read_record()) && !thd->killed && !thd->is_error()) { if (record_should_be_deleted(thd, table, select, explain, delete_history)) { table->file->position(table->record[0]); - if (unlikely((error= - deltempfile->unique_add((char*) table->file->ref)))) - { - error= 1; - goto terminate_delete; - } + if ((error= deltempfile->unique_add((char*) table->file->ref))) + break; if (!--tmplimit && using_limit) break; } } end_read_record(&info); - if (unlikely(deltempfile->get(table)) || - unlikely(table->file->ha_index_or_rnd_end()) || - unlikely(init_read_record(&info, thd, table, 0, &deltempfile->sort, 0, - 1, false))) + if (table->file->ha_index_or_rnd_end() || error > 0 || + deltempfile->get(table) || + init_read_record(&info, thd, table, 0, &deltempfile->sort, 0, 1, 0)) { error= 1; goto terminate_delete; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 612a4f640b4..33ebb9f1291 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -16313,6 +16313,7 @@ ha_innobase::external_lock( case F_UNLCK: DEBUG_SYNC_C("ha_innobase_end_statement"); m_mysql_has_locked = false; + ut_a(trx->n_mysql_tables_in_use); if (--trx->n_mysql_tables_in_use) { break; From 38d3b6027b6637d7be0da2060a6aa4c314d2337d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 26 Jan 2025 21:24:53 +0100 Subject: [PATCH 115/118] MDEV-35943 ASAN errors in Query_arena::free_items / fill_schema_table_from_frm shouldn't try to close the table if open failed. followup for deb20fb751f6 --- sql/sql_show.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 97db86644f0..6ba6f8088fa 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5093,9 +5093,11 @@ static int fill_schema_table_from_frm(THD *thd, MEM_ROOT *mem_root, tbl.s= share; table_list.table= &tbl; table_list.view= (LEX*) share->is_view; - res= schema_table->process_table(thd, &table_list, table, - res, db_name, table_name); - closefrm(&tbl); + bool res2= schema_table->process_table(thd, &table_list, table, res, + db_name, table_name); + if (res == 0) + closefrm(&tbl); + res= res2; } From 17e31abd8b6a045d6f5240a0d3387dbad942683a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 24 Jan 2025 18:05:31 +0100 Subject: [PATCH 116/118] compilation failure on CentOS 7 --- storage/innobase/handler/ha_innodb.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 33ebb9f1291..5188f5b511b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12447,9 +12447,9 @@ create_table_info_t::create_foreign_keys() if (sqlcom == SQLCOM_ALTER_TABLE) { mem_heap_t* heap = mem_heap_create(10000); - LEX_CSTRING t{innodb_convert_name(cs, m_form->s->table_name, - t_name)}; - LEX_CSTRING d{innodb_convert_name(cs, m_form->s->db, db_name)}; + LEX_CSTRING t = innodb_convert_name(cs, m_form->s->table_name, + t_name); + LEX_CSTRING d = innodb_convert_name(cs, m_form->s->db, db_name); dict_table_t* alter_table; char* n = dict_table_lookup(d, t, &alter_table, heap); @@ -12638,7 +12638,7 @@ create_table_info_t::create_foreign_keys() memcpy(foreign->foreign_col_names, column_names, i * sizeof(void*)); - LEX_CSTRING t{innodb_convert_name(cs, fk->ref_table, t_name)}; + LEX_CSTRING t = innodb_convert_name(cs, fk->ref_table, t_name); LEX_CSTRING d = fk->ref_db.str ? innodb_convert_name(cs, fk->ref_db, db_name) : LEX_CSTRING{table->name.m_name, table->name.dblen()}; From d0c2a007ee99d299042e3729bbb08b49d9eb6ba0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 24 Jan 2025 14:26:20 +0100 Subject: [PATCH 117/118] C/C 3.3.14 --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index 3f2196d84e2..2d56f340c4a 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 3f2196d84e20dd89c682fde6154849ec5bb36c85 +Subproject commit 2d56f340c4a0f2c636e317a3efd41b8c5f554088 From a89e734fcb43bf04bf82c36f49eff490c110d209 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 24 Jan 2025 14:17:15 +0100 Subject: [PATCH 118/118] ColumnStore 6.4.10-1 --- storage/columnstore/columnstore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/columnstore/columnstore b/storage/columnstore/columnstore index 9f905c07b9c..ef0647b74ac 160000 --- a/storage/columnstore/columnstore +++ b/storage/columnstore/columnstore @@ -1 +1 @@ -Subproject commit 9f905c07b9c5ba68590a7cec24e71859d4082d56 +Subproject commit ef0647b74ac41263cfdc25d3d4b5169c9e8df7ec