涉及写入操作的SQL执行方法、装置及存储介质与流程

文档序号:26139693发布日期:2021-08-03 14:23阅读:87来源:国知局
本公开涉及大数据
技术领域
:,尤其涉及一种涉及写入操作的sql执行方法、装置及存储介质。
背景技术
::hive是建立在hadoop上的数据仓库框架,提供一种类sql的语言hql(hivequerylanguage),对结构化和半结构化数据进行批量分析,完成数据计算。hql具有对海量数据处理的能力,将执行的hql语句转换为分布式计算任务,从而完成海量数据的查询和分析工作。同时,为了满足不同场景的需求,hql能通过实现用户自定义函数(userdefinedfunction,udf)、用户自定义聚合函数(user-definedaggregationfunction,udaf)以及用户自定义表函数(user-definedtable-generatingfunctions,dtf)对其进行扩展。hivesql执行sql语句的过程通常需要经历词法语法解析、语义解析、生成逻辑执行计划、优化逻辑执行计划、生成物理计划、优化物理计划这几个阶段。在词法语法解析阶段会对sql语句进行词法和语法解析,生成抽象语法树(abstractsyntaxtree,ast)。在语义解析阶段遍历ast,抽象出查询的基本组成单元queryblock。在生成逻辑执行计划阶段会遍历queryblock,构造一颗父子关系操作树operatortree。操作树通常包含tablescanoperator、selectoperator、filesinkoperator、moveoperator四类操作,filesinkoperator是把select语句的查询结果输入到临时文件。在优化逻辑执行计划阶段会通过逻辑层优化器进行操作树operatortree的变换,合并operator,达到减少mrjob,减少数据传输及shuffle数据量的目的。生成逻辑执行计划阶段和优化逻辑执行计划阶段统称为逻辑计划阶段。在生成物理执行计划阶段遍历operatortree,将operatortree翻译为mapreduce/tez/spark任务。在优化物理执行计划阶段使用物理层优化器进行物理计划的变换,生成最终的执行计划。生成和优化物理执行计划阶段统称为物理计划阶段,其主要任务是把操作树构造成work链条,然后在对work进行编排构造成task任务链,一个task任务由一个work树组成,一个work由一个操作树组成。apachehudi用于基于分布式文件系统(hdfs或云存储)接收和管理大型分析数据集的存储,是一个数据湖datalakes的开源方案。hudi将dfs上的数据集组织到基本路径下的目录结构中。数据集分为多个分区,这些分区是包含该分区的数据文件的文件夹,这与hive表非常相似。hudi可提供类似于时序数据库的功能,每次提交都有一个时间,可以查询每个时间点的数据,也可以根据提交时间查询一段时间内的增量。hudi可提供从不同时间点出发得到不同的视图下的数据集。主要特性是支持增量读取和更新插入。hudi提供两种存储类型,分别为写时复制和读时合并。写时复制存储类型仅使用列文件格式(例如parquet)存储数据,通过在写入过程中执行同步合并以更新版本并重写文件。读时合并存储类型使用列式(例如parquet)+基于行(例如avro)的文件格式组合来存储数据,更新记录到增量文件中,然后进行同步或异步压缩以生成列文件的新版本。hudi可以通过hivesql或sparksql执行引擎(统称为sql执行引擎)进行全量和增量查询,但是写入操作只能通过sparkdatasourceapi执行引擎进行操作,然后通过同步的方式,把表属性信息和分区信息同步到hive表中,但是hudi表内置了一些字段,例如以“_hoodie”开头的字段是hudi表内置的字段,这些字段在hivesql执行涉及写入操作的sql语句(例如insert、update、delete)时,无法正常得到处理,即hudi表还不支持sql执行引擎执行涉及写入操作的sql语句。技术实现要素:有鉴于此,本公开提供一种涉及写入操作的sql执行方法、装置及存储介质,用于解决hudi表不支持sql执行引擎执行涉及写入操作的sql语句的技术问题。本公开的目的是基于数据仓库实现针对hudi表的涉及写入操作的sql语句的执行。本公开技术方案对sql语句的语义解析阶段、逻辑计划阶段、物理计划阶段进行了改进,使其支持hudi表的插入(insert)、更新(update)、删除(delete/truncate)操作。图1为本公开提供的涉及写入操作的sql执行方法步骤流程图,该方法应用于安装有hadoop分布式系统基础架构、hive数据仓库框架及sparksql执行引擎的集群环境中,该方法包括:步骤s101.对接收到的sql语句进行词法和语法解析,生成抽象语法树ast,并获取元数据;所述sql语句包括针对hudi表的类型为插入类、更新类或删除类的sql语句;步骤s102.在语义解析阶段,在生成所述sql语句的抽象语法树ast后,构造hudi参数对象;其中,所述hudi参数至少包括表元数据信息、临时文件地址、hudi标识、sql语句类型;所述hudi标识用于标识是否为针对hudi表的操作;步骤s103.在逻辑计划阶段,根据hudi参数对象判定所处理的表为hudi表时,修改操作树中用于将中间结果数据写入临时文件的操作符对应的对象,使所述对象将hudi表内置字段剔除;步骤s104.在物理计划阶段,将原始生成的任务树中移动类任务替换为sparttask任务,所述sparktask任务用于读取存放中间结果的临时文件并直接调用sparkdatasourceapi接口对hudi表执行与hudi对象中sql语句类型相对应的操作。进一步地,在所述构造hudi参数对象之前,所述方法还包括:根据所述抽象语法树,判断所述sql语句是否是针对hudi表的操作;如果是针对hudi表的操作,则执行构造hudi参数对象的步骤,然后遍历所述抽象语法树,生成查询块;如果不是针对hudi表的操作,直接执行遍历所述抽象语法树,生成查询块的步骤;所述查询块用于在逻辑计划阶段生成操作树。进一步地,在判定是针对hudi表的操作之后,在构造hudi参数对象之前,所述方法还包括:判断所述sql语句的类型是否为更新类或删除类的sql语句,若判定为更新类或删除类的sql语句,则将所生成的抽象语法树重构为针对hudi表的插入类sql语句的抽象语法树,即根据原始生成的抽象语法树及表元数据信息新建一颗针对hudi表的insertast,剔除insertast中的hudi表内置字段,并以新的insertast替换掉原始生成的抽象语法树。进一步地,所述sql执行引擎为hivesql执行引擎或sparksql执行引擎。进一步地,根据所述元数据中的表属性inputformat是否为“org.apache.hudi.hadoop.hoodieparquetinputformat”来判断是否是针对hudi表的sql语句。图2为本公开提供的一种涉及写入操作的sql执行装置结构示意图,该装置200中的各功能模块可以采用软件、硬件或软硬件相结合的方式实现。当多个硬件设备共同实施本公开的技术方案时,由于各硬件设备之间相互协作的目的是共同实现本发明目的,一方的动作和处理结果确定了另一方的动作执行的时机及可能获得的结果,因此,可视为各执行主体之间具有相互协作关系,各执行主体之间具有相互指挥和控制关系。本公开所提供的装置200包括:词法语法解析模块210,用于对接收到的sql语句进行词法和语法解析,生成抽象语法树ast,并获取元数据;所述sql语句包括针对hudi表的类型为插入类、更新类或删除类的sql语句;语义解析模块211,用于所述sql语句进行语义解析,在生成所述sql语句的抽象语法树ast后,构造hudi参数对象;其中,所述hudi参数至少包括表元数据信息、临时文件地址、hudi标识、sql语句类型;所述hudi标识用于标识是否为针对hudi表的操作;逻辑计划模块212,用于所述sql语句的逻辑执行计划的生成和优化,根据hudi参数对象判定所处理的表为hudi表时,修改操作树中用于将中间结果数据写入临时文件的操作符对应的对象,使所述对象将hudi表内置字段剔除;物理计划模块213,用于所述sql语句的物理执行计划的生成和优化,将原始生成的任务树中移动类任务替换为sparttask任务,所述sparktask任务用于读取存放中间结果的临时文件并直接调用sparkdatasourceapi接口对hudi表执行与hudi对象中sql语句类型相对应的操作。进一步地,所述语义解析模块211在构造hudi参数对象之前,还用于根据所述抽象语法树,判断所述sql语句是否是针对hudi表的操作;如果是针对hudi表的操作,则执行构造hudi参数对象的步骤,然后遍历所述抽象语法树,生成查询块;如果不是针对hudi表的操作,直接执行遍历所述抽象语法树,生成查询块的步骤;所述查询块用于在逻辑计划阶段生成操作树。进一步地,所述语义解析模块211在判定是针对hudi表的操作之后,在构造hudi参数对象之前,还用于判断所述sql语句的类型是否为更新类或删除类的sql语句,若判定为更新类或删除类的sql语句,则将所生成的抽象语法树重构为针对hudi表的插入类sql语句的抽象语法树即insertast,并剔除其中的hudi表内置字段。本公开对sql语句的语义解析阶段、逻辑计划阶段、物理计划阶段进行了改进,将根据sql语句生成的原始ast统一重构为insertast并在hudi参数对象中记录sql语句类型,在逻辑计划阶段在操作树中剔除hudi表的内置字段,在物理计划阶段使用sparttask任务替换movetask任务,根据所记录的sql语句类型执行相应操作。本公开实现了基于hive数据仓库的hudi存储格式,提供统一sql支持,减少用户的繁琐代码、配置等工作,使用更加快捷、易用、灵活。附图说明为了更加清楚地说明本公开实施例或者现有技术中的技术方案,下面将对本公开实施例或者现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本公开中记载的一些实施例,对于本领域普通技术人员来讲,还可以根据本公开实施例的这些附图获得其他的附图。图1为本公开提供的涉及写入操作的sql执行方法步骤流程图;图2为本公开提供的一种涉及写入操作的sql执行装置结构示意图;图3为本公开一实施例提供的一种针对hudi表涉及写入操作的sql语句的执行方法的步骤流程示意图;图4a为本公开一实施例中更新类update语句抽象语法树的示例;图4b为本公开一实施例中将更新类update语句的ast重构为插入类insert语句的ast的示意图;图5a为本公开一实施例中删除类delete语句抽象语法树的示例;图5b为本公开一实施例中将删除类delete语句的ast重构为插入类insert语句的ast的示意图;图6为本公开一实施例提供的一种实施本公开提供的方法的电子设备结构示意图。具体实施方式在本公开实施例使用的术语仅仅是出于描述特定实施例的目的,而非限制本公开实施例。本公开实施例中所使用的单数形式的“一种”、“所述”和“该”也旨在包括多数形式,除非上下文清楚地表示其它含义。本公开中使用的术语“和/或”是指包含一个或多个相关联的列出项目的任何或所有可能组合。应当理解,尽管在本公开实施例可能采用术语第一、第二、第三等来描述各种信息,但这些信息不应限于这些术语。这些术语仅用来将同一类型的信息彼此区分开。例如,在不脱离本公开实施例范围的情况下,第一信息也可以被称为第二信息,类似地,第二信息也可以被称为第一信息。取决于语境,此外,所使用的词语“如果”可以被解释成为“在……时”或“当……时”或“响应于确定”。本公开技术方案的目的是实现hivesql或sparksql等sql执行引擎支持执行有关hudi表的涉及写入操作的sql语句。本公开所述的涉及写入操作的sql语句是指会引起向hudi物理存储空间执行物理写入或更新操作的语句,这种写入操作可能是因为向hudi表中新增记录、删除记录、修改记录或清空表中的记录等任何一种操作所引起。为实现上述目的,本公开技术方案对上述涉及写入操作的sql语句的语义解析阶段、逻辑计划阶段、物理计划阶段进行了改进。图3为本公开一实施例提供的一种针对hudi表涉及写入操作的sql语句的执行方法的步骤流程示意图。为简化流程,该附图以sql执行引擎接收到有关hudi表涉及写入操作的sql语句的处理过程为例,给出sql语句处理步骤。其中,深色线框内的步骤为本公开技术方案对现有技术做出改进的部分。该实施例以安装有hadoop分布式系统基础架构、hive数据仓库框架及sparksql执行引擎的集群环境为例对本公开提供的方法进行详细描述。步骤301.对接收到的sql语句进行词法和语法解析,生成抽象语法树ast;该实施例设定的应用场景为所接收到的sql语句为针对hudi表涉及写入操作的sql语句,例如这些语句可以为结构化查询语言(structurequerylanguage,sql)中的插入insert语句、更新update语句、删除delete语句、清空truncate语句中的任何一种。对于不涉及写入操作的sql语句只需要按sql执行引擎现有处理方式处理即可,本公开不做过多赘述。sql语句的执行过程需要经过词法语法解析阶段、语义解析阶段、逻辑计划阶段和物理计划阶段,在完成上述四个阶段后,sql执行引擎才能实际的完成相应的操作任务。词法语法解析阶段的作用是将sql语句的“字符串”变换为一个描述这个字符串的“结构体”,让计算机可以更容易的理解用户输入的字符串是什么意义。这个阶段包含三个过程,分别是词法解析过程、语法解析过程、输出抽象语法树ast过程,经过上述三个过程后最终将sql语句转化成抽象语法树(abstractsyntaxtree,ast)。抽象语法树ast是sql语句的树形结构的表现形式,树上的每一个节点都是一个单词,树的结构体现了语法。抽象语法树是随着语法解析的过程构造的,当语法解析正常结束后,语法解析器就会输出一个抽象语法树。步骤302.获取元数据,所述元数据信息包括表属性;在语法解析阶段,sql执行引擎会基于ast树获取sql语句中涉及到的表的元数据信息,对sql语句所涉及到的元数据信息进行验证,例如验证ast树中的hudi表、表中的字段等是否存在,名称是否正确,所执行的操作是否违反相关表或字段的约束条件等。以hive为例,hive所有的表结构信息都存储在元数据服务metastore中,表数据都存储在hdfs之上,想要获得表结构信息,就需要从元数据服务中读取。步骤303.根据sql语句的类型,对sql语句进行语义解析生成对应的抽象语法树ast;由于sql执行引擎针对不同类型的sql语句,解析的规则和方式不同,因此需要在语义解析之前区分sql语句的类型,然后再根据sql语句的类型分别进行解析。以标准sql语句为例,sql语句的类型可分为插入类语句(insert)、更新类语句(update)、删除类语句(delete/truncate)等,因此该步骤中会根据sql语句的类型对应地会生成insertast、updateast或deleteast。对于插入类sql语句在语义解析过程中直接执行步骤305,对于更新类或删除类语句在语义解析过程中需要首先执行步骤304然后再执行步骤305。需要说明的是,步骤304和步骤305是针对hudi表才需要执行的步骤,因此在执行步骤304或步骤305之前,需要根据所获取的元数据中的表属性判断是否是hudi格式的表,若为非hudi格式的表,则按执行引擎原有流程直接执行步骤306即可。判断是否为hudi格式的表的方式可以为:根据获取的元数据中表属性inputformat判断是否为“org.apache.hudi.hadoop.hoodieparquetinputformat”来判断对应的表是否为hudi格式的表,如果判定是上述格式,则标记hudi标识为指示该表为hudi表的标识符。步骤304.将更新/删除类sql语句的ast树重构为插入类sql语句的ast树;hudi表支持插入模式更新,即当表中不存在insert语句中的记录时,执行插入操作,当表中存在insert语句中的记录时,直接以新字段更新原有字段值。因此本公开的思路是将标准sql中的更新类(update)和删除类(delete/truncate)sql语句的ast树都统一先重构为hudi表支持的insertast树,同时通过hudi参数对象记录重构的insertast树所对应的sql语句的类型,在最终将存储于临时文件位置的中间结果写入hudi表时,根据hudi参数对象中记录的sql语句类型执行与sql语句类型向对应的操作。图4a和图4b以sql语句“updatehudi_trips_cowsetrider='test'whereuuid='25'”为例,示例了根据原始生成的updateast树及表元数据信息,将updateast树重构为insertast树的方式。该步骤中根据前述步骤已经生成的updateast以及根据ast获取的元数据新构造出一颗针对hudi表的insertast树,与该重构出来的insertast对应的insertsql语句示例为:“insertintohudi_trips_cowselect_hoodie_commit_id,uuid,riderfromhudi_trips_cowwhereuuid=’25’”,然后还需要在重构的insertast中删除掉hudi表内置字段(例如hoodie_commit_id等字段),此外还需要将待更新字段的值直接替换为新值,例如将rider字段值直接替换为前述update语句中的更新值’test’。图5a和图5b以sql语句“deletedeletefromhudi_trips_cowwhereuuid='25'”为例,示例了根据原始生成的deleteast树及表元数据信息,将deleteast树重构为insertast树的方式。该步骤中根据前述步骤中已经生成的deleteast树及表元数据信息新构造出一颗针对hudi表的insertast树,与重构出来的的insertast对应的insertsql语句示例为:“insertintohudi_trips_cowselect_hoodie_commit_id,uuid,riderfromhudi_trips_cowwhereuuid=’25’”,然后还需要在重构的insertast中删除掉hudi表内置字段(例如hoodie_commit_id等字段)。对于删除类sql语句,重构后的inertast树仅起到定位记录的作用,在movetask任务执行时会实际执行删除对应记录的操作。步骤305.构造hudi参数对象,所述hudi参数至少包括表元数据信息、临时文件地址、hudi标识、sql语句类型;该步骤构造一个自定义的hudi对象,该对象用来存储hive表元数据信息、临时文件地址、hudi标识、sql语句类型等。其中,临时文件地址为中间结果存放在分布式文件系统hdfs上的临时地址;hudi标识用于标识是否是对hudi表的操作;sql语句类型字段用于记录原始ast树对应的sql语句的类型,主要分为新增(insert)类型、更新(update)类型、删除(delete/truncate)类型三种。例如,当原ast树为insertast树时,hudi对象中的sql语句类型字段值为新增类型标识,当原ast树为updateast树时,hudi对象中的sql语句类型字段值为更新类型标识,当原ast树为deleteast树时,hudi对象中的sql语句类型字段值为删除类型标识,依次类推。步骤306.遍历ast,生成查询的基本组成单元即查询块queryblock;步骤307.遍历查询块queryblock,生成操作树operatortree;在逻辑计划阶段,首先会遍历queryblock,构造生成一颗父子关系操作树operatortree。操作树通常包括用于扫描表数据的操作符tablescanoperator、用于选择输出列的操作符selectoperator、用于将查询结果数据输出至临时文件的操作符filesinkoperator和用于将存储中间结果的文件移动到hive相应的表目录下的操作符moveoperator。本公开在逻辑计划阶段,对操作树中的filesinkoperator操作符对应的处理步骤做了改进,当根据hudi参数对象判定所处理的表为hudi表时,修改操作树中用于将中间结果数据写入临时文件的操作符对应的对象,使所述对象将hudi表内置字段剔除。例如,当根据hudi参数对象判断到所处理的表为hudi表时,将filesinkoperator操作符对象所包括的filesinkdesc对象中的hudi表内置字段(以“_hoodie”开头的字段)剔除,使filesinkoperator操作符按照hudi表字段顺序的把中间结果输出到临时文件中。步骤308.优化操作树;在逻辑计划阶段,在生成操作树operatortree之后,需要对所生成的操作树进行优化。在优化时,会通过逻辑层优化器进行操作树operatortree的变换,合并操作符operator,达到减少mapreduce作业量,减少数据传输及洗牌shuffle数据量的目的。步骤309.遍历操作树,生成原始任务树;在物理计划阶段,会遍历逻辑计划阶段生成和优化后的操作树operatortree,将operatortree翻译生成与所使用的大规模数据处理引擎(例如mapreduce/tez/spark等)类型相对应的任务树即task树。本公开将根据优化后的操作树初始生成的任务树命名为原始任务树,将原始任务树中的任务区分为两类,一类是为获得最终结果而执行的获取结果类任务,另一类为将位于临时文件位置的最终的处理结果移动到分布式数据库中的表目录下的移动类任务。获取结果类任务可包括与扫描表数据的操作符tablescanoperator、选择输出列的操作符selectoperator、将查询结果数据输出至临时文件的操作符filesinkoperator等一种或多种操作符相对应的任务,移动类任务为与moveoperator操作符对应的任务。步骤310.重构原始任务task树,将原始任务树中movetask任务替换为sparktask任务,所述sparktask任务用于读取临时文件并直接调用sparkdatasourceapi接口对hudi表进行与hudi对象中sql语句类型相对应的操作。物理计划阶段,原movetask是把临时文件移动到分布式数据库的表目录下,但是在前述步骤中生成的临时文件,不满足hudi表存储结构要求,故需要对生成的任务树进行重构,将其中的movetask任务替换为本公开新构造的sparktask任务。sparktask任务会读取临时文件,并根据前面步骤获得的自定义的hudi对象中的信息,对hudi表直接调用sparkdatasourceapi接口进行与hudi对象中sql语句类型相对应的操作,如hudi表为分区表,还需要更新分区元数据。例如,当hudi对象中sql语句类型为插入insert类型时,使sql执行引擎在执行任务时,直接调用sparkdatasourceapi接口对hudi表进行新增(insert)操作。当hudi对象中sql语句类型为更新update类型时,使sql执行引擎在执行任务时,直接调用sparkdatasourceapi接口对hudi表插入更新(upsert)操作。当hudi对象中sql语句类型为删除(delete/truncte)类型时,使sql执行引擎在执行任务时,直接调用sparkdatasourceapi接口对hudi表进行相应的删除(delete/truncte)操作。步骤311.执行所生成的任务;至此,完成了针对hudi表涉及写入操作的sql语句的执行。通过本公开提供的技术方案,能够实现基于hive数据仓库的hudi存储格式,提供统一sql支持,减少用户的繁琐代码、配置等工作,使用更加快捷、易用、灵活。图6为本公开一实施例提供的一种实施本公开提供的方法的电子设备结构示意图,该设备600包括:诸如中央处理单元(cpu)的处理器610、通信总线620、通信接口640以及存储介质630。其中,处理器610与存储介质630可以通过通信总线620相互通信。存储介质630内存储有计算机程序,当该计算机程序被处理器610执行时即可实现本公开提供的方法的各步骤。其中,存储介质可以包括随机存取存储器(randomaccessmemory,ram),也可以包括非易失性存储器(non-volatilememory,nvm),例如至少一个磁盘存储器。另外,存储介质还可以是至少一个位于远离前述处理器的存储装置。处理器可以是通用处理器,包括中央处理器(centralprocessingunit,cpu)、网络处理器(networkprocessor,np)等;还可以是数字信号处理器(digitalsignalprocessing,dsp)、专用集成电路(applicationspecificintegratedcircuit,asic)、现场可编程门阵列(field-programmablegatearray,fpga)或其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件。应当认识到,本公开的实施例可以由计算机硬件、硬件和软件的组合、或者通过存储在非暂时性存储器中的计算机指令来实现或实施。所述方法可以使用标准编程技术,包括配置有计算机程序的非暂时性存储介质在计算机程序中实现,其中如此配置的存储介质使得计算机以特定和预定义的方式操作。每个程序可以以高级过程或面向对象的编程语言来实现以与计算机系统通信。然而,若需要,该程序可以以汇编或机器语言实现。在任何情况下,该语言可以是编译或解释的语言。此外,为此目的该程序能够在编程的专用集成电路上运行。此外,可按任何合适的顺序来执行本公开描述的过程的操作,除非本公开另外指示或以其他方式明显地与上下文矛盾。本公开描述的过程(或变型和/或其组合)可在配置有可执行指令的一个或多个计算机系统的控制下执行,并且可作为共同地在一个或多个处理器上执行的代码(例如,可执行指令、一个或多个计算机程序或一个或多个应用)、由硬件或其组合来实现。所述计算机程序包括可由一个或多个处理器执行的多个指令。进一步,所述方法可以在可操作地连接至合适的任何类型的计算平台中实现,包括但不限于个人电脑、迷你计算机、主框架、工作站、网络或分布式计算环境、单独的或集成的计算机平台、或者与带电粒子工具或其它成像装置通信等等。本公开的各方面可以以存储在非暂时性存储介质或设备上的机器可读代码来实现,无论是可移动的还是集成至计算平台,如硬盘、光学读取和/或写入存储介质、ram、rom等,使得其可由可编程计算机读取,当存储介质或设备由计算机读取时可用于配置和操作计算机以执行在此所描述的过程。此外,机器可读代码,或其部分可以通过有线或无线网络传输。当此类媒体包括结合微处理器或其他数据处理器实现上文所述步骤的指令或程序时,本公开所述的发明包括这些和其他不同类型的非暂时性计算机可读存储介质。当根据本公开所述的方法和技术编程时,本公开还包括计算机本身。以上所述仅为本公开的实施例而已,并不用于限制本公开。对于本领域技术人员来说,本公开可以有各种更改和变化。凡在本公开的精神和原理之内所作的任何修改、等同替换、改进等,均应包含在本公开的保护范围之内。当前第1页12当前第1页12
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1