首页 > 数据库 >MySQL如何初始化常量Item?

MySQL如何初始化常量Item?

时间:2023-06-15 15:04:36浏览次数:46  
标签:YYTHD 初始化 error float Item length str MySQL


MySQL中的一切表达式都是继承自Item类,常量也不外乎如此。以Item_float为例子说明MySQL如何初始化常量Item。

首先在Parser里面:

NUM_literal:
          NUM
          {
            int error;
            $$= new (YYTHD->mem_root)
                  Item_int($1,
                           (longlong) my_strtoll10($1.str, NULL, &error),
                           $1.length);
            if ($$ == NULL)
              MYSQL_YYABORT;
          }
        | LONG_NUM
          {
            int error;
            $$= new (YYTHD->mem_root)
                  Item_int($1,
                           (longlong) my_strtoll10($1.str, NULL, &error),
                           $1.length);
            if ($$ == NULL)
              MYSQL_YYABORT;
           }
        | ULONGLONG_NUM
          {
            $$= new (YYTHD->mem_root) Item_uint($1.str, $1.length);
            if ($$ == NULL)
              MYSQL_YYABORT;
          }
        | DECIMAL_NUM
          {
            $$= new (YYTHD->mem_root) Item_decimal($1.str, $1.length,
                                                   YYTHD->charset());
            if (($$ == NULL) || (YYTHD->is_error()))
            {
              MYSQL_YYABORT;
            }
          }
        | FLOAT_NUM
          {
            $$= new (YYTHD->mem_root) Item_float($1.str, $1.length);
            if (($$ == NULL) || (YYTHD->is_error()))
            {
              MYSQL_YYABORT;
            }
          }
        ;

FLOAT_NUM部分编译后变成如下代码:

case 1946:
/* Line 1455 of yacc.c  */
#line 13534 "/export/home/pb2/build/sb_0-15908920-1436909309.31
#            /mysql-5.6.26-release-export-8213452_gpl/sql/sql_yacc.yy"
{
     (yyval.item_num)=
        new (YYTHD->mem_root) Item_float((yyvsp[(1) - (1)].lex_str).str,
                                         (yyvsp[(1) - (1)].lex_str).length);
     if (((yyval.item_num) == NULL) || (YYTHD->is_error()))
     {
          MYSQL_YYABORT;
     }
}
break;

对应的Item_float构造函数为:

/**
  This function is only called during parsing:
  - when parsing SQL query from sql_yacc.yy
  - when parsing XPath query from item_xmlfunc.cc
  We will signal an error if value is not a true double value (overflow):
  eng: Illegal %s '%-.192s' value found during parsing

  Note: str_arg does not necessarily have to be a null terminated string,
  e.g. it is NOT when called from item_xmlfunc.cc or sql_yacc.yy.
*/

Item_float::Item_float(const char *str_arg, uint length)
{
  int error;
  char *end_not_used;
  value= my_strntod(&my_charset_bin, (char*) str_arg,
                    length, &end_not_used,
                    &error);
  if (error)
  {
    char tmp[NAME_LEN + 1];
    my_snprintf(tmp, sizeof(tmp), "%.*s", length, str_arg);
    my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", tmp);
  }
  presentation.copy(str_arg, length);
  item_name.copy(str_arg, length);
  decimals=(uint8) nr_of_decimals(str_arg, str_arg+length);
  max_length=length;
  fixed= 1;
}

可见,对于Float、Int、Decimal等,都是先传入字符串及其长度,然后他们内部进行解析,以确定max_length、decimals等值。

既然说到了Item_float,就顺便说一下里面的一个函数nr_of_decimals,它用来计算浮点数中小数点后面的位数,然而,如代码中的注释所言,这个函数跟没有啥鸟用,是Decimal出现之前的产物。在Decimal出现之前 1.35会被当做一个浮点数,下面的函数会计算出decimal=2;有了Decimal之后,1.35根本不会被当做float,而是直接当做Decimal处理。

static uint nr_of_decimals(const char *str, const char *end)
{
  const char *decimal_point;

  /* Find position for '.' */
  for (;;)
  {
    if (str == end)
      return 0;
    if (*str == 'e' || *str == 'E')
      return NOT_FIXED_DEC;
    if (*str++ == '.')
      break;
  }
  decimal_point= str;
  for ( ; str < end && my_isdigit(system_charset_info, *str) ; str++)
    ;
  if (str < end && (*str == 'e' || *str == 'E'))
    return NOT_FIXED_DEC;
  /*
    QQ:
    The number of decimal digist in fact should be (str - decimal_point - 1).
    But it seems the result of nr_of_decimals() is never used!

    In case of 'e' and 'E' nr_of_decimals returns NOT_FIXED_DEC.
    In case if there is no 'e' or 'E' parser code in sql_yacc.yy
    never calls Item_float::Item_float() - it creates Item_decimal instead.

    The only piece of code where we call Item_float::Item_float(str, len)
    without having 'e' or 'E' is item_xmlfunc.cc, but this Item_float
    never appears in metadata itself. Changing the code to return
    (str - decimal_point - 1) does not make any changes in the test results.

    This should be addressed somehow.
    Looks like a reminder from before real DECIMAL times.
  */
  return (uint) (str - decimal_point);
  }

所以,对于float来说,这个函数总是返回NOT_FIXED_DEC(=31)

fix variable decimals which always is NOT_FIXED_DEC

关于NOT_FIXED_DEC,会在下一篇博客中详细讨论。


标签:YYTHD,初始化,error,float,Item,length,str,MySQL
From: https://blog.51cto.com/u_16162111/6492516

相关文章

  • 详解MySQL Server端如何发送结果集给客户端
    MySQLServer和Client之间的交互有一套定义得很明确的协议,称为MySQLClient/ServerProtocol。写数据库的人,只需要遵循这套协议来写程序,就能让自己的数据库被各种MySQL客户端连接,如mysql命令行,phpmysql,JDBC等等。这是一个非常诱人的设计选择(DesignChoice)!如果自己实现一套协议,写......
  • CentOs7安装部署Sonar环境(JDK1.8+MySql5.7+sonarqube7.8)
    sonarqube安装前环境准备JDK1.8、MySql5.7。一、JDK安装1、下载jdk#打开下面的网址,选择jdk-8u371-linux-x64.tar.gz进行下载(8u371版本可能会有区别,但是没有影响)http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html2、安装jdk#创建......
  • 云小课|RDS for MySQL参数模板一键导入导出,参数配置轻松搞定
    摘要:云数据库RDSforMySQL支持参数模板的导入和导出功能。本文分享自华为云社区《【云小课】【第56课】RDSforMySQL参数模板一键导入导出,参数配置轻松搞定》,作者:数据库的小云妹。云数据库RDSforMySQL支持参数模板的导入和导出功能。导入参数模板:导入后会生成一个新的参数模板,......
  • 云小课|RDS for MySQL参数模板一键导入导出,参数配置轻松搞定
    摘要:云数据库RDSforMySQL支持参数模板的导入和导出功能。本文分享自华为云社区《【云小课】【第56课】RDSforMySQL参数模板一键导入导出,参数配置轻松搞定》,作者:数据库的小云妹。云数据库RDSforMySQL支持参数模板的导入和导出功能。导入参数模板:导入后会生成一个新的参......
  • mysql和neo4j集成多数据源和事务
    在微服务大行其道的今天,按理说不应该有多数据源这种问题(嗯,主从库算是一个多数据源的很常见的场景。),但是也没人规定不能这样做。就算有人规定的,曾经被奉为圭臬的数据库三大范式现在被宽表冲得七零八落,在很多场景下,其实是鼓励建立冗余字段的。话说项目中需要用到图数据库,我们选用......
  • 基于中间件实现MySQL读写分离
    1.场景在数据库读多写少的时候2.读写分离只在主服务器上写,只在从服务器上读。使用amoeba中间件3.部署3.1Dockercompose一键部署Compose文件:version:'3.8'services:mysql_master:image:mysql:8.0.33-oracle......
  • windows环境下操作,同一台机器 如何跑两个mysql服务?
    在同一台机器上运行两个MySQL服务是可行的,但需要注意以下几点:确保端口号不冲突。每个MySQL服务都需要监听一个独立的端口,以便客户端可以连接到正确的服务。配置文件的区分。每个MySQL实例需要有自己独立的配置文件,包括数据存储路径、日志文件路径等信息。确保资源......
  • 如何从CLI管理阿里巴巴MySQL数据库
    阿里云提供高度可用的按需MySQL,SQLServer和PostgreSQL数据库,作为其ApsaraDBforRDS  (关系数据库服务)的一部分。RDS易于设置和部署。该服务处理数据库服务器的所有管理任务,包括在发生灾难时进行配置,修补和恢复。除了这个即用型数据库服务,您还可以选择从弹性计算服务(ECS)实例设置......
  • MySQL中的非确定性函数(即rand)可能会让您感到惊讶
    使用sysbench处理测试用例,我遇到了这个问题:的MySQL>选择*从sbtest1其中ID=ROUND(RAND()*10000,0);+------+--------+-------------------------------------------------------------------------------------------------------------------------+----------------......
  • MySQL数据库运维实录--通过MySQL Shell Dump/Load 实现数据库对象的逻辑备份与恢复
    [mysql@node01~]$mysqlshMySQLJS>\connectroot@node01:3306MySQLnode01:3306sslJS>util.dumpInstance('/home/mysql/backup')[mysql@node01~]$scp-rbackup/*node02:/home/mysql/backup/util.dumpInstance的关键特性1,多线程备份。并发线程数由thr......