diff options
Diffstat (limited to 'storage/connect/ha_connect.cc')
-rw-r--r-- | storage/connect/ha_connect.cc | 173 |
1 files changed, 122 insertions, 51 deletions
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 849cf7594eb..2206cfc271d 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -170,7 +170,7 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.07.0002 October 18, 2020"; + char version[]= "Version 1.07.0002 January 27, 2021"; #if defined(__WIN__) char compver[]= "Version 1.07.0002 " __DATE__ " " __TIME__; static char slash= '\\'; @@ -230,6 +230,9 @@ char *GetUserVariable(PGLOBAL g, const uchar *varname) PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); PQRYRES VirColumns(PGLOBAL g, bool info); PQRYRES JSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info); +#ifdef BSON_SUPPORT +PQRYRES BSONColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt, bool info); +#endif // BSON_SUPPORT PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info); #if defined(REST_SUPPORT) PQRYRES RESTColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); @@ -251,11 +254,15 @@ bool ExactInfo(void); USETEMP UseTemp(void); int GetConvSize(void); TYPCONV GetTypeConv(void); +int GetDefaultDepth(void); +int GetDefaultPrec(void); bool JsonAllPath(void); char *GetJsonNull(void); -int GetDefaultDepth(void); uint GetJsonGrpSize(void); char *GetJavaWrapper(void); +#if defined(BSON_SUPPORT) +bool Force_Bson(void); +#endif // BSON_SUPPORT size_t GetWorkSize(void); void SetWorkSize(size_t); extern "C" const char *msglang(void); @@ -397,7 +404,7 @@ static MYSQL_THDVAR_ENUM( // Adding JPATH to all Json table columns static MYSQL_THDVAR_BOOL(json_all_path, PLUGIN_VAR_RQCMDARG, "Adding JPATH to all Json table columns", - NULL, NULL, 0); // NO by default + NULL, NULL, 1); // YES by default // Null representation for JSON values static MYSQL_THDVAR_STR(json_null, @@ -410,11 +417,17 @@ static MYSQL_THDVAR_STR(json_null, static MYSQL_THDVAR_INT(default_depth, PLUGIN_VAR_RQCMDARG, "Default depth used by Json, XML and Mongo discovery", - NULL, NULL, 0, -1, 16, 1); + NULL, NULL, 5, -1, 16, 1); // Defaults to 5 + +// Default precision for doubles +static MYSQL_THDVAR_INT(default_prec, + PLUGIN_VAR_RQCMDARG, + "Default precision used for doubles", + NULL, NULL, 6, 0, 16, 1); // Defaults to 6 // Estimate max number of rows for JSON aggregate functions static MYSQL_THDVAR_UINT(json_grp_size, - PLUGIN_VAR_RQCMDARG, // opt + PLUGIN_VAR_RQCMDARG, // opt "max number of rows for JSON aggregate functions.", NULL, NULL, JSONMAX, 1, INT_MAX, 1); @@ -439,6 +452,13 @@ static MYSQL_THDVAR_BOOL(enable_mongo, PLUGIN_VAR_RQCMDARG, #endif // !version 2,3 #endif // JAVA_SUPPORT || CMGO_SUPPORT +#if defined(BSON_SUPPORT) +// Force using BSON for JSON tables +static MYSQL_THDVAR_BOOL(force_bson, PLUGIN_VAR_RQCMDARG, + "Force using BSON for JSON tables", + NULL, NULL, 0); // NO by default +#endif // BSON_SUPPORT + #if defined(XMSG) || defined(NEWMSG) const char *language_names[]= { @@ -480,6 +500,7 @@ TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);} char *GetJsonNull(void) {return connect_hton ? THDVAR(current_thd, json_null) : NULL;} int GetDefaultDepth(void) {return THDVAR(current_thd, default_depth);} +int GetDefaultPrec(void) {return THDVAR(current_thd, default_prec);} uint GetJsonGrpSize(void) {return connect_hton ? THDVAR(current_thd, json_grp_size) : 10;} size_t GetWorkSize(void) {return (size_t)THDVAR(current_thd, work_size);} @@ -501,6 +522,10 @@ char *GetJavaWrapper(void) bool MongoEnabled(void) {return THDVAR(current_thd, enable_mongo);} #endif // JAVA_SUPPORT || CMGO_SUPPORT +#if defined(BSON_SUPPORT) +bool Force_Bson(void) {return THDVAR(current_thd, force_bson);} +#endif // BSON_SUPPORT) + #if defined(XMSG) || defined(NEWMSG) extern "C" const char *msglang(void) {return language_names[THDVAR(current_thd, msg_lang)];} @@ -1050,12 +1075,12 @@ static PGLOBAL GetPlug(THD *thd, PCONNECT& lxp) /****************************************************************************/ TABTYPE ha_connect::GetRealType(PTOS pos) { - TABTYPE type; + TABTYPE type= TAB_UNDEF; if (pos || (pos= GetTableOptionStruct())) { type= GetTypeID(pos->type); - if (type == TAB_UNDEF) + if (type == TAB_UNDEF && !pos->http) type= pos->srcdef ? TAB_MYSQL : pos->tabname ? TAB_PRX : TAB_DOS; #if defined(REST_SUPPORT) else if (pos->http) @@ -1063,7 +1088,8 @@ TABTYPE ha_connect::GetRealType(PTOS pos) case TAB_JSON: case TAB_XML: case TAB_CSV: - type = TAB_REST; + case TAB_UNDEF: + type = TAB_REST; break; case TAB_REST: type = TAB_NIY; @@ -1073,8 +1099,7 @@ TABTYPE ha_connect::GetRealType(PTOS pos) } // endswitch type #endif // REST_SUPPORT - } else - type= TAB_UNDEF; + } // endif pos return type; } // end of GetRealType @@ -1386,7 +1411,7 @@ PCSZ ha_connect::GetStringOption(PCSZ opname, PCSZ sdef) PTOS options= GetTableOptionStruct(); if (!stricmp(opname, "Connect")) { - LEX_CSTRING cnc= (tshp) ? tshp->connect_string + LEX_CSTRING cnc= (tshp) ? tshp->connect_string : table->s->connect_string; if (cnc.length) @@ -1572,6 +1597,7 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) // Now get column information pcf->Name= (char*)fp->field_name.str; + chset = (char*)fp->charset()->name; if (fop && fop->special) { pcf->Fieldfmt= (char*)fop->special; @@ -1582,8 +1608,15 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) pcf->Scale= 0; pcf->Opt= (fop) ? (int)fop->opt : 0; - if ((pcf->Length= fp->field_length) < 0) - pcf->Length= 256; // BLOB? + if (fp->field_length >= 0) { + pcf->Length = fp->field_length; + + // length is bytes for Connect, not characters + if (!strnicmp(chset, "utf8", 4)) + pcf->Length /= 3; + + } else + pcf->Length= 256; // BLOB? pcf->Precision= pcf->Length; @@ -1600,8 +1633,6 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf) pcf->Fieldfmt= NULL; } // endif fop - chset= (char *)fp->charset()->name; - if (!strcmp(chset, "binary")) v = 'B'; // Binary string @@ -2155,7 +2186,6 @@ int ha_connect::MakeRecord(char *buf) int rc= 0; Field* *field; Field *fp; - my_bitmap_map *org_bitmap; CHARSET_INFO *charset= tdbp->data_charset(); //MY_BITMAP readmap; MY_BITMAP *map; @@ -2169,7 +2199,7 @@ int ha_connect::MakeRecord(char *buf) *table->def_read_set.bitmap, *table->def_write_set.bitmap); // Avoid asserts in field::store() for columns that are not updated - org_bitmap= dbug_tmp_use_all_columns(table, table->write_set); + MY_BITMAP *org_bitmap= dbug_tmp_use_all_columns(table, &table->write_set); // This is for variable_length rows memset(buf, 0, table->s->null_bytes); @@ -2196,7 +2226,7 @@ int ha_connect::MakeRecord(char *buf) continue; htrc("Column %s not found\n", fp->field_name.str); - dbug_tmp_restore_column_map(table->write_set, org_bitmap); + dbug_tmp_restore_column_map(&table->write_set, org_bitmap); DBUG_RETURN(HA_ERR_WRONG_IN_RECORD); } // endif colp @@ -2256,7 +2286,7 @@ int ha_connect::MakeRecord(char *buf) sprintf(buf, "Out of range value %.140s for column '%s' at row %ld", value->GetCharString(val), - fp->field_name.str, + fp->field_name.str, thd->get_stmt_da()->current_row_for_warning()); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, buf); @@ -2279,7 +2309,7 @@ int ha_connect::MakeRecord(char *buf) memcpy(buf, table->record[0], table->s->stored_rec_length); // This is copied from ha_tina and is necessary to avoid asserts - dbug_tmp_restore_column_map(table->write_set, org_bitmap); + dbug_tmp_restore_column_map(&table->write_set, org_bitmap); DBUG_RETURN(rc); } // end of MakeRecord @@ -2299,7 +2329,7 @@ int ha_connect::ScanRecord(PGLOBAL g, const uchar *) //PTDBASE tp= (PTDBASE)tdbp; String attribute(attr_buffer, sizeof(attr_buffer), table->s->table_charset); - my_bitmap_map *bmap= dbug_tmp_use_all_columns(table, table->read_set); + MY_BITMAP *bmap= dbug_tmp_use_all_columns(table, &table->read_set); const CHARSET_INFO *charset= tdbp->data_charset(); String data_charset_value(data_buffer, sizeof(data_buffer), charset); @@ -2421,7 +2451,7 @@ int ha_connect::ScanRecord(PGLOBAL g, const uchar *) } // endfor field err: - dbug_tmp_restore_column_map(table->read_set, bmap); + dbug_tmp_restore_column_map(&table->read_set, bmap); return rc; } // end of ScanRecord @@ -2469,7 +2499,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, OPVAL op; Field *fp; const key_range *ranges[2]; - my_bitmap_map *old_map; + MY_BITMAP *old_map; KEY *kfp; KEY_PART_INFO *kpart; @@ -2486,7 +2516,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, both= ranges[0] && ranges[1]; kfp= &table->key_info[active_index]; - old_map= dbug_tmp_use_all_columns(table, table->write_set); + old_map= dbug_tmp_use_all_columns(table, &table->write_set); for (i= 0; i <= 1; i++) { if (ranges[i] == NULL) @@ -2581,11 +2611,11 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q, if ((oom= qry->IsTruncated())) strcpy(g->Message, "Out of memory"); - dbug_tmp_restore_column_map(table->write_set, old_map); + dbug_tmp_restore_column_map(&table->write_set, old_map); return oom; err: - dbug_tmp_restore_column_map(table->write_set, old_map); + dbug_tmp_restore_column_map(&table->write_set, old_map); return true; } // end of MakeKeyWhere @@ -4500,7 +4530,10 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, const char *dbn, bool case TAB_VEC: case TAB_REST: case TAB_JSON: - if (options->filename && *options->filename) { +#if defined(BSON_SUPPORT) + case TAB_BSON: +#endif // BSON_SUPPORT + if (options->filename && *options->filename) { if (!quick) { char path[FN_REFLEN], dbpath[FN_REFLEN]; @@ -4531,11 +4564,10 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, const char *dbn, bool case TAB_DIR: case TAB_ZIP: case TAB_OEM: - if (table && table->pos_in_table_list) { // if SELECT + if (table && table->pos_in_table_list) { // if SELECT #if MYSQL_VERSION_ID > 100200 Switch_to_definer_security_ctx backup_ctx(thd, table->pos_in_table_list); #endif // VERSION_ID > 100200 - return check_global_access(thd, FILE_ACL); } else return check_global_access(thd, FILE_ACL); @@ -4551,9 +4583,10 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, const char *dbn, bool case TAB_OCCUR: case TAB_PIVOT: case TAB_VIR: + default: // This is temporary until a solution is found return false; - } // endswitch type + } // endswitch type my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0)); return true; @@ -4804,6 +4837,7 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type) lock.cc by lock_external() and unlock_external() in lock.cc; the section "locking functions for mysql" in lock.cc; copy_data_between_tables() in sql_table.cc. + */ int ha_connect::external_lock(THD *thd, int lock_type) { @@ -4936,11 +4970,11 @@ int ha_connect::external_lock(THD *thd, int lock_type) // Here we do make the new indexes if (tdp->MakeIndex(g, adp, true) == RC_FX) { // Make it a warning to avoid crash - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, - 0, g->Message); - rc= 0; - //my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); - //rc= HA_ERR_INTERNAL_ERROR; + //push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + // 0, g->Message); + //rc= 0; + my_message(ER_TOO_MANY_KEYS, g->Message, MYF(0)); + rc= HA_ERR_INDEX_CORRUPT; } // endif MakeIndex } else if (tdbp->GetDef()->Indexable() == 3) { @@ -5354,7 +5388,8 @@ static char *encode(PGLOBAL g, const char *cnm) */ static bool add_field(String* sql, TABTYPE ttp, const char* field_name, int typ, int len, int dec, char* key, uint tm, const char* rem, - char* dft, char* xtra, char* fmt, int flag, bool dbf, char v) { + char* dft, char* xtra, char* fmt, int flag, bool dbf, char v) +{ #if defined(DEVELOPMENT) // Some client programs regard CHAR(36) as GUID char var = (len > 255 || len == 36) ? 'V' : v; @@ -5431,7 +5466,10 @@ static bool add_field(String* sql, TABTYPE ttp, const char* field_name, int typ, if (fmt && *fmt) { switch (ttp) { case TAB_JSON: error |= sql->append(" JPATH='"); break; - case TAB_XML: error |= sql->append(" XPATH='"); break; +#if defined(BSON_SUPPORT) + case TAB_BSON: error |= sql->append(" JPATH='"); break; +#endif // BSON_SUPPORT + case TAB_XML: error |= sql->append(" XPATH='"); break; default: error |= sql->append(" FIELD_FORMAT='"); } // endswitch ttp @@ -5596,8 +5634,8 @@ static int connect_assisted_discovery(handlerton *, THD* thd, String sql(buf, sizeof(buf), system_charset_info); sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info); - user = host = pwd = tbl = src = col = ocl = pic = fcl = skc = rnk = zfn = NULL; - dsn = url = NULL; + user= host= pwd= tbl= src= col= ocl= pic= fcl= skc= rnk= zfn= NULL; + dsn= url= NULL; // Get the useful create options ttp= GetTypeID(topt->type); @@ -5658,7 +5696,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, try { // Check table type - if (ttp == TAB_UNDEF) { + if (ttp == TAB_UNDEF && !topt->http) { topt->type= (src) ? "MYSQL" : (tab) ? "PROXY" : "DOS"; ttp= GetTypeID(topt->type); sprintf(g->Message, "No table_type. Was set to %s", topt->type); @@ -5669,11 +5707,21 @@ static int connect_assisted_discovery(handlerton *, THD* thd, goto err; #if defined(REST_SUPPORT) } else if (topt->http) { - switch (ttp) { + if (ttp == TAB_UNDEF) { + topt->type = "JSON"; + ttp= GetTypeID(topt->type); + sprintf(g->Message, "No table_type. Was set to %s", topt->type); + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); + } // endif ttp + + switch (ttp) { case TAB_JSON: - case TAB_XML: +#if defined(BSON_SUPPORT) + case TAB_BSON: +#endif // BSON_SUPPORT + case TAB_XML: case TAB_CSV: - ttp = TAB_REST; + ttp = TAB_REST; break; default: break; @@ -5856,7 +5904,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_XML: #endif // LIBXML2_SUPPORT || DOMDOC_SUPPORT case TAB_JSON: - dsn= strz(g, create_info->connect_string); +#if defined(BSON_SUPPORT) + case TAB_BSON: +#endif // BSON_SUPPORT + dsn= strz(g, create_info->connect_string); if (!fn && !zfn && !mul && !dsn) sprintf(g->Message, "Missing %s file name", topt->type); @@ -6020,8 +6071,15 @@ static int connect_assisted_discovery(handlerton *, THD* thd, qrp= VirColumns(g, fnc == FNC_COL); break; case TAB_JSON: +#if !defined(FORCE_BSON) qrp= JSONColumns(g, db, dsn, topt, fnc == FNC_COL); break; +#endif // !FORCE_BSON +#if defined(BSON_SUPPORT) + case TAB_BSON: + qrp= BSONColumns(g, db, dsn, topt, fnc == FNC_COL); + break; +#endif // BSON_SUPPORT #if defined(JAVA_SUPPORT) case TAB_MONGO: url= strz(g, create_info->connect_string); @@ -6086,6 +6144,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, goto err; } // endif !nblin + // Restore language type + if (ttp == TAB_REST) + ttp = GetTypeID(topt->type); + for (i= 0; !rc && i < qrp->Nblin; i++) { typ= len= prec= dec= flg= 0; tm= NOT_NULL_FLAG; @@ -6261,7 +6323,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, // Now add the field if (add_field(&sql, ttp, cnm, typ, prec, dec, key, tm, rem, dft, xtra, - fmt, flg, dbf, v)) + fmt, flg, dbf, v)) rc= HA_ERR_OUT_OF_MEM; } // endfor i @@ -6385,6 +6447,9 @@ int ha_connect::create(const char *name, TABLE *table_arg, // Check table type if (type == TAB_UNDEF) { options->type= (options->srcdef) ? "MYSQL" : +#if defined(REST_SUPPORT) + (options->http) ? "JSON" : +#endif // REST_SUPPORT (options->tabname) ? "PROXY" : "DOS"; type= GetTypeID(options->type); sprintf(g->Message, "No table_type. Will be set to %s", options->type); @@ -6402,7 +6467,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, DBUG_RETURN(HA_ERR_INTERNAL_ERROR); inward= IsFileType(type) && !options->filename && - (type != TAB_JSON || !cnc.length); + ((type != TAB_JSON && type != TAB_BSON) || !cnc.length); if (options->data_charset) { const CHARSET_INFO *data_charset; @@ -6760,8 +6825,8 @@ int ha_connect::create(const char *name, TABLE *table_arg, if (trace(1)) htrc("xchk=%p createas=%d\n", g->Xchk, g->Createas); -#if defined(ZIP_SUPPORT) if (options->zipped) { +#if defined(ZIP_SUPPORT) // Check whether the zip entry must be made from a file PCSZ fn= GetListOption(g, "Load", options->oplist, NULL); @@ -6783,9 +6848,11 @@ int ha_connect::create(const char *name, TABLE *table_arg, } // endif LoadFile } // endif fn - +#else // !ZIP_SUPPORT + my_message(ER_UNKNOWN_ERROR, "Option ZIP not supported", MYF(0)); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); +#endif // !ZIP_SUPPORT } // endif zipped -#endif // ZIP_SUPPORT // To check whether indexes have to be made or remade if (!g->Xchk) { @@ -7387,7 +7454,8 @@ static struct st_mysql_sys_var* connect_system_variables[]= { MYSQL_SYSVAR(json_null), MYSQL_SYSVAR(json_all_path), MYSQL_SYSVAR(default_depth), - MYSQL_SYSVAR(json_grp_size), + MYSQL_SYSVAR(default_prec), + MYSQL_SYSVAR(json_grp_size), #if defined(JAVA_SUPPORT) MYSQL_SYSVAR(jvm_path), MYSQL_SYSVAR(class_path), @@ -7397,7 +7465,10 @@ static struct st_mysql_sys_var* connect_system_variables[]= { MYSQL_SYSVAR(enable_mongo), #endif // JAVA_SUPPORT || CMGO_SUPPORT MYSQL_SYSVAR(cond_push), - NULL +#if defined(BSON_SUPPORT) + MYSQL_SYSVAR(force_bson), +#endif // BSON_SUPPORT + NULL }; maria_declare_plugin(connect) |