CN114341831A - 可插拔访客语言的数据库模块化 - Google Patents
可插拔访客语言的数据库模块化 Download PDFInfo
- Publication number
- CN114341831A CN114341831A CN202080060981.2A CN202080060981A CN114341831A CN 114341831 A CN114341831 A CN 114341831A CN 202080060981 A CN202080060981 A CN 202080060981A CN 114341831 A CN114341831 A CN 114341831A
- Authority
- CN
- China
- Prior art keywords
- guest
- module
- mle
- language
- programming language
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/20—Information retrieval; Database structures therefor; File system structures therefor of structured data, e.g. relational data
- G06F16/24—Querying
- G06F16/242—Query formulation
- G06F16/2433—Query languages
- G06F16/2443—Stored procedures
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/20—Information retrieval; Database structures therefor; File system structures therefor of structured data, e.g. relational data
- G06F16/21—Design, administration or maintenance of databases
- G06F16/211—Schema design and management
- G06F16/212—Schema design and management with details for data modelling support
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/46—Multiprogramming arrangements
- G06F9/54—Interprogram communication
- G06F9/541—Interprogram communication via adapters, e.g. between incompatible applications
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Physics & Mathematics (AREA)
- Databases & Information Systems (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Data Mining & Analysis (AREA)
- Software Systems (AREA)
- Mathematical Physics (AREA)
- Computational Linguistics (AREA)
- Stored Programmes (AREA)
- Devices For Executing Special Programs (AREA)
Abstract
本文中是扩展软件***来嵌入以透明、模块化和可配置方式交互操作的新的访客编程语言(GPL)的技术。在实施例中,计算机将GPL的实现***到***的部署中。命令注册GPL,为GPL定义子例程,生成访客虚拟环境,并添加依赖项与访客模块的绑定。在实施例中,原生编程语言调用访客编程语言以使得导入语言内或语言间依赖项。实施例定义了在第一GPL中实现并从第二GPL访问的访客对象。在实施例中,从具有几个备选实现机制的虚拟文件***中检索依赖项,所述备选实现机制包括:归档文件或实际文件***,以及存储缓冲器或数据库表格的列。
Description
技术领域
本发明涉及诸如数据库管理***(DBMS)之类的软件***的多语言编程。本文中是扩展软件***来嵌入以透明、模块化和可配置方式交互操作的新的访客(guest)编程语言的技术。
背景技术
诸如JavaScript和Python之类的现代编程语言受益于由公共可用库和附加组件组成的丰富而庞大的生态***。然而,数据库***很少或根本不支持多种编程语言。例如,就JavaScript和Python来说,包管理和包导入具有可能难以或不可能调和的不同方法。
在JavaScript生态***中,代码库捆绑工具的使用是常见的。这些工具通过内联依赖项(dependency)的源代码来解决由require语句所施加的包依赖项。这些捆绑技术的结果是包含所有必需源逻辑的单片源文件。对于其他语言生态***,这些捆绑工具是不可用的。
包管理通常依赖于版本控制。像NPM或Pip这样的包管理器能够处理包版本。NPM通过经由不同的目录来组织不同的包版本并向包名称附加版本号来处理版本控制。在Python中使用不同的方法。诸如Pip之类的工具可用于构造和管理部署,使得只安装一个包版本。然而,这些方法不容易转移到关系数据库。通常,数据库***不支持不同的对象版本。
不同的项目可能以不同的对象版本和不同的语言设定或选项运行,这可能导致库干扰或故障。数据库***拥有通常在编程语言生态***中碰不到的不同特性,比如:
·模式:数据库对象总是以特定的模式创建的。如果对象是在没有具体指定模式的情况下创建的,则它是以当前用户账户的模式创建的。当对象名称和模式二者被指定时,数据库对象是完全限定的。如果对象在SQL查询中不是完全限定的,则查询优化器将需要对其进行解析。从而,如果由不同的用户账户执行,缺乏完全限定对象引用的相同查询可能会导致不同的结果,比如当存在共享相同名称但位于不同模式中的对象的不同版本时。这可能会带来技术挑战,比如源代码应部署在哪里,以及一旦部署,如何共享源代码。
·权限:数据库***实现丰富的权限模型。与典型的文件***权限模型相比,权限模型的粒度要细得多。在全***、***模式、用户模式和单个数据库对象级别存在读取、创建、执行、删除和修改权限。除了将源代码存储到哪里的问题之外,还存在是否和如何保护对源代码的访问,以及源代码可以行使哪些权限的问题。
附图说明
附图中:
图1是描述用于处理数据定义语言(DDL)语句的示例计算机***的框图,DDL语句将新的访客编程语言的实现上传到数据库管理***(DBMS)中;
图2是描述用于执行将新的访客编程语言的实现上传到DBMS中的DDL语句的示例计算机处理的流程图;
图3是描述用于在DBMS中添加和使用新的访客编程语言的示例计算机处理的流程图;
图4是描述用于处理单个DDL语句的示例DBMS的框图,所述单个DDL语句对于访客编程语言导致生成包含多个访客子例程的访客模块;
图5是描述使DBMS对于访客编程语言生成包含多个访客子例程的访客模块的示例单个DDL语句的流程图;
图6是描述访客模块和访客子例程的一些示例生命周期活动的流程图;
图7是描述用于处理通过访客编程语言导入依赖项的请求的示例DBMS的框图,这使DBMS基于映射提供访客模块;
图8是描述处理通过访客编程语言导入依赖项的请求的流程图,这使DBMS基于映射提供访客模块;
图9是描述在诸如数据库会话、数据操纵语言(DML)语句和访客模块之类的数据库组件的边界的一些示例活动的流程图;
图10是描述用于满足依赖项的一些示例活动的流程图;
图11是描述具有多语言引擎(MLE)的示例DBMS的框图,所述多语言引擎便利不同访客编程语言之间的协作;
图12是描述用于从不同的访客编程语言以访客编程语言访问访客对象的一些示例活动的流程图;
图13是描述具有访客虚拟环境的示例DBMS的框图,所述访客虚拟环境向不同的访客模块提供命名相同的依赖项的备选绑定;
图14是描述用于生成、修改和使用访客虚拟环境的一些示例活动的流程图,所述访客虚拟环境符号化地将访客依赖项绑定到访客模块;
图15是描述用于比如在多租户环境中,比如具有协作或孤立(即,不协作)的多个数据库应用,比如在企业的私有云中,在多个数据库用户和多个访客编程语言之间共享访客虚拟环境的一些示例活动的流程图;
图16是描述从虚拟文件***透明地检索资源以泛化备选存储机构的示例DBMS的框图;
图17是描述DBMS从诸如虚拟文件***之类的虚拟化存储装置中检索资源的一些示例活动的流程图;
图18是图解说明可在其上实现本发明的实施例的计算机***的框图;
图19是图解说明可用于控制计算***的操作的基本软件***的框图。
具体实施方式
在下面的说明中,为了便于说明,陈述了众多的具体细节,以便透彻地理解本发明。然而,显然可在没有这些具体细节的情况下实践本发明。在其他情况下,以框图形式表示公知的结构和设备,以避免不必要地模糊本发明。
总体概述
本文中的方法便于比如从数据操纵语言(DML),访问以诸如JavaScript和Python之类的现代编程语言编写的(例如,自定义)访客对象,比如存储的过程和用户定义函数。在实施例中,所有编程语言源代码由称为GraalVM的同一高性能引擎执行。例如,访客编程语言可以具有基于Truffle框架的实现。GraalVM在数据库管理***(DBMS)的地址空间中执行这些访客编程语言,以使效率和性能最大化,但是运行被沙箱化的源代码,使得未经授权的存储器访问或***调用变得不可能。
将访客源代码部署到数据库中是通过称为访客模块的用户定义包进行的。每个访客模块与单一访客编程语言关联,并且访客模块的内容和结构特定于该访客编程语言。诸如访客模块中的逻辑之类的访客对象可以以各种方式访问,例如:
·通过调用规范可以从诸如PL/SQL之类的DML调用由访客模块定义的子例程。
·访客模块可以由同一访客编程语言的其他访客模块使用特定于语言的导入机制来导入。
·访客模块可以由相同或不同访客编程语言的其他访客模块使用应用编程接口(API)来导入,所述API由DBMS的多语言引擎(MLE)实现,这便于导入模块中的子例程直接从导入模块被调用。
本文中是用于基于访客模块执行访客子例程的示例MLE体系结构。MLE可以用除PL/SQL以外的编程语言,比如诸如JavaScript、Ruby、Python和/或R之类的动态语言执行存储的过程或用户定义函数(UDF)。MLE不限于动态语言的执行,因为它还可以运行诸如Java之类的或多或少的静态语言。
MLE可以包含几层。顶层可以实现访客编程语言。在MLE上运行的各个访客编程语言实现可以基于Oracle Truffle。Truffle是构建在诸如Java VM(JVM)之类的虚拟机(VM)上运行的高性能抽象语法树(AST)解释器的语言实现框架。Truffle AST中的各个节点具有执行方法,其中它执行其子节点并返回它自己的结果,例如用于部分评估。Truffle AST解释器的主要优点在于它通过使用简档分析信息和部分评估实现自优化。
这些简档是在访客语言程序的执行期间收集的。重要的优化可以包括类型专门化、重写间接函数调用、多态内联高速缓存、分支消除和推测函数内联,如本文中所讨论的。如果推测假设被证明是错误的,则可以将专用AST恢复到为更一般的情况提供功能的更通用版本。
当Truffle节点的执行计数达到预定义阈值时,Truffle通过对Graal的调用触发部分评估。Graal是构成又一个MLE层的动态编译器。Graal可以是MLE的即时编译器(JIT),它能够进行AST的各个部分的部分评估,这可能需要本文中所讨论的Futamura投影。Graal的输出可以是具有去优化点的高度优化的机器代码。这些点可被实现为在推测假设不再成立的情况下必须触发去优化的检查点。去优化意味着控制从编译的代码被转移回AST解释器,然后在AST解释器中将专用AST节点恢复为更通用的版本。
MLE的另一层是VM。例如,MLE可以使用Oracle的Substrate VM(SVM),它是提供诸如代码高速缓存或垃圾收集之类的服务的可嵌入VM。MLE可以对MLE包含的所有语言实现使用相同的VM。
一个目标可以是在不需要代码改变的情况下提供未来的可扩展性。MLE可以比如为通用语言、传统语言和/或领域专用语言(DSL)提供可插拔的售后语言方法。例如,已在Truffle框架之上实现自己的访客编程语言的客户可以按照MLE提供的API将该语言***MLE中,这可以在既不对MLE也不对DBMS进行代码改变的情况下完成。MLE提供部署和管理诸如包和模块之类的代码库单元的统一方式。
访客模块是部署到数据库中的(例如源)逻辑的单元。每个访客模块用单一的相应访客编程语言实现。访客模块的内容和结构可以特定于该访客编程语言。本文中是一种新的数据定义语言(DDL)语句,用于将源逻辑作为访客模块部署到数据库。
本文中是让所有访客编程语言共享用于诸如存储和查找之类的活动的相同基础设施的MLE扩展,比如访客模块和访客虚拟环境。另外,数据库权限可以用于控制对此类组件的访问。MLE还可以包含虚拟文件***,通过该虚拟文件***,诸如访客脚本之类的源逻辑可以分布在嵌套目录结构中的几个文件上,所述几个文件可以捆绑在一起并以诸如zip文件之类的容器格式存储。这样的源包可以作为二进制大对象(BLOB)或文件来提供,并且比如通过DDL语句提供给MLE。
MLE提供用于语言模块内和语言模块间导入的体系结构。访客虚拟环境可以提供模块名称和保持模块内容的模式对象之间的映射。该机制可以隐藏不同访客编程语言的模块/包导入规范的差异。导入其他访客模块的能力提供了几个好处:
·将源逻辑分离成几个独立模块的能力。
·源逻辑的可重用性。通过将代码分解成模块,可以重用某些模块。库可以作为分开的访客模块来提供,并从属于不同项目的其他访客模块导入。从而,每个访客模块可以具有或多或少独立的维护计划表,比如按照软件开发生命周期(SDLC)。
·易于修补。如果没有模块间导入,则尽管只需要改变底层源代码的一小部分,也将需要重新部署单片(即,大的)访客模块。通过将代码划分为较小的访客模块,只需要重新部署模块的子集。MLE还可以提供诸如结构化查询语言(SQL)驱动程序之类的内置模块。
用于访客编程语言的导入机制可以具有用于在加载模块时咨询环境的逻辑。例如,对于JavaScript,通过require语句导入模块,MLE可以截取并特别处理require语句,包括通过环境解析依赖项模块名称。类似的技术被扩展到诸如Python之类的其他访客编程语言。
用于访客模块和访客虚拟环境的语言无关机制为数据库内的源逻辑管理提供统一的API。这为能够适应编程语言生态***的特定需求的工具化部署留下了很大的自由。例如,版本解析可以或多或少留给客户端侧工具,并且所解析的版本使用数据库内的访客虚拟环境来映射。
在实施例中,计算机将访客编程语言的实现***DBMS的部署中。执行DDL语句以在DBMS中注册访客编程语言。通过执行DML语句在DBMS中调用访客编程语言。
在实施例中,执行单个DDL语句,以为DBMS中的访客编程语言定义多个子例程。第二DDL语句将特定子例程作为用户定义函数(UDF)或存储的过程注册在DBMS中,DML语句可以调用该子例程。
在实施例中,DML语句调用访客编程语言从而导致:执行原生于访客编程语言的导入请求以访问依赖项,并且基于原生于访客编程语言的导入请求和在DBMS中定义的映射来解析依赖项。如本文中后面所述,在DBMS中定义对象可能需要将对象的数据和/或元数据存储到DBMS中的或者DBMS的数据库中的数据库模式和/或数据库字典中,其中元数据定义对象的性质、特性或配置。
实施例在DBMS中定义用第一访客编程语言实现的访客对象。DBMS包括:原生数据操纵语言(DML)、第一访客编程语言和第二访客编程语言。从原生DML调用第二访客编程语言,导致执行来自第二访客编程语言的访问请求以访问用第一访客编程语言实现的访客对象。
在实施例中,第一DDL语句在DBMS中生成访客虚拟环境。第二DDL语句向访客虚拟环境添加依赖项与访客模块的绑定。访客编程语言发出访问该依赖项的请求。基于该请求和绑定,访问访客模块。
在实施例中,DML语句调用访客编程语言,从而导致:
·执行原生于访客编程语言的请求以访问依赖项,和
·从具有多个备选实现机制的虚拟文件***检索该依赖项,所述多个备选实现机制包括:基于归档文件或实际文件***的第一实现机制,以及基于存储缓冲器或数据库表格的列的第二实现机制。
1.0示例计算机***
图1是描述实施例中的示例计算机***100的框图。数据定义语言(DDL)语句181将新的访客编程语言的实现上传到数据库管理***(DBMS)110中。计算机***100包含一个或多个计算机,比如190,每个计算机可以是诸如刀片服务器之类的机架服务器、个人计算机、大型机、虚拟计算机或其他计算设备。当计算机***100包含多个计算机时,这些计算机通过通信网络互连。
计算机***100包含DBMS 110,DBMS 110可以由计算机190托管,由不同的计算机(未图示)托管,或者对于分布式和/或多实例数据库,由多个计算机托管。DBMS 110支持多语言(即,多语种)可编程数据库,比如具有多语言引擎(MLE)软件层的数据库,多语言引擎(MLE)软件层可以为多种访客编程语言单独地或者如在Oracle的Graal MLE中一样组合地嵌入相应的解释器和/或虚拟机,比如Java虚拟机(JVM)、JavaScript解释器。例如,MLE可以解释文本脚本,生成字节代码,解释字节代码,和/或将字节代码编译为原生机器指令,例如通过即时(JIT)编译。例如,MLE可以包含执行从多种访客编程语言的源逻辑生成的字节代码的JVM。
通过添加诸如140之类非原生于DBMS 110的访客编程语言,DBMS110是可扩展的。访客编程语言140可以在售后添加以便在DBMS 110中使用,比如通用编程(例如脚本)语言或领域专用语言(DSL)。例如,访客编程语言140不需要最初和DBMS 110一起提供,也不需要从DBMS110的原始设备制造商(OEM)(例如,独立软件供应商ISV)获得。
访客编程语言140的添加是通过数据定义语言(DDL)语句181进行的。例如,DDL可以是原生于DBMS 110的专有语言或数据库语言的管理方言,比如结构化查询语言(SQL)。DDL通常将元数据写入DBMS 110中,比如写入DBMS 110的数据库中的数据库模式和/或数据库字典内,如本文中后面所述。诸如SQL之类的原生数据库语言最初被内置到DBMS 110中,从而不需要像对于访客编程语言140所需那样分开地添加到DBMS 110中。在实施例中,DDL语句181可以是“CREATE MLE LANGUAGE MYLANGUAGE;”,其中MYLANGUAGE是标识访客编程语言140的名称。
DBMS 110可以从客户端,比如特设(ad hoc)数据库工具或其他软件应用接收DDL语句181,比如通过开放式数据库互连(ODBC)连接用文本来接收,这可能需要进程间通信或联网,比如当计算机190是远程客户端时。在另一种情形下,DDL语句181由DBMS 110内部生成。DDL语句181的执行或多或少完全地将访客编程语言140添加到DBMS110中。
例如,访客编程语言140可以基于诸如150之类的实现文件,比如类文件和/或资源文件,它们可以是松散的文件和/或捆绑到诸如Java归档(JAR)文件之类的归档文件中。在实施例中,实现文件150可以包含:a)正式地定义访客编程语言140的句法的语法162,比如用于标记(tokenize)和/或解析,和/或b)解析器161,也用于解析,比如基于语法162,比如用于构造解析树(未图示)。在实施例中,不同的访客编程语言可以各自具有自己的相应语法,比如162,但是共享同一解析器161。其他(例如,可共享的)语言组件可包括语义分析器、优化器、(例如,中间或机器)代码生成器,和/或定位交叉引用资源的链接器或加载器。例如,Graal提供了许多这样的组件,它们可以被共享和/或定制,比如协作的编译器/解释器层,比如作为前端的Truffle和作为后端的Substrate。
在实施例中,比如在提交DDL语句181之前,比如由数据库管理员(DBA)、***管理员、或其他能够访问托管DBMS 110的计算机的命令shell和/或文件***的用户,(例如,手动)使访客编程语言140的实现文件置放(stage)(即,放置)到DBMS 110的代码库或其他文件***中。在另一个实施例中,DDL语句181的执行自动使实现文件置放到DBMS110中,这可能需要在同一文件***内复制实现文件,在多个文件***之间复制实现文件,文件的(例如符号)链接,或者从远程客户端上传实现文件。例如,远程客户端可以使用包括超文本传输协议(HTTP)或Java远程方法协议(JRMP)的Java ODBC(JDBC)驱动程序,比如通过HTTP post将文件从远程客户端上传到DBMS 110的子***,比如公共网关接口(CGI)。例如,DDL语句181可以包括JAR文件的统一资源定位符(URL),该JAR文件包含访客编程语言140的可嵌入实现(例如,解释器)。
DDL语句181的执行使访客编程语言140(例如,公开地)在作为DBMS 110的一部分的数据库字典120或其他元数据存储库内注册。数据库字典120包括定义DBMS 110的数据库对象和其他配置方面的元数据。数据库字典120可以包括存储数据库元数据的多个数据结构。例如,数据库字典120可以包括多个文件和表格。数据结构的各个部分可以被高速缓存在DBMS 110的数据库服务器的主存储器中。
定义DBMS 110的特定数据库对象或DBMS 110的配置的特定方面的元数据的子集在本文中被称为元数据定义或简称为定义。定义还可以包括多个数据结构和表格。特定数据库对象的定义可以包括组成数据对象的定义。例如,表格的定义可以包括表格的各列的多个定义。
定义过程的数据库字典120中的元数据可以指定过程的名称、过程的自变量、返回数据类型和自变量的数据类型,并且可以包括源代码及其编译版本。数据库对象可以由数据库字典120定义,不过数据库字典120中的元数据本身只能部分指定数据库对象的性质。其他性质可以由不被视为数据库字典120的一部分的数据结构定义。例如,如本文中后面所述,在Java类中实现的用户定义函数(UDF)可以通过指定用户的Java函数的名称和通过指定对包含该Java类的源代码的文件(即,.java文件)和包含类的编译版本(即,字节代码)的文件(即,.class文件)的引用,由数据库字典120部分定义。
绑定可以是直接与数据库字典120中的其他对象(比如名称)关联的定义。例如,数据库字典120可以包含键值对,比如在查找表或散列表中。例如,数据库字典120可以是数据库命名空间的实现,和/或可以包含诸如关系模式之类的数据库对象。DDL语句可用于将定义和/或绑定写入数据库字典120或数据库模式中。
数据字典120中的条目可以通过诸如名称130之类的检索关键字访问。对象(即,值)可以直接或者通过引用间接存储在数据库字典120的内容存储器中,所述引用比如是寻址数据库字典120之外存储该对象的存储单元的指针。因而,在数据库字典120内显示的组件,比如访客编程语言140,实际上可能驻留在DBMS 110的存储器中的其他地方,并由数据库字典120的相应条目(例如键-值对)引用。
名称130可以是如上所述出现在DDL语句181中的相同语言名称,比如MYLANGUAGE。例如,DDL语句181可以立即使访客编程语言140在DBMS 110的存储器中生成,比如通过执行来自访客编程语言140的已置放的实现文件中的初始化逻辑。在实施例中,对于访客编程语言140的存储器初始化可以惰性发生,例如依据以后的需求,比如在以后使用名称130来访问访客编程语言140时。不管访客编程语言140的初始化是惰性的(lazy)还是贪婪的(eager),名称130都立即通过DDL语句181绑定到数据库字典120中的访客编程语言140。
之后,DBMS 110可以接收或生成使逻辑在访客编程语言140内执行的数据操纵语言(DML)语句182,比如数据库查询。例如,DML可以是原生于DBMS 110的专有语言或数据库语言的数据访问方言,比如SQL。DML被设计成在DBMS 110的数据库中创建、读取(例如查询)、更新和删除(CRUD)普通数据。然而,DDL是为写入(即,创建、更新和删除)而设计的,但是用于元数据(即,定义)而不是数据库数据。示例查询(QBE)(例如JavaScript对象表示法,JSON)和路径表达式(例如XPath)可以是DML的全部或部分示例。
DML语句182可以包含在DBMS 110中定义的数据库对象的文本引用(例如,名称)。DBMS 110可以使用数据库字典120或数据库模式将这些名称解析为实际的数据库对象,比如用户定义函数(UDF)。一些数据库对象可以仅通过SQL语句的执行来生成(即定义)。其他数据库对象可以代替用访客编程语言140生成。从而,一些数据库对象也是访客对象。
如本文中后面所述,并且在一些情况下,通过绑定,比如数据库字典中的绑定的促进,访客对象可以绑定到不是访客对象的数据库对象。例如,DML语句182可以明确地调用作为数据库对象的存储的过程或UDF,该数据库对象尽管不是访客对象,但实际上被实现为(即,绑定到)访客对象,比如访客编程语言140中的子例程170。
例如,子例程170可以是单独的Python函数,或Python的整个命令式脚本,它被展示为DML语句182明确调用的存储的过程或UDF。在未示出的实施例中,数据库字典120包含供检查的,比如由DBMS 110的查询规划器检查的该存储的过程或UDF的声明或定义。用于操作原生DML语句182和访客子例程170之间的语言边界的机制和技术在下文中讨论。
如上所述,访客编程语言140可以用专用于特定的(例如,编译)活动(比如优化)的组件和/或层(比如Truffle和Substrate)在DBMS 110中实现。从而,可以按照各种统计和/或增量技术来加速访客子例程170的执行,比如:a)Futamura投影,b)仅仅一部分的子例程170的及时编译(JIT),和/或c)生成具有一个或多个去优化点的推测代码。按照推断(例如观察到)的多态变量的数据类型静态或动态地(例如简档分析)优化推测逻辑。
去优化点划分所生成代码的由于意外的数据类型而变得无效并且应当立即用较少优化(例如较早)的代码替换的片段。部分JIT可以比如通过循环展开,变换子例程170的热(即,重复次数超过阈值)片段,比如紧凑循环。如本文中后面所述,Futamura投影是体系结构变换,它可以包括部分评估(即,逻辑专门化)、记忆化(即,通常具有包含函数的名称或指针及其实际自变量值的复合键的函数结果高速缓存)和/或强度降低(即,语义重构;例如,a)具有循环不变量和/或归纳变量的热点,或b)算术运算替换)。
Substrate可以应用诸如提前(AOT)代码生成之类的Futamura投影。例如,DDL语句181可能对于一些或所有的子例程170,贪婪地(例如,立即地)导致在后台(例如低优先级)的AOT代码生成,即使子例程170直到很久以后才可能首次被(例如DML语句182)调用。从而,预计脚本的复杂难懂的解释的工程师可以改为获得用于直接执行的机器语言,该机器语言对于特定中央处理单元(CPU)模型的特定版本是高度优化的,比如在应用开发期间未知或不可用的生产环境中。
2.0示例语言部署处理
图2是描述在实施例中,计算机***100将新的访客编程语言140添加到DMBS 110中的流程图。参考图1讨论图2。
取决于实施例,步骤202和204可以合并成或不合并成一个步骤。在实施例中,步骤202可以完全由DBMS 110本身实现、部分由DBMS110本身实现或根本不由DBMS 110本身实现。例如,执行步骤202所需的自动化可以在计算机***100中的其他地方实现,并且可以需要或不需要诸如数据库管理员(DBA)之类的***管理员的手工劳动。
步骤202将访客编程语言140的实现***DBMS 110的部署中。例如,DBMS 110可以具有库路径,比如文件***文件夹路径的有序列表,所述库路径识别DBMS 110可以从哪里找到(例如,售后)对它自己的代码库的扩展,比如访客编程语言140的实现的代码库,该代码库可以由松散的文件或打包的文件组成。自动化或管理员可以将访客编程语言140的代码库文件置放到DBMS 110的库路径中(即,复制到位置中)。取决于DBMS 110的实现,DBMS110可能需要也可能不需要重新启动,以使DBMS 110准备好加载(例如,动态链接)已置放的访客编程语言140的代码库。
在步骤204,执行DDL语句181,以在DBMS 110中注册访客编程语言140。例如,数据库客户端脚本或特设客户端可以(例如经由ODBC)将DDL语句181从计算机190发送到可以在相同或不同的计算机上的DBMS 110。取决于实施例,DDL语句181可以识别以下中的任何一个:a)访客编程语言140的名称130,比如用作要***数据库字典120中的命名键,和/或b)访客编程语言140的实现的代码库路径和/或类名称。
DDL语句181的执行使DBMS 110的多语言引擎(MLE)实例化实现访客编程语言140的存储器数据结构,这可能需要来自访客编程语言140的已置放的代码库的类加载或脚本执行。在实施例中,DDL语句181也可以执行步骤202(即与步骤204结合)。
例如,DDL语句181可以包括定位还不需要置放到DBMS 110中的访客编程语言140的实现的统一资源定位符(URL)或交叉安装路径。置放可以基于如下的推送或拉取机制自动发生,这种机制适合于对于公共云的部署,公共云可能拒绝客户端对DBMS 110的文件***的直接访问,比如通过远程shell。
在拉取实施例中,DBMS 110可以处理URL以自动上传并将访客编程语言140的代码库置放到DBMS 110的部署中。该实施例可能需要在URL所指向的主机上运行的web服务器或文件服务器,该主机可以是也可以不是计算机190。
在推送实施例中,客户端(例如,ODBC)驱动程序具有将代码库文件上传到DBMS110中的附加逻辑。取决于实施例,该上传可以通过驱动程序的数据库连接被多路复用,并且DBMS 110可以将上传保存到它自己的代码库中,或者驱动程序可以使用分开的网络连接,比如用于到web服务器的公共网关接口(CGI)POST,该web服务器可以将上传保存到DBMS110的代码数据库中。例如,DBMS 110可以包括web服务器(未图示)。
在步骤204之后,访客编程语言140就准备好可以在DBMS 110中使用了。步骤206执行在DBMS 110中调用访客编程语言140的DML语句182。例如,如本文中后面所述,DBA可以导出访客编程语言140的子例程作为DML语句182可以调用的UDF。从而,访客编程语言140可间接地用于DML查询,而不使客户端暴露于访客编程语言140。例如,传统查询可以调用复杂的UDF,该UDF最初被实现为次优的DML,并且最终被访客编程语言140透明地改造(例如重新实现和加速)。
3.0示例语言管理
图3是描述在实施例中,计算机***100在DMBS 110中添加并使用新的访客编程语言140的流程图。参考图1讨论图3。
步骤301-302便于如下将访客编程语言140部署到公共云(未图示)中。如上所述,DBMS 110包含一个或多个服务器计算机,服务器计算机可以包括也可以不包括客户端计算机190。例如,客户端计算机190可以与DBMS 110分开,并且托管起DBMS 110的远程客户端作用的客户端软件,比如利用ODBC。例如,访客计算机190可以与托管DBMS 110的公共云分开。从而在步骤301中,DBMS 110从客户端计算机190远程接收DDL语句181。
步骤302上传访客编程语言的代码库文件150,这可以在DDL语句181的处理期间自动发生。本文中前面讨论了用于推送或拉取上传文件150的各种技术。
步骤303-304需要被记录在数据库字典120中的访客编程语言140的配置元数据(未图示)。步骤303将访客编程语言140的名称130绑定到访客编程语言140的(例如部分)已链接/已加载的实现。例如,这样的实现可以基于代码库文件150。链接、加载和数据库字典120内的注册在本文中的其他地方讨论。
步骤304使用数据库字典120中的配置元数据来调用访客子例程170。如本文中后面所述,这样的元数据可以是调用规范,该调用规范将用于从DML语句182调用的子例程170包装为存储的过程或UDF。另外如本文中后面所述,另一个DDL语句(未图示)可以生成这样的元数据。
步骤304可以导致动态地(重新)优化逻辑的步骤305-307中的一个、一些或全部步骤。如本文中前面所述,访客编程语言140可以是解释(例如脚本编写)语言,比如Python、R、JavaScript、Ruby、Pig或(例如Java)中间字节代码,所有这些通常都需要解释器来执行。例如,代码库文件150可以实现该解释器。在诸如具有Truffle的实施例中,该解释器本身经历动态分析,比如部分评估和其他解释、专门化和其他(例如推测)优化、以及JIT编译。
从而,对于特定的访客子例程170和/或调用访客子例程170的特定的DML查询182,解释器本身可以向最优方向突变/演化。这种适合特定访客逻辑的解释器细化被称为Futamura投影,其中沿着强度谱存在几个递进程度(即,投影),从在强度谱的一端,优化解释器,到将优化后的解释器重塑为编译器,或者在强度谱的另一端,优化编译器。步骤305至少进行第一程度的Futamura投影(即,解释器优化)。Futamura投影效率可以取决于访客子例程140的大量重复调用来摊销优化开销(例如,初始时延)。例如,在执行同一DML查询182期间,可以为数据库表格的数千或数百万行中的每一行调用访客子例程140。
步骤306部分评估访客子例程170。例如,DBMS 110可以优化访客子例程170的AST的全部或部分(例如,子树)。例如,访客子例程170内的紧凑循环可以被隔离,以单独进行语义优化,而访客子例程170的其余部分在不进行优化的情况下进行持续的解释。同样地,可以对AST的全部或部分应用JIT编译。
步骤307基于诸如数据类型推断之类或多或少脆弱的假设,比如基于访客子例程170的动态简档分析,生成表示访客子例程170的一些或全部的推测逻辑。推测逻辑可以包括动态验证此类假设的保护(guard)。例如,保护可以检测到失败的(即,违反的)假设,并通过在去优化点恢复逻辑来作出反应,包括退回到不需要此类假设的非优化逻辑,比如先前使用并仍被高速缓存的逻辑。
4.0访客模块
图4是描述实施例中的示例DBMS 400的框图。对于访客编程语言420,单个DDL语句441使DBMS 400生成包含多个访客子例程471-472的访客模块461。DBMS 400可以是DBMS110的实现。
诸如461-463之类的语言模块是定义诸如子例程471-472之类的对象的管理和/或词法(即,范围/可见性)单元,子例程471-472原生于访客编程语言420,并且可以从访客模块461外部(例如,公开地)访问。取决于实施例,访客模块461可以包含其他对象,这些对象是:a)也是可公共访问的,但不是子例程的对象,比如全局变量,比如数据结构,b)只能从访客模块461内访问的对象,或者c)只能在访客编程语言420内访问的对象。
在实施例中,DDL语句441可以是“CREATE MLE MODULE scott.'jsmodule'LANGUAGE JAVASCRIPT AS module.exports.func=function(){...};”,细节如下。JAVASCRIPT是为其创建访客模块461的访客编程语言420的名称452。访客模块461的名称是jsmodule,如名称451所示。
当被创建时,在数据库模式(未图示)内注册访客模块461。如果名称451在DDL语句441中没有限定,则在默认(例如,当前、全局和/或***)模式内注册访客模块461。如果名称具有限定符,比如scott,则改为在命名为scott的现有模式内注册访客模块461。例如,数据库字典410可以用于诸如scott或默认之类的模式,并且数据库字典410可以包含名称451-455作为检索关键字。由于模式充当命名空间,因此不同模式中的模块可能具有相同的非限定名称,但是具有不同的限定符。
如在上面的示例DDL语句441中出现的一样,新的模块导出(即,公开)命名为“func”的单个对象,在这种情况下,恰好是:a)匿名(即,没有访客原生名称)的JavaScript对象,b)函数,和c)定义的内联函数(即,像JavaScript一样直接在DDL语句441中)。导出子句可以导出多个对象,比如“AS module.exports.A=function(){}module.exports.B=function(){}”,其中空格作为分隔符。
上面的示例DDL语句441是模块创建语句的冗余(即,自包含)的形式,因为导出的对象是定义的内联函数。模块创建语句可以具有改为通过引用来定义导出的对象的其他形式。下面是模块创建语句的示例语法。
在上述语法中,USING子句是AS内联子句的替代。BFILE项可指定文件路径或资源URL,比如JAR URL,比如用于访客语言材料,所述访客语言材料是:可远程获得的、捆绑在归档文件中、和/或动态(例如HTTP CGI)内容。二进制大对象(BLOB)或字符(即,文本)大对象(CLOB)项可指定从关系表或结果集的单行的单列来检索内容的DML(例如,SQL)选择子句。例如,DBMS 400可以是关系DBMS(RDBMS),RDBMS在数据库中维护在同一列的每行中存储相应JavaScript对象的表格。
取决于实施例,VERSION项可用于兼容性检查和/或用于公开具有相同名称451的同一模块的多个版本。ENV项指定语言编程环境,如本文中后面所述。
在实施例中,在DDL语句441用访客编程语言420创建访客模块461之后,则访客子例程471-472立即可以在一些但不是全部上下文中加以应用,如下所示。此时,对于新创建的访客模块461,在DBMS 400的重要组件,比如包括410在内的数据库字典,诸如DML解析和查询规划之类的关系代数机制,以及除420以外的访客编程语言中,可能仍然没有声明访客子例程471-472。取决于实施例,访客子例程471-472此时可能完全不可用,或者仅在访客编程语言420、访客模块461和/或当前的访客虚拟环境(ENV)的特定组合(例如,所有组合)下可见以供使用,如本文中后面所述。
从而,在创建访客模块461之后,公开访客子例程471-472需要创建相应的调用规范,比如480。调用规范480是在数据库字典410中定义为供诸如DML和/或(例如,不同的)访客编程语言之类的其他语言使用的语言间绑定的元数据。调用规范480可以用于:a)解析子例程472的(例如,DML)调用,包括签名重载,b)转换访客子例程472的输入和/或输出的数据类型,c)起访客子例程472的占位符或代理作用,例如在计划或解析的查询树中,和/或d)实际调用(即,将控制流转移到)访客子例程472。从而,调用规范480有时可以起访客子例程472的被动描述的作用,而在其他时间起访客子例程472和其调用者之间的主动中介(即,胶连逻辑)的作用。
DDL语句442创建调用规范480。在实施例中,DDL语句442可以是“CREATE ORREPLACE FUNCTION function472 RETURN VARCHAR2 AS MLE MODULE jsmoduleSIGNATURE'subroutine472(str1 string,str2 string)';”,细节如下。访客模块461的名称是jsmodule,如名称451所示。访客子例程472的名称是subroutine472。访客子例程472被公开(例如,比如考虑到冲突或考虑到向后兼容性而被重命名)为function472。访客子例程472具有接受两个字符串参数(即,原生于访客编程语言420的字符串类型)并返回字符串(即,原生于DML语言的字符串类型)的签名。DDL语句442的执行使得调用规范480的可见性和访客子例程472的可调用性在访客模块461可用的任何地方(比如DML和除420以外的访客编程语言)变得可用。
诸如461-463之类的访客模块是可组合的,并且可以相互依赖,如下所示。例如,访客模块462可以公开(即,导出)访客模块461使用的对象。例如,访客模块461中的访客子例程471可以导入(和例如,调用)由访客模块462提供的访客子例程(未图示)。
本文中的技术寻求灵活性和重用性,而不管诸如向后兼容性和隔离(比如用于多租户和/或库版本控制)之类的复杂性。从而,相互依赖的访客模块461-463只是松散地(即,符号化地)与名称453-455耦接,如下所示。每个访客模块可以重命名依赖项(即,被导入(即,交叉引用)的其他访客模块)(即,为所述依赖项其定义它自己的名称)。
例如,访客模块462在访客模块461内被称为名称453,该名称不必是访客模块462的原始名称。例如,可以用Python脚本定义访客子例程471,它具有列举(即,交叉引用)被绑定到访客模块462的名称453的导入语句。然而,诸如463之类的不同访客模块可以通过不同的名称来导入同一访客模块462,或者可以具有绑定到相同名称453的不同访客模块。
从而,名称453起别名的作用。在实施例中,别名可以级联。例如,在访客模块461内,名称454-455是同义的,因为名称455被绑定到名称454。例如,Python脚本可以使用名称454或455来指代访客模块463。
访客编程语言420可以改为是Java,它可以具有类而不是脚本。本文中针对脚本执行讨论的活动可以改为在类加载和/或类执行期间发生。在实施例中,每个Java访客模块被实现为原生Java模块,比如Java-9模块、OpenJDK Jigsaw模块、或开放服务网关规范(OSGi)模块。每个Java模块具有它自己的交叉引用其他模块作为依赖项的描述符类。除了OSGi以外,加载许多相互依赖的Java模块中的一个Java模块导致交叉引用的描述符类的传递闭包的贪婪加载。从Java模块加载其他实现(例如,帮助)类可依赖于自然的类加载语义,这基本上或完全是惰性的。
不论实现的原生模块加载有多惰性,DBMS 400的实施例可以强行实施也可以不强行实施访客模块的贪婪解析,即使访客模块加载或多或少是惰性的。模块解析需要将依赖项名称(即,别名)映射到实际的模块实现。例如,具有惰性模块解析的实施例可以通过以任何顺序发出DDL创建语句,以任何顺序创建模块。然而,贪婪模块解析可能要求依赖项模块在使用这些依赖项的其他模块之前被创建,使得循环依赖项被禁止。例如,对于贪婪模块解析,如果一个模块的依赖项名称中的任何一个不能立即解析到其他已经解析的模块,则创建该模块的DDL语句将失败。然而,惰性模块解析可以推迟解析(例如,如果不能解析的话),直到实际使用该依赖项为止。在任一情况下,模块解析是否包括模块加载(例如脚本执行)取决于实施例。
如上所述,模块461-463在数据库模式(未图示)内定义,这自然提供可能重要的隔离,如下所示。访客对象的寿命和可见性可能背离现有访客语言概念的状态,如下所示。例如,DBMS 400可以是多用户、多角色、多租户和访问受控的(例如,DDL授权语句)。在诸如web浏览器之类的传统JavaScript环境中不存在这些复杂性。然而,数据库模式通过强行实施各种粒度的可见性,提供了实质性的隔离。
例如,每个数据库应用或应用子***可以具有定义它自己的用户、他们的角色和他们的权限的自己的数据库模式。由于应用通常不共享模式,因此这些应用程序也不应如下共享模块。多个应用可以共享模块的同一代码库(例如,脚本、库),并且这些应用可以给予该模块相同的别名。然而,由于这些应用具有分开的模式,因此该模块的分开实例(即,副本)应在运行时加载到DBMS 400的RAM中。例如,访客模块461可以是同一模块部署的许多定义实例中的一个。DBMS 400将同一模块部署的每个实例视为分开(即,独立)的模块。
同一模块部署的每个实例是分开初始化的,这可能需要同一代码库的重复执行。例如,模块创建DDL语句441在一个数据库模式中只创建一个模块实例。如下将模块实例与其代码库区分开。诸如脚本或库之类的模块的代码库(未图示)可以是部署到DBMS 400中的单元。例如,通过重复执行模块的脚本可以创建同一模块的多个实例。
例如,另一个或多或少类似的DDL语句(未图示)可以创建同一通用模块的另一个模块实例,但是在不同的模式中。两个DDL语句都可以导致同一模块代码库的重复执行。例如,两个DDL语句都可以指定同一Python脚本或同一Java归档文件(JAR)作为模块代码库,这会使该脚本运行两次,或者会使该JAR被两个单独的类加载器实例加载两次。从而,创建的两个模块实例可具有Python的名义上相同的全局变量或Java的相同静态字段的分开(即,独立)副本。
5.0示例模块创建处理
图5是描述单个DDL语句441使DBMS 400为访客编程语言420生成包含多个访客子例程471-472的访客模块461的流程图。参考图4讨论图5。
在所示实施例中,在数据库字典410中准备新的访客子例程472发生在步骤502和504中,这些步骤中的每一个都执行相应的DDL语句441-442,如下所示。步骤502执行启动多个访客子例程471-472的批量加载以在数据库字典410中定义它们的DDL语句441。DDL语句441为访客编程语言420创建新的访客模块461,并将数据库字典410中的访客模块461绑定到DDL语句441包含的名称451。
DDL语句441直接或间接地提供(例如,自定义)代码库,该代码库(文本地)定义一个或多个访客子例程471-472。例如,DDL语句441可以包含(例如,引述并且字符转义编码的)字符串,该字符串包含字面上定义内联访客子例程471-472的(例如,Python)访客脚本语句。在另一个例子中,DDL语句441通过URL或路径引用包含这些访客脚本语句的Python脚本文件。
在任一情况下,步骤502执行这些访客脚本语句,以使访客编程语言420在内部定义访客对象,比如子例程471-472。在实施例中,只有这些新的访客对象471-472的子集被直接提供给DBMS 400。例如,DDL语句441和/或访客脚本语句可以声明特定的访客对象要导出(或者在实施例中,不导出)。
导出和选择性导出在本文中的其他地方讨论。例如,DBMS 400的多语言引擎(MLE)可以具有基于访客编程语言420的相应导出实现。例如,可以以或多或少原生于访客编程语言420的方式直接支持导出,例如通过Harmony(又名ECMAScript6)。不幸的是,导出会侵入访客脚本处理语句,如在本文中的其他地方所述。类似地,如本文中所述,Java的原生模块***需要(例如手工编码的)类来实现导出。然而,其他实现可以适当地分离诸如导出和脚本处理之类的问题。例如,DBMS 400的MLE可以自动地为模块的导出、依赖项(即导入)和/或其他方面、模块边界和/或模块组成(即聚合安排)生成样板声明。
本文中的实施例可以将访客对象的导出和公布分成不同的步骤502和504。如上所述,步骤502实例化访客子例程471-472,并将它们导出到DBMS 400及其MLE。然而,在实施例中,导出并不使访客子例程471-472可用于从DML语句444调用,因为DML语句只能调用UDF和存储的过程,而不能调用任意子例程。
步骤504执行DDL语句442,以便为访客子例程472生成调用规范480,并在数据库字典410中注册调用规范480,供以后由诸如444之类的DML语句引用。本文中前面讨论了调用规范480的生成。在未示出的实施例中,没有DDL语句442,也没有步骤504,而是比如在前一步骤502期间,自动地(例如,惰性地)为访客模块461的所有导出的访客子例程生成调用规范。
步骤506执行如本文中前面所述,引用调用规范480以调用访客子例程472的DML语句444,比如在数据库查询期间。步骤506从DML语句444中提取调用点信息,它可以包括UDF或存储的过程的名称,所述名称可以用作从数据库字典410检索调用规范480的查找关键字。可以从调用点推断自变量排序和数据类型,比如用于签名重载和/或警告语义错误,比如自变量数量错误、自变量或返回值的数据类型不匹配、或OUT自变量的方向错误。在实施例中,即使当访客编程语言420原生不支持输出自变量时,比如当DBMS 400的MLE可以生成或以其他方式提供对自变量进行编组的数据结构时,调用规范480也可以具有OUT或IN/OUT自变量。
如在本文中的其他地方所述,调用规范480可以在(例如,稍微相似的)数据类型之间转换返回值或自变量值。步骤506可以通过调用规范480重复地调用访客子例程472,比如按照多个数据库表格行中的每一行和/或按照多个调用点中的每个调用点。DML语句444也可以调用其他访客子例程(比如471)的其他调用规范。
6.0示例模块生命周期活动
图6是描述访客模块461和访客子例程471-472的一些生命周期活动的流程图。参考图4讨论图6。
步骤601-605表示了在访客模块461的初始部署期间可能发生的活动。步骤606表示了访客子例程471-472的维护(例如,补丁)。步骤607表示了访客子例程472的使用。
访客模块461的初始部署可能需要执行一系列DDL语句,包括步骤601-603中通过DDL语句441的访客模块创建,步骤604中通过数据控制语言(DCL)语句443的访客模块管理,以及步骤605中通过DDL语句442的调用规范生成。在步骤601,DBMS 400接收并开始执行DDL语句441,以创建访客模块461和访客子例程471-472。由于实例化访客子例程471-472需要执行访客编程语言420,因此DDL语句441应包含访客编程语言420的名称452,步骤601可以将名称452用作数据库字典410中的查找关键字。
步骤602创建新的访客模块461,它可能需要执行访客编程语言420中的脚本或类。例如,DDL语句441可以包含内联脚本或可以引用文件中的脚本。
步骤603在数据库字典410中,将名称451绑定到新的访客模块461,比如按照在本文中的其他地方描述的数据库对象定义技术和机制。DDL脚本441指定名称451。数据库字典410及其与(例如,用户或默认)数据库模式的关联在本文中的其他地方讨论。
步骤604执行DCL语句443,以向各种用户和/或角色授予各种许可。例如,可以允许一些用户使用访客模块461,但不能修改访客模块461。另外例如,一些用户可能被禁止使用访客模块461。
步骤605执行DDL语句442,以便为访客子例程472生成调用规范480。对于调用规范480,步骤605可以生成或重用DML和访客编程语言430之间的数据类型映射,并且可以将这样的映射逻辑嵌入调用规范480中。调用规范480可以指定:自变量类型,比如用于签名的解析和/或重载,自变量方向(比如OUT),和/或(例如,用于优化和/或并行化的)幂等性、高速缓存性和/或线程安全性的指示。
许久之后,访客子例程471-472中的一个、一些或全部可以被修改。步骤606执行单个DDL语句(未图示),比如在本文中的其他地方所示的ALTER MODULE语句,以修改(即,替换)任意或所有访客子例程471-472。例如,ALTER MODULE语句可以指定修改的代码库,诸如内联或在文件中。步骤606替换访客子例程471-472,并保留已生成的任何调用规范,比如480,尽管一些或所有此类调用规范可能需要通过附加的DDL语句来重新生成,比如对于签名更改。在实施例中,在步骤606期间自动重新生成调用规范480。
步骤607在DML语句444的执行期间实际调用访客子例程472。访客子例程472可能需要增加的特权来访问资源,或者可能为了安全而受益于减少的权限,比如避免意外的或恶意的误用。如本文中后面所述,调用规范480可以声明访客子例程472是否继承调用该调用规范480的无论哪个用户账户的权限,或者访客子例程472是否应该改为继承定义了访客模块461的管理用户账户的权限。
即,调用规范480指定访客子例程472应在这两个用户账户中的哪个账户下执行。从而,如图所示,当通过调用规范480调用访客子例程472时,步骤607可以切换到模块定义者的用户账户。当访客子例程472将控制返回给执行中的DML语句444时,执行返回到调用者的用户账户,这是提交了DML语句444的用户。用户账户和访客模块边界可以与执行上下文相关,这将在本文中后面介绍。
7.0模块依赖项
图7是描述实施例中的示例DBMS 700的框图。访客编程语言710导入依赖项790的原生请求751使DBMS 700基于映射780提供访客模块721或722,如下所示。DBMS 700可以是DBMS 110的实现。
诸如导出的子例程之类的访客对象在DBMS 700的访客编程语言710中定义,比如在(例如,Python)访客脚本730中定义。尽管未示出,不过多个访客对象可以分布于在访客编程语言710中定义的一个或多个访客模块上。操作中,诸如SQL之类的DML语句771-773可以访问导出的访客对象,比如在DBMS 700的数据库字典(未图示)中。
例如,访客模块可能是基于(例如,Python)访客脚本730已定义的,该访客脚本730定义一个或多个被公开(即,导出)的访客对象,比如子例程。这些访客对象的创建需要执行访客脚本730,每次使用同一访客模块部署来定义访客模块实例时都会发生访客脚本730的执行。
如上所述,脚本执行创建访客对象。访客对象的寿命取决于如下各种实现。访客对象的寿命不会超过包含它的访客模块。
访客对象的寿命和可见性可能背离现有访客语言概念的状态,如下所示。例如,DBMS 700可以是多用户、多角色、多租户和访问受控的(例如,DDL授权语句)。在诸如web浏览器的传统JavaScript环境中不存在这些复杂性。DBMS 700可能具有另外的技术问题,比如作为命名空间的数据库模式和多个线程,它们具有浏览器脚本没有的可见性和共享影响。如在本文中的其他地方所述,诸如访客模块和环境之类的技术可以提供一些所需的隔离。然而,如下所示,为了附加的安全(即,正确性,比如为了安全性或兼容性),企业或云解决方案可能需要更鲁棒的隔离。
在实施例中,执行上下文(未图示)是提供充分隔离的附加机制。执行上下文是介于操作***的轻量级线程和重量级进程之间的具有操作特性的粗粒度控制流机制。类似于线程,多个执行上下文可以共享同一地址空间,比如DBMS 700的地址空间。与重量级进程一样,执行上下文可以具有它自己的私有环境命名空间,从中解析(即,查找)资源依赖项。执行上下文可以与DBMS 700的数据库对象互操作,如下所示。
DBMS 700可以具有并发的执行上下文,并且每个执行上下文都被数据库会话独占并且是单线程的。执行上下文可以与它的数据库会话一样长寿。至少当其数据库会话空闲时,执行上下文可以是空闲的。从而,在任何时刻实际上只有执行上下文的波动子集是活动的。例如,线程池可以具有比线程池所服务的执行上下文的数量少的线程总数。
在实施例中,多个执行上下文不共享访客模块实例。例如,同一个用户对于同一数据库模式可能具有两个数据库会话,这可以为同一访客模块部署创建两个访客模块实例。例如,对于同一访客模块部署,可以为使用该访客模块部署的每个执行上下文创建新的访客模块实例。从而,每当另一个执行上下文首次使用该同一访客模块部署时,可以重复访客模块实例初始化(例如,脚本执行)。
例如,每个执行上下文可以具有它自己的Java类加载器。同样地,对于分开的执行上下文和对于同一访客模块部署的重复的实例初始化可以重复执行同一(例如,Python)访客脚本730。从而,每个执行上下文可以具有它自己的名义上相同的访客全局变量的实例。
在以下场合可能发生执行上下文创建。尽管未示出,不过每个导出的访客子例程具有它自己的调用规范,如前所述。对于每个数据库会话,当访客模块的调用规范的调用点被首次调用时,比如在DML语句771中,则创建寿命可以与该会话一样长的新的执行上下文。用于同一调用规范或用于同一访客模块中的其他调用规范的后续调用点应当重用该执行上下文。在同一会话中,不同访客模块中的调用规范的调用点的首次调用使得创建另外的执行上下文。
通常,执行上下文具有与DML语句771的会话相同的权限。然而,创建调用规范的DDL语句(未图示)可以可选地改为指定应该为调用该调用规范的所有用户的所有会话保留和共享(例如,克隆)该DDL语句的会话的执行上下文。从而,用户A可以创建绑定到访客子例程的调用规范,即使当调用规范被另一个用户调用时,该访客子例程也总是以用户A的权限执行,从而在子例程执行期间临时提升权限。
如本文中后面所述,在一个访客模块中定义的访客子例程可以调用在另一个访客模块中定义的访客子例程。通常,即使对于同一会话,不同访客模块中的访客子例程也具有不同的执行上下文。然而,当第一访客子例程调用第二子例程时,DML语句771中只有一个调用点,该调用点是针对第一子例程的。当只有一个调用点时,同一会话只有一个执行上下文,实施例可以重用该执行上下文,使得通过同一调用点调用的两个子例程(即,一个子例程是直接调用的,另一个子例程是间接调用的)应当共享同一执行上下文。从而,调用点是同一执行上下文可以从其注入到访客子例程的整个调用树中的根,而不管访客模块边界如何。执行上下文与调用点或调用规范关联,如下所示。
在各个实施例中,访客编程语言710可以具有同一访客模块的多个实例,比如每个用户一个、每个会话一个、每个事务一个、每个(例如准备的,批处理的)DML语句一个、DML语句的每个调用规范一个、或者每个调用规范调用点一个。作为元数据,调用规范可以由同一访客模块的一些或所有(例如非同期的)实例共享。例如,一个实施例可能需要同一调用规范的多个实例,而另一个实施例可能改为只具有共享的单例模式。为每个DML事务、语句或语句的调用规范(即,无论有多少调用点)重新实例化同一访客模块可以通过在重新实例化时延和词法隔离(即正确性/安全,例如安全性或兼容性)之间进行平衡来提高性能效率。
在实施例中,不管同一个DML语句中有多少个调用点,每个调用规范实例化它所声明的访客模块的它自己的实例。在该实施例中,任何访客模块的寿命都不会超过实例化访客模块的DML语句的执行。从而,每次发出DML语句771时,访客脚本730就每个被引用的访客子例程运行一次,即,不是每个重复的(例如,每个表格行)调用运行一次,也不是每个调用点运行一次。例如,特定的访客模块可以导出函数foo和bar,但是不能导出来自不同访客模块的函数splat。如果DML语句771是“SELECT foo(),foo(),bar(),splat()FROMSomeTable;”,则该特定的访客模块被实例化两次(即,一次用于foo,一次用于bar)。UDFsplat()可以是用SQL实现的普通UDF,或者可以用相同或不同的访客编程语言在不同的访客模块中实现。
访客模块可以使用(即,依赖于)其他访客模块,但是空的访客模块作为依赖项可能或多或少是无用的。由访客模块导出的资源(即,访客对象)是使该访客模块有用的内容。例如,一个访客模块可以包含访客脚本730,访客脚本730可以初始化该访客模块,包括生成可以用于导出也可以不用于导出,比如导出到其他访客模块的访客对象。
如图所示,DML语句771-772与MLE的存储器(比如RAM)中由访客脚本730生成的访客对象(未图示)交互(例如,调用)。这些访客对象中的每一个可以由访客脚本730中的相应几行文本定义,访客脚本730本身是文本。
访客脚本730可能依赖于其他访客模块,比如按照依赖项790,如下所示。不管访客脚本730的执行是贪婪的、惰性的、解释的、编译的、还是基于中间代码(例如,字节代码)的,都一个语句接一个语句(例如,逐行)地发生访客脚本730的执行,这最终执行访客脚本730中的命令式语句740,命令式语句740是发出动态链接依赖项790的导入请求751的导入指令,依赖项790符号化地识别要解析的访客模块(未图示)。导入请求751的处理可以如下发生。
8.0示例导入处理
图8是描述访客编程语言710的导入依赖项的原生请求751的执行的流程图,这使DMBS 700基于映射780提供资源721或722,如下所示。参考图7讨论图8。
在共享本文中的机制的三种不同情形下,可能发生按照本文中的技术的依赖项的动态导入。尽管未示出,不过些情形之一是由用于访客模块创建的DDL语句引起的,如下所述。如图所示,其他两种情形由对于同一DML语句的相应备选实现(比如771-773)引起,如下所述。图8的讨论以如下各种方式解决了所有三种情形。
步骤802接收并执行(例如,DDL或DML)数据库语句,所述数据库语句明确地(即,DDL)或隐含地(即,对调用规范的DML调用点)调用访客编程语言710。
例如,用于访客模块创建的DDL语句可以调用(例如,Python)访客脚本730,以贪婪地实例化诸如资源721之类的访客对象,它可以是访客子例程。访客脚本730可以开始于依赖项导入指令或者在其他地方包含依赖项导入指令,所述依赖项导入指令通常是访客编程语言710中的命令式语句,比如740。然而如下所示,一些导入指令可能已经被静态地预处理(即,内联和删除),比如在访客脚本730的部署之前,比如在构建(即,打包)阶段期间。
此类构建阶段对本文中的技术来说是可选的。然而,与一般的软件一样,可能存在静态链接(即,构建阶段)和动态链接(即运行时),其中一些依赖项在构建时被完全解析和链接(例如,内联)。例如,JavaScript具有诸如Browserify和WebPack之类的静态打包工具,一些链接可以被卸载到这些静态打包工具上,从而减少对本文中的动态导入技术的需求。尽管Python没有包括静态内联,不过诸如Pip之类的工具可以将大多数链接职责转移到构建时,从而远离运行时。
在任何情况下,避免所有动态链接可能是不可能的或者不可取的,例如由于本文中其他地方的原因。从而,任何时间访客脚本730执行时,或者任何时候由访客脚本730定义的访客子例程被稍后调用时,导入语句都可能执行从而导致动态链接,如下所述发生。
在另一种情形下,尽管不太可能,不过访客子例程本身的主体可以包含导入语句。从而,调用访客子例程(例如,从DML查询)可能导致动态链接。
在作为其他两种情形的混合的另一情形下,访客模块或多或少频繁地被重新实例化,比如对于多个执行上下文,如本文中后面所述。例如,在DML语句771的执行期间,(例如,附加的)执行上下文的初始化可导致在DBMS 700的存储器(例如,RAM)中实例化同一模块部署的另一实例。从而,在混合情形下,导入语句在执行DML语句的同时执行,与一种情形一样,不过对于模块创建DDL语句,导入执行会如上所述那样地进行,与另一种情形一样。
从而,步骤802、804和806是由DDL语句还是DML语句引起的,这取决于情形。同样,这需要(重新)执行所有的访客脚本730,还是只需要调用通过访客脚本730的早先执行已定义的访客子例程,这也取决于情形。此外,一种实现可以只支持三种情形中的一种或两种情形。
步骤802导致步骤804和806,如下所示。访客脚本730或其访客子例程之一的执行可以通过串行地执行各个访客语句来进行,包括命令式语句740,命令式语句740是在步骤804中发出导入请求751以动态链接依赖项790的导入指令,所述依赖项790符号化地识别要解析的访客模块(未图示)。
在实施例中,DBMS 700的MLE在每个访客编程语言实现中都具有相应的适配器。在步骤804期间,该适配器截取并特别处理导入请求751,如下所示。尽管未示出,不过导入请求751包含依赖项790的名称,如模块解析所需那样。MLE可以在下一步骤806中使用该依赖项名称,如下所示。
步骤806解析依赖项790。依赖项名称可以用作依赖项映射780中的查找关键字,以选择满足依赖项790的访客模块。依赖项映射780可以由参与依赖项解析的访客虚拟环境实现,如本文中后面所述。例如,在映射780中,依赖项790可以绑定到访客模块721。
9.0示例组件边界行为
图9是描述在诸如数据库会话761-762、DML语句771-773和访客模块721-722之类组件的边界的示例活动的流程图,如下所示。参考图7讨论图9。
图9的步骤描述可能一起发生也可能不一起发生的多个情形,如下所示。步骤901A-B涉及同一DML语句771调用同一访客编程语言710的相应不同访客模块721-722中的两个调用规范。换句话说,DML语句771直接依赖于多个访客模块,这在实施例中暗示执行上下文,如下所示。
如本文中前面所述,执行上下文通常对应于数据库会话和访客模块的组合。即,在同一数据库会话期间对同一访客模块的调用可以重用单个执行上下文。例如,DML语句771发生在数据库会话761中。DML语句771的执行跨越步骤901A-B,如下所示。
在步骤901A期间,DML语句771调用其调用规范存在于访客模块721中的第一UDF。从而,第一UDF是在对于数据库会话761和访客模块721的组合的第一执行上下文中调用的。如果该第一执行上下文已经存在,则重用第一执行上下文,如果不存在,则立即创建第一执行上下文。
在步骤901B期间,同一DML语句771调用其调用规范存在不同访客模块722中的第二UDF。从而,即使两个访客模块721-722都是用相同的访客编程语言710定义的,也不应重用第一执行上下文来调用第二UDF。代替地,在对于同一数据库会话761和不同的访客模块722的组合的第二执行上下文中调用第二UDF。如果该第二执行上下文已经存在,则重用第二执行上下文,如果不存在,则立即创建第二执行上下文。
如本文中前面所述,与其他执行上下文(例如,其他数据库会话)共享访客模块721的部署的每个执行上下文可能需要它自己的访客模块实例。另外如上所述,每个附加模块实例可以被单独初始化,使得每次附加模块实例被初始化时,访客脚本730就重新运行。例如,如果DML语句771具有数据库会话761的访客模块721的第一次使用,则应当在DML语句771的执行期间为数据库会话761实例化访客模块721。从而,DML语句771可以使访客脚本730运行,这导致步骤902A-C,如下所示。
如本文中前面所述,访客脚本730的执行可以通过一次一个地解释访客脚本730内的各个语句来进行。例如,步骤902解释可以是导入指令的命令式语句740。命令式语句740的解释可能不需要步骤902B-C,或者需要步骤902B-C之一,或者可能需要步骤902B-C两者,如下所示。
在步骤902B,访客编程语言710的实现解析脚本文本,比如访客脚本730的所有文本或单个文本行。例如,步骤902B可以生成Truffle AST或附加到现有的Truffle AST。
取决于访客编程语言710,命令式语句740最初可以是字节代码,或者可以通过步骤902B被动态编译成字节代码。在任一情况下,步骤902C解释诸如字节代码之类的中间代码。从而尽管未示出,不过步骤902B可能导致也可能不导致步骤902C。
DML语句771可以调用UDF,该UDF通过调用规范调用访客子例程,比如通过步骤901A-B中的任意一个。然而,该访客子例程本身可以调用同一访客编程语言710的其他访客模块中的其他访客子例程,如步骤903A-B中所示。例如,DML语句771可以通过访客模块721中的UDF和调用规范,直接调用(即,示为步骤903A)访客子例程,该访客子例程通过它自己的访客逻辑,调用不同访客模块722中的访客子例程,示为步骤903B。
从而,和跨越两个访客模块之间的边界的步骤901A-B一样,步骤903A-B也跨越模块之间的边界。然而,步骤903A-B共享同一执行上下文。而步骤901A-B不共享同一执行上下文。从而,访客模块之间的边界是否导致两个执行上下文之间的切换取决于情形。
空的访客模块可能或多或少是无用的。只需要相对于访客模块的依赖项或者访客模块的导入,因为该访客模块包含所需的资源(即,访客对象),比如访客子例程。然而,所需的访客对象不必是子例程,可以改为是数据对象,比如数组。例如,同一访客编程语言710的多个相互依赖的访客模块721-722可以共享由访客模块721构造的同一阵列。例如,在步骤904,访客模块722中的逻辑可以导入访客模块721,然后引用该数组。
访客子例程或访客脚本本身可以发出DML语句,示为步骤905。例如,DML语句771可以是调用UDF的SQL,该UDF由其访客逻辑发出附加SQL查询的访客子例程来实现。从而,DBMS700的MLE具有SQL和访客编程语言710之间的完全双向接口,这可能需要使数据库会话761作为当前或默认数据库会话对该访客子例程可用,这可以如下所示实现。
在一个实施例中,由于每个执行上下文可以具有它自己的全局变量的独立实例,如本文中前面所述,因此该全局变量可以将数据库会话761存储为当前会话。在另一个实施例中,导出当前数据库会话,或者导出返回当前数据库会话的工厂子例程,并且这两者中的任意一个都是从一个模块导出的,该模块像访客模块一样地操作,但是原生于DBMS 700,并且不具有访客编程语言,或者访客编程语言是DML,比如PL/SQL或T/SQL。访客模块721可能需要导入该原生模块来访问当前数据库会话。
10.0示例依赖项解析处理
图10是描述实施例中的用于满足依赖项790的示例活动的流程图。本文中后面介绍了附加的依赖项满足技术。参考图7讨论图10。
步骤1002将访客模块722加载并高速缓存到DBMS 700的存储缓冲器705中。例如,数据库会话761中的DML语句771使导入请求751访问依赖项790,如本文中前面所述。另外如上所述,DBMS 700使用映射780来决定应当使用哪个实际访客模块来满足依赖项790。映射780的实现在本文中后面介绍。例如,可以选择访客模块722来满足依赖项790。
步骤1004可以执行不同数据库会话762中的DML语句773,它可以调用UDF的调用规范来调用访客子例程,该访客子例程可以执行导入请求752来访问同一依赖项790,表示为步骤1006。如在本文中其他地方所述,在步骤1008中将为依赖项790选择哪个访客模块取决于可以基于当前数据库会话和/或当前执行上下文的映射780。从而,在步骤702中被解析为访客模块721的依赖项790可以改为在步骤708中被解析为不同的访客模块722。本文中后面介绍了用于这种资源变更的附加机制,比如访客虚拟环境。
11.0多语言集成
图11是描述实施例中的示例软件容器1100的框图。软件容器1100具有多语言引擎(MLE),所述多语言引擎便利不同访客编程语言1112-1113之间的协作,如下所示。软件容器1100可以是DBMS 110的实现。
取决于实施例,软件容器1100可以是能够加载和执行定制逻辑的任何中间件,比如平台即服务(PaaS)或基础设施即服务(IaaS)。例如,软件容器1100可以是诸如web服务器之类的应用服务器、诸如Spring之类的控制反转(IoC)容器、诸如管理程序或Java VM(JVM)之类的虚拟机(VM)、脚本或字节代码的编程语言解释器、诸如Docker或Kubernetes之类的应用容器、或者诸如RDBMS之类的DBMS。
如本文中前面所述,软件容器1100的MLE具有创新的集成机制,包括:a)多个访客编程语言1112-1113的托管,b)访客模块(未图示)的加载和操作,c)访客模块之间的符号化依赖项(未示出)的解析,以及d)诸如1120之类的调用规范的生成和公布。另外如本文中前面所述,MLE可以创新地侵入(即,截取)和增强访客编程语言1112-1113的操作,比如作为共享资源的访客对象的导入和导出。
可以这样实现MLE,使得通过少数特定于语言的适配器,MLE的大部分或全部核心功能都以语言中性的方式可用。在实施例中,MLE基于作为功能单元的访客模块通过中介接口的协作,来以透明的方式便利多种访客语言1112-1113的协作,如下所示。例如,访客编程语言1112的访客模块可以与访客编程语言1113的访客模块交互,而两个访客模块中的任何一个都不知道另一个模块使用的是哪种语言。从而,软件容器1100或多或少实现了多种访客语言的完全接口兼容性,这些访客语言可以协作以便例如帮助执行用原生编程语言1111表达的语句。
原生编程语言1111完全集成到软件容器1100中。例如,当软件容器1100是DBMS时,则原生编程语言1111可以是诸如DML(比如SQL)之类的查询语言。作为另一个例子,软件容器1100可以用原生编程语言1111来实现。例如,当软件容器1100是用Java实现的SpringIoC时,原生编程语言1111可以是Java。在实施例中,原生编程语言1111是领域专用语言(DSL),它可以是也可以不是软件容器1100专有的。
如本文中前面比如对于DBMS所述,软件容器1100为访客编程语言1112-1113的子例程生成调用规范,比如1120。例如,调用规范1120可以导出访客编程语言1112的子例程,作为原生编程语言1111的UDF。UDF调用规范1120包括具有原生于原生编程语言1111的相应数据类型的自变量(比如1141)和/或返回值。调用规范1120还包括数据绑定1131,数据绑定1131将自变量从原生编程语言1111的数据类型转换为访客编程语言1112数据类型,比如用于访客自变量1142的数据类型,并且反过来对于返回值和/或OUT参数也一样。从而,语言1111-1112或多或少与彼此的类型***完全隔离,使得任何一种语言1111-1112都不会暴露给另一种语言的数据类型。
绑定1131不是两种访客编程语言之间的绑定,相反可以如下所示实现绑定131。如上所述,作为第一绑定,绑定1131可以双向转换语言1111-1112的数据类型。同样地,原生编程语言1111还可以具有双向转换语言1111和1113的数据类型的第二绑定(未图示)。
在实施例中,访客编程语言1112-1113之间的绑定1132可以是第一绑定和第二绑定两者的耦接(未图示)。从而,访客编程语言1112-1113中的任何一个的数据类型最初被转换为原生编程语言1111的数据类型,作为中间表示,然后被转换为访客编程语言1112-1113中的另一个。例如,绑定1132可以将Python字符串转换为SQL字符串,然后转换为JavaScript字符串,使得Python模块可以将值传递给JavaScript模块。
在每个访客编程语言只需要提供一个双向数据绑定(即,与原生编程语言1111的绑定)的意义上,该方法是可缩放的。在另一个实施例中,绑定1132不使用原生编程语言1111数据类型作为中间表示,而是直接在访客编程语言1112-1113的数据类型之间转换。这种方法可以具有更高的运行时效率。
无论数据绑定1132是如何实现的,都可以如图所示地布置软件容器1100的组件,以实现查询的多语言执行。诸如调用规范、数据绑定和模块依赖项解析之类的集成技术以透明地实现不同访客编程语言的模块之间的控制流和/或数据流的方式,便利相互依赖的访客模块的配置。例如,原生编程语言1111的查询可以调用访客编程语言1112中的子例程,该子例程访问访客编程语言1113中的诸如对象1150之类的资源。
从而,查询的执行可以跨越访客语言边界,以协作方式接合访客编程语言1112-1113。根据这样的互操作性,可以具有如下所示的各种突出好处。
例如,可以按照访客编程语言1112-1113的自然强度来分配同一查询的不同职责。例如,统一资源定位符(URL)处理可以委托给访客编程语言1112,访客编程语言1112又将正则表达式委托给访客编程语言1113。
例如,应用开发者不会限于任何一种访客编程语言,从而可以具有许多访客编程语言的大量第三方(例如,开源)资源,供随时作为访客模块部署。这可能使购买与构建之间的权衡偏离从头开始的功能开发,从而加速开发和/或降低开发成本。反过来,这可以鼓励规模更宏大(即,特征丰富)的数据库应用,和/或促进诸如应用服务器之类具有更少(例如,中间件)层的整合服务拓扑,这可以降低操作/管理成本和技能。
12.0示例访客对象访问处理
图12是描述实施例中的用于从不同的访客编程语言1113访问访客编程语言1113中的访客对象1150的示例活动的流程图。参考图11讨论图12。
步骤1202是预备性的,创建访客编程语言1113中的访客对象1150,如本文中前面所述,包括诸如访客模块实例化、访客脚本执行、访客对象导出和各种数据库字典***之类的活动。步骤1204从原生编程语言1111语句调用不同的访客编程语言1112,如本文中前面所述。例如,调用规范1120可以在原生编程语言1111和访客编程语言1112之间进行中介,包括如上所述的用于自变量数据类型转换的绑定1131的操作。从而,步骤1204将控制从原生编程语言1111转移到访客编程语言1112,这可能需要也可能不需要如上所述的执行上下文的生成和/或切换。
步骤1206执行从不同的访客编程语言1112访问访客编程语言1113中的访客对象1150的请求。同样,这可能需要也可能不需要如上所述的执行上下文的生成和/或切换。步骤1206以与也跨越语言界线的步骤1204或多或少类似的方式跨越语言边界。如本文中上面所述,如同步骤1204和1206中的每一个一样,跨越到访客编程语言需要以下中的一些或全部:a)执行上下文生成和/或切换,b)访客模块解析和/或实例化,带或不带访客脚本执行,c)自变量数据类型转换和/或验证,例如通过绑定1131或1132,d)重载签名解析,和e)将控制实际转移到访客编程语言中,比如访客子例程的调用和解释或其他执行。
如前所述,该访客脚本或访客子例程可以发出导入依赖项的指令。发出指令的脚本或子例程不需要知道哪个相同的或其他的访客编程语言实现了能够满足该依赖项的访客模块。例如并且取决于依赖项映射,如本文中上面和下面所述,在本文中呈现的各种情形下,同一依赖项可以由以同一或不同的访客编程语言的不同访客模块来满足。例如,由于预期的替换或由于意外的名称冲突,同一依赖项可能对于一个客户端解析为Python访客模块,而对于另一个客户端解析为JavaScript访客模块。
多语言引擎的实现可以使用一些解耦机制,包括可重用的数据结构和/或生成的胶连逻辑,来实现这种多语言模块可插拔性。查找表和散列映射提供了基于间接的或多或少被动的翻译。例如,如在本文中其他地方所述,可能存在一个被动的、贪婪的或惰性的适配器,该适配器将访客编程语言的原生模块化框架翻译成本文中所教导的访客模块机制和技术。例如,如本文中所述,原生于软件容器1100和/或原生编程语言1111的原生数据类型和其他结构,比如SQL的各个方面,可以用作也可以不被用作所有访客语言数据类型被翻译成或从其翻译过来的规范表示。在实施例中,诸如访客虚拟环境之类的命名空间便利了模块耦接,如下所示。
13.0访客虚拟环境
图13是描述实施例中的示例计算机1300的框图。计算机1300的访客虚拟环境1311-1312提供相同命名的依赖项对不同访客模块的备选绑定,如下所示。计算机1300可以包括DBMS 110的实现。
如上所述,访客模块,比如1341-1342,可以依赖于其他访客模块来满足依赖项。另外如上所述,诸如隔离和代码库版本控制之类的问题可能限制访客模块的共享。例如,可能需要同一模块部署的多个实例,或者可能需要用于相似模块的不同代码库(例如,发布版本),和/或可能需要避免资源名称冲突。从而,计算机1300具有比如为多租户提供隔离的访客虚拟环境1311-1312。
访客虚拟环境1311-1312是命名空间,所述命名空间提供一些访客模块1341-1342的符号化依赖项(即,本文中讨论的名称)(未图示)和充当这些依赖项的实现(即,本文中讨论的定义)的其他访客模块(未图示)之间的映射(即,绑定)(未图示)。在该意义上,每个访客虚拟环境1311-1312起命名空间的作用,通过该命名空间每个访客模块1341-1342都可以看到其他所需的访客模块。从而,数据库应用程序可以或多或少由协作的访客模块组成。在实施例中,每个访客虚拟环境1311-1312都被实现为存储访客模块的绑定以便查找的关联数据结构,比如字典或散列表,如下所示。
在实施例中,计算机1300包括RDBMS或其他DBMS。其他实施例不包含DBMS。在所示实施例中,计算机1300接收并执行比如用于DBMS的DDL语句1321-1323,以便创建或以其他方式管理访客虚拟环境1312。其他实施例可以接收和执行命令,这些命令尽管不是DDL和/或不是用于DBMS的,不过也可以创建和管理访客虚拟环境1312。DDL语句1321-1323是计算机1300的实现选择的示例。从而,关于DDL语句1321-1323的技术的以下讨论可以容易地应用于既不需要DBMS也不需要DDL的实现。在实施例中,计算机1300包含不是DBMS的软件容器,比如本文中前面所介绍的。在实施例中,计算机1300既不需要DBMS,也不需要本文中前面所述的任何其他软件容器。
DDL语句1323在计算机1300中创建新的访客虚拟环境1312。DDL语句1323可以指定其中定义访客虚拟环境1312的数据库模式,该数据库模式可以默认为发出DDL语句1323的数据库会话的当前模式。DDL语句1323可以可选地指定要用作原型的现有访客虚拟环境,从该原型可以生成克隆。例如,DDL语句1323可以指定新的访客虚拟环境1312应当从现有的访客虚拟环境1311克隆。克隆复制所有依赖项绑定,并且如果没有克隆,则新的访客虚拟环境1312最初根本没有依赖项绑定。
DDL语句1321将新的依赖项绑定添加到现有的访客虚拟环境1311中。例如,示为导入1360的DDL语句1321的细节可以指定依赖项的名称和要绑定到该依赖项的访客模块的名称。例如,访客编程语言1350中的访客模块1341可以通过名称,比如用require()语句(未图示)来导入依赖项。计算机1300的多语言引擎(MLE)(未图示)可以截取并特别处理导入指令(即,请求),比如require()。例如,require()的调用可以指定MLE可以用作查找关键字来选择访客虚拟环境1311中的绑定的依赖项名称。所选择的绑定可以识别进行请求的访客模块1341应当用于获得与该require()调用相关的资源的其他访客模块。
为了解析依赖项,每个访客模块实例具有一个相应的访客虚拟环境。例如,创建访客模块的DDL语句(未图示)可以指定现有的访客虚拟环境。如果没有指定访客虚拟环境,则计算机1300为访客模块提供默认访客虚拟环境。
多个访客模块1341-1342可以共享同一访客虚拟环境1311。不管访客模块1341-1342是否:a)具有不同的代码库,b)在不同的访客编程语言中定义,c)由在不同的访客编程语言中定义的其他访客模块导入,和/或d)是为不同的用户账户和/或数据库会话加载的,都可发生这种共享。
访客模块1341可以最初被分配给访客虚拟环境1311,然后再被重新分配给访客虚拟环境1312,比如通过DDL语句(未图示)。在实施例中,这种重新分配导致访客模块1341基于访客虚拟环境1312被(例如,惰性地)重新加载。例如,可以重新运行实现访客模块1341的Python脚本。
DDL语句1322具有示为重新分配1370的细节,所述细节用新的依赖项绑定替换访客虚拟环境1311中的现有依赖项绑定。从而,依赖项可以被重新映射到不同的访客模块,比如访客模块的新的发布版本。在实施例中,DDL语句1322是没有追溯力的,使得已使用访客虚拟环境1311的访客模块不会受到对访客虚拟环境1311的更改的影响。例如,访客模块1341-1342可以分别使用访客虚拟环境1311的并发的不同版本。
取决于实施例,DDL语句1321-1323中的任何一个可以指定:访客编程语言的版本号、访客编程语言的配置设定、和/或资源加载路径,比如本文中后面讨论的。每个访客虚拟环境在数据库模式中定义,所述数据库模式可以包含多个访客虚拟环境。数据控制语言(DCL)语句1330可以管理访客虚拟环境1311的使用许可。
14.0示例访客虚拟环境处理
图14是描述实施例中的用于生成、修改和使用访客虚拟环境1311的示例活动的流程图,访客虚拟环境1311符号化地将访客依赖项绑定到访客模块。参考图13讨论图14。
步骤1402生成最初是空的(即,没有绑定)的访客虚拟环境1311。例如,DDL语句1323可以是“CREATE MLE ENV scott.'myenv';”,该语句创建访客虚拟环境1311,并在数据库模式scott中将其命名为myenv。
最初为空的访客虚拟环境1311可能或多或少还不能使用,因为其目的是将依赖项映射到相应的访客模块。在访客虚拟环境1311中,步骤1404添加关于依赖项的绑定。例如,DDL语句1321可以是“ALTER MLE ENV scott.'myenv'ADD IMPORT hello MODULE scott.'hello';”,该语句指定将名为hello的依赖项绑定到访客虚拟环境1311中的访客模块1341的导入1360。
访客模块1341已在或者(现在或稍后)将在访客编程语言1350中实例化。然而,访客模块1342在同一或不同的编程语言中实例化。在任何情况下,访客模块1342中的访客脚本或访客子例程的执行都可以发出访问名为hello的依赖项的请求,比如通过导入指令,如步骤1406所示。步骤1406通过选择访客模块1341,使用访客虚拟环境1311来解析名为hello的依赖项。例如,按照访客模块1342的元数据,或者按照当前执行上下文、当前数据库会话或当前数据库模式,访客模块1342可能正在使用访客虚拟环境1311。
在步骤1406期间,访客虚拟环境1311用于解析对于依赖项hello,访客模块1342依赖于访客模块1341,这可能需要也可能不需要诸如加载、实例化和/或重用访客模块1341之类的活动。
与本文中所述的MLE相结合,访客虚拟环境1311可以:a)包含与在许多访客编程语言中实现的访客模块的绑定,b)在运行时(例如,查询)时使用,用于由在许多访客编程语言中定义的访客模块解析,以及c)用于便利跨越任何两种访客编程语言之间的边界。从而,访客虚拟环境1311是语言中性的。
15.0访客虚拟环境共享
图15是描述实施例中用于比如在多租户环境中,比如具有协作或孤立(即,不协作)的多个数据库应用,比如在企业的私有云中,在多个数据库用户和多个访客编程语言之间共享访客虚拟环境1311的示例活动的流程图。参考图13讨论图15。
图15示出了可能相互独立也可能不相互独立的各种情形。步骤1502执行DCL语句1330,以对于计算机1300中的一些用户账户或角色授予或撤销对现有访客虚拟环境1311的某些访问。例如,安全和防护可以鼓励对于大多数用户,DCL语句1330只被用于准许对访客虚拟环境1311的只读访问。
而在步骤1504A-B中,没有修改访客虚拟环境1311的许可的用户账户可以如下接近这样的修改。步骤1504A执行DDL语句1323以生成访客虚拟环境1312,作为访客虚拟环境1311的可修改克隆。步骤1504B执行DDL语句1322,DDL语句1322包含重新分配2370,以在访客虚拟环境1312中增加或替换命名依赖项和可用访客模块1342之间的绑定。
从而,比如通过将该命名依赖项和访客模块1341之间的绑定替换为同一命名依赖项和不同的访客模块1342之间的新的绑定,可以自定义克隆访客虚拟环境1312。从而,通过克隆,模块替换是可能的,比如当一个数据库应用需要打补丁的(例如第三方)库,而计算机1300的同一DBMS中的另一个数据库应用必须继续使用所述库的较旧且更稳定的版本时。
依赖项绑定的数据结构和词法范围可取决于实施例。例如,步骤1506可以在一个或多个数据结构,比如:访客虚拟环境、数据库模式和/或数据库字典内,将依赖项名称绑定到访客模块。计算机1300的MLE可被设计成基于这样的相关数据结构来解析依赖项。
诸如访客虚拟环境之类的这些数据结构便利共享和重用。例如,比如在步骤1508A期间,导入同一依赖项名称的请求可以在步骤1508B期间解析到同一访客模块或者访客模块的同一部署的类似实例。例如,即使当这些导入请求来自不同的用户账户、不同的数据库会话、或者甚至来自不同的访客编程语言时,也可能发生此类共享。这是因为诸如访客虚拟环境之类的绑定结构可以被共享或克隆,或者不同的访客虚拟环境可以以其他方式被配置成包含一些相同的绑定。
16.0虚拟文件***
图16是描述实施例中的示例软件容器1600的框图。软件容器1600从虚拟文件***透明地检索资源1681-1682,以如下所述泛化备选存储机构1671-1674。软件容器1600可以是DBMS 110的实现。本文中前面讨论了软件容器的各种实施例,包括一些不需要DBMS或DML的实施例。从而,作为其他实施例中可能不存在的示例性实现选择的一部分,呈现了本文中的和软件容器1600一起使用DBMS或DML的技术。其他实施例可以使用这些所描述的技术而不需要DBMS或DML。
软件容器1600具有诸如访客模块的部署(即,代码库)之类的数据资源的灵活持久的存储。备选存储机构1672-1674提供了诸如1671之类的实际文件***通常不具备的特征。这些特征可以如下所述,以可以对应用开发者和客户端(比如客户端会话1611-1612)透明的特殊方式支持代码库使用。同样地,软件容器1600可以强行实施与实际文件***1671正交的许可。例如,软件容器1600可以作为操作***(OS)超级用户来执行,该操作***(OS)超级用户可以访问实际文件***1671的所有文件,并且还可以比如按照先前的数据控制语言(DCL)授权拒绝特定数据库客户端的访问。
例如,访客模块(未图示)可以用诸如可运行脚本、类文件、图片和/或电子表格之类的代码或数据的一个或多个持久对象(比如资源1681-1682)来实现。这样的持久对象可以被存储为松散(即,单个)的文件,聚集在单片归档文件(即,库)中,或者以其他方式进行大容量存储,如下所示。持久对象可以与元数据对象(例如,清单或描述符)搭配,虚拟文件***1650可以分析元数据对象以便利资源加载。
客户端会话1611-1612的种类和性质取决于实施例。客户端会话1611-1612封装可能暂时重叠也可能不暂时重叠的客户端使用的单独(例如,通过强行实施的隔离)的序列。在实施例中,软件容器1600是RDBMS或其他DBMS,而客户端会话1611-1612是数据库会话。在实施例中,每个客户端会话1611-1612都是远程的,并且具有它自己的单独网络或进程间连接。例如,客户端会话1611-1612可以或多或少对应于超文本传输协议(HTTP)会话和/或开放***互连(OSI)网络堆栈的会话层(也称为层5)。在所示实施例中,软件容器1600具有客户端会话1611-1612。在其他实施例中,软件容器不需要客户端会话。例如,软件容器可以从队列或控制器接收命令,所述命令可以混合、模糊或以其他方式没有会话边界。例如,多个客户端可以向软件容器1600所依赖的同一队列提交命令,而不考虑命令的来源。
软件容器1600提供资源的高度动态的导入(例如,加载)。资源通常在访客模块实例(未图示)的初始化期间导入,比如当客户端会话1611首次调用模块的任何调用规范(未图示)时,这是有些动态的。然而,资源导入(例如,require()脚本语句)可以在访客编程语言1630的访客逻辑执行的任何时候发生。例如,require()调用可以是有条件的(例如在if语句中),并从访客子例程(未图示)内发出,这是高度动态的。在任何情况下,DDL或DML语句(比如1621-1622)都可能导致访客模块和/或访客对象的加载。例如,DML语句1621-1622可以发出相应的原生请求1641-1642,以例如通过require()调用导入同一依赖项1660。
不需要DBMS的软件容器1600的实施例可以接受既不是DML也不是DDL的命令。从而,DML语句1621-1622是实现选择的示例。在其他实施例中,本文中的技术可以在没有DBMS、DML或DDL的情况下实现虚拟文件***1650的类似使用。
文件***实现后端1671-1674是相互排斥的备选方案,用虚线箭头表示。软件容器1600可以具有许多虚拟文件***,比如1650,但是每个虚拟文件***只有一个相应的实现后端。如用实线箭头所示,虚拟文件***1650使用归档文件1672作为它的后备存储区。
例如,虚拟文件***1650可以通过在可能包含许多资源的归档文件1672内选择资源(未图示)来解析依赖项1660。例如,归档文件1672可以是(例如,压缩的)zip文件、磁带归档(tar)文件或Java归档(jar)文件。在实施例中,虚拟文件***1650例如通过解压缩并按照归档文件1672内列出包含在归档文件1672内的原始文件的清单(未图示),从归档文件1672中提取该资源。
在实施例中,虚拟文件***1650可以直接使用提取的资源。在另一个实施例中,虚拟文件***1650可以将归档文件1672内的文件分解(即解包)到诸如1671之类的实际文件***中。例如,可以级联虚拟文件***,使得对于诸如解包和/或高速缓存之类的特征,一个虚拟文件***可以委托给另一个虚拟文件***。例如,虚拟文件***可以被聚集(例如,菊花链接)为一组加载路径,比如类路径或模块路径。
如本文中前面所述,作为软件容器1600的多语言引擎(MLE)的一部分,访客编程语言1630的解析器、编译器和/或解释器可以截取并特别处理原生请求1641-1642。例如,原生请求1641可以指定依赖项1660的限定或非限定名称,MLE或访客编译器可以分析所述限定或非限定名称,以识别依赖项1660的符号名称。如本文中前面所述,访客虚拟环境(未图示)可以将符号化依赖项映射到实际访客模块实例。例如,依赖项1660可以映射到其代码库是归档文件1672的访客模块。从而,MLE、访客虚拟环境和虚拟文件***1650可以协作以动态满足依赖项1660。
在实施例中,虚拟文件***可以作为资源高速缓存操作。例如,虚拟文件***可以用存储缓冲器1673实现,存储缓冲器1673可以高速缓存访客模块的一些或全部,包括资源1682。例如,虚拟文件***1650可以将归档文件1672分解到存储缓冲器1673中。资源1682可以是静态资源,比如图片,或者可以是计算的(即,动态生成的)访客对象,比如由访客模块的初始化脚本生成的JavaScript对象表示法(JSON)数据结构。
在实施例中,整个访客模块或该模块内的各个资源可以分别作为大对象(即,BLOB或CLOB)存储在数据库表格1674的列1690中。从而,可以按照数据库语义而不是原生文件***语义来管理模块资源。虚拟文件***可以自动地发出(例如,生成)访问数据库列1690所需的DML。
17.0示例虚拟文件***处理
图17是描述实施例中软件容器1600从虚拟化存储装置(比如虚拟文件***1650)检索诸如1681-1682之类的资源的示例活动的流程图。参考图16讨论图17。
步骤1702调用访客编程语言。例如,可以执行DML语句1621。在步骤1704,该访客编程语言执行访问依赖项1660的请求1641,比如导入指令,如本文中前面所述。
依赖项1660的满足可以分两个阶段发生。在第一阶段,软件容器1600的MLE比如按照绑定(比如包含在访客虚拟环境(未图示)中的绑定)将依赖项1660解析到特定的访客模块(未图示)。取决于情形,该访客模块可能已被加载或者可能还未被加载。
在第二阶段,步骤1706检索满足依赖项1660的资源1681。如果解析的访客模块还没有被加载,则发生步骤1706,或者即使该访客模块已被加载,有时也可能发生步骤1706,如本文中后面所述。
步骤1706检测资源1681存储在哪里以及是如何存储的。由于图17的处理一般发生在访客模块创建/实例化期间,因此资源1681可以是访客模块的代码库中的(一个或多个)访客脚本,所述访客脚本可以是实际文件***1671中的(一个或多个)(例如,文本或类)文件。或者,依赖项1660可以由数据存储区1672-1674任意之一中的资源来满足。从而,步骤1706检测所需资源保持在哪个数据存储区中。
如本文中前面所述,访客模块的代码库通常由创建访客模块的DDL语句来识别。从而,软件容器1600可以维护描述访客模块的元数据,包括诸如包含访客模块的代码库的数据存储区的位置和种类之类的细节。每当该访客模块被(重新)实例化时,软件容器1600可以查阅该元数据以检测该代码库存储在哪里以及是如何存储的。
访客模块的部署可以共享,比如当两个数据库会话分别需要该访客模块的他们自己的实例时。例如,两个数据库会话可以分别执行同一访客脚本以初始化该访客模块的每个实例。虚拟文件***1650是数据存储区适配器,两个会话可以共享该适配器来访问相同的资源,比如访客模块的代码库的全部或部分。作为适配器,虚拟文件***1650向软件容器1600的MLE的其余部分隐藏哪种数据存储区实际上用于访客模块。从而,虚拟文件***1650提供了统一的外观或接口,通过该统一的外观或接口可以在不暴露检索机制的情况下检索资源。
软件容器1600可以在访客模块的元数据内包含虚拟文件***1650。从而,步骤1706可以通过访问与依赖项被解析到的访客模块关联的虚拟文件***1650,来定位和检索用于被解析的依赖项的资源。例如,DML查询可能需要几个依赖项,并且软件容器1600的MLE可以将这些依赖项解析到特定的访客模块,并以统一和存储无关的方式透明地加载这些访客模块,即使这些访客模块中的每一个实际上可能驻留在非常不同的数据存储区中。
18.0示例实现
以下是基于特定实现选择的示例实现。例如,DBMS是关系DBMS(RDBMS)。同样地,DDL、DCL和DML由SQL提供。
包含在本示例实现中的是用于配置和操作在本示例实现和本文中其他地方呈现的新颖的多语言数据库组件的数据库语句。在本示例实现中,访客组件也可以被称为MLE组件。例如,MLE模块是访客模块。本示例实现示范了对以下语言的支持:SQL、Java、JavaScript和Python。在本示例实现中使用的MLE还支持更多访客编程语言的添加。
本示例实现突出了MLE和对于各种访客编程语言来说原生的和/或最佳的相应模块化(例如,包)框架之间的集成。例如,访客模块可以通过设计被安排成子目录的层次结构,并且包命名可以反映该层次结构。例如,访客模块通过名称来绑定和解析,并且这样的名称可以反映该层次结构。然而,MLE的其他实施例不需要在名称和/或子目录上施加层次结构语义。
在实施例中,虚拟文件***、访客虚拟环境和/或支持访客模块的(一个或多个)其他MLE组件可以直接支持层次结构行为/方面,比如名称标记、子文件夹枚举、父文件夹、大小写敏感性和/或清单。另外如本文中上面所述和下面所示,MLE可以集成的访客原生模块化的其他特征包括相互依赖、可见性、推迟加载、解压缩、版本和/或搜索顺序。
18.1创建MLE语言
MLE语言应在可以创建和执行在该语言中执行的MLE函数之前添加到RDBMS中。使用CREATE MLE LANGUAGE DDL可以将新的MLE语言添加到数据库中:
CREATE MLE LANGUAGE MYLANGUAGE;
这创建具有与指定的语言名称(这种情况下为MYLANGUAGE)匹配的标识符的模式对象。DDL语句将向RDBMS字典注册由MLE***(drop-in)库提供的现有MLE语言实现。该DDL给予用户向数据库注册他自己的MLE语言实现的能力,而不是仅仅依赖于预定义的语言注册。
18.2运行时状态隔离
当MLE语言代码,比如由MLE模块导出的动态MLE代码段或函数,在会话中被执行时,与执行关联的运行时状态被封装在执行上下文中。运行时状态包括全局变量以及语言环境的状态。执行上下文是用于一种或多种MLE语言的独立的、隔离的运行时环境。共享执行上下文的所有代码都可以完全访问它的所有运行时状态(例如,先前定义的任何全局变量)。相反,在一个执行上下文中执行的代码没有办法看到或修改另一个执行上下文中的运行时状态。
MLE将执行上下文用于来自SQL和PL/SQL的函数和过程调用。这里,执行上下文分离不同用户和不同MLE模块的运行时状态。
18.3利用MLE模块的代码管理
MLE语言代码可以作为MLE模块持久存储。MLE模块是包含用单一MLE语言编写的代码的模式对象。MLE模块对应于相应MLE语言中的“库”或“模块”的概念。例如,JavaScriptMLE模块是JavaScript UMD模块。
MLE模块中的代码可以以两种不同的方式使用:
·MLE模块导出的函数可以通过创建调用规范来公布。可以从SQL和PL/SQL以与PL/SQL函数和过程相同的方式调用MLE调用规范。
·MLE模块可以由用相同语言编写的其他MLE代码导入。例如,在MLE中执行的JavaScript代码可以使用require()导入JavaScript MLE模块。
·一旦MLE支持除JavaScript以外的更多语言,用一种语言编写的MLE模块就可以由用另一种语言编写的代码导入。
MLE提供DDL命令来管理数据库中的MLE模块(例如,创建、修改、删除)。
18.4MLE模块的创建
MLE模块是使用指定MLE模块的名称和源代码的CREATE MLE MODULE DDL语句在数据库中创建的:
CREATE MLE MODULE scott."jsmodule"
LANGUAGE JAVASCRIPT
AS module.exports.func=function(){...}
CREATE MLE MODULE DDL语句在本文中的其他地方进一步讨论。
每个MLE模块只能包含用单一MLE语言编写的代码。该语言在创建模块时在DDL语句中被指定(例如,上面的DDL语句创建JavaScript模块)。指定的语言应是经由CREATE MLELANGUAGE添加到数据库中的MLE语言之一。
创建的模块的名称可以像上面的例子中那样是完全限定的,即,模式(scott)和创建的模块在模式内的名称("jsmodule")都被限定。如果省略了模式名称,则在当前用户的模式中创建模块。
MLE模块的名称在模式内应当是唯一的。与其他模式对象标识符一样,如果模块名称用双引号括起来,则该模块名称是大小写敏感的。如果省略括起来的双引号,则名称被隐含地转换为大写。
MLE模块的源代码可以使用AS子句内联指定,或者可以从BFILE、BLOB或CLOB获得。
MLE模块可以通过更换来更新。这是通过在模块创建DDL中指定OR REPLACE来完成的,并且具有先前授予的对象权限在更换之后仍然有效的优点。
CREATE OR REPLACE MLE MODULE scott."jsmodule"
LANGUAGE JAVASCRIPT
AS module.exports.bafsfunc=new function(){...}
用户应具有在他们自己的模式中创建MLE模块的CREATE MLE MODULE权限,或者在任意模式中创建MLE模块的CREATE ANY MLE MODULE权限。
18.5MLE模块的结构
MLE模块的结构是语言相关的。对于每种MLE语言,MLE模块对应于该语言的代码“单元”(例如,JavaScript的UMD模块,Python的模块或包)。MLE模块还可以可选地捆绑它所封装的代码单元的一些或全部依赖项。
下面描述JavaScript、Python和Java MLE模块是如何构造的。
18.6JavaScript MLE模块
JavaScript MLE模块是UMD模块,用于用JavaScript编写模块的标准格式。UMD模块通过将函数(或更一般地,将值)分配给module.exports对象的字段来导出所述函数(或更一般地,值)。可以使用Node.js require()函数来导入UMD模块。require()函数评估模块的内容并返回module.exports对象,通过module.exports对象,导入器可以访问由所导入的模块导出的函数。
例如,以下逻辑中的UMD模块导出单个函数squareAndAdd()。
模块文本还定义用于squareAndAdd()的实现的函数square()。然而,该函数不被导出,并且因此本身不能直接从导入该模块的代码中调用。
UMD模块本身可以使用require()来导入其他UMD模块,并且为了正确地工作可能需要依赖项的特定版本(或版本范围)。关于JavaScript模块的所有依赖项的信息,包括名称和版本,通常包含在package.json文件中。这些依赖项可以使用npm install来安装,npminstall读取package.json文件并从包注册表中取回依赖项。
诸如browserify和webpack之类的工具可以用于将UMD模块及其所有依赖项捆绑到单个UMD模块。捆绑的模块导出与原始模块相同的函数集,但是另外内联来自其所有依赖项的代码。关于捆绑的模块的require()语句被移除,对其函数的所有调用都被替换为对其内联代码的调用。
JavaScript MLE模块是可以捆绑它们的一些或全部依赖项的UMD模块。JavaScript MLE模块的未捆绑依赖项(即,通过对部署模块的文本中的require()的调用而加载的任何模块)通过语言模块内导入来满足。
调用规范的SIGNATURE子句可以引用JavaScript MLE模块的导出函数之一。当调用这样的调用规范时,MLE以类似于require()函数的方式加载模块:评估模块的内容,在module.exports对象中查找并调用命名的函数。
18.7Python MLE模块
Python MLE模块包含Python模块或包。模块和包是将代码封装在Python中的标准方式,并且可以由其他Python代码通过导入语句导入。
Python模块是通常包含在单个源文件中的语句的集合。例如,以下逻辑表示定义两个函数的Python模块:
Python模块不会明确地导出函数和值。在Python模块的文本中定义的任何标识符都可由导入它的代码访问。然而,以下划线('_')开始的标识符名称按约定被认为是私有的。模块文本中的所有其他定义构成模块的公共API。当模块被导入时,导入语句返回封装在模块文本中声明的所有值(包括函数)的模块对象。
Python包是进一步组织大型代码库的方式。包可以被认为是文件***中包含Python模块的目录,并且可以包含其他包。例如,上述模块的内容可以分成两个单独的模块(比如说,export.py和helpers.py),并如下放置在目录(比如说,pypackage)中。
该逻辑可以是helpers.py:
def square(val):
return val*val
该逻辑可以是exports.py:
from.import helpers
def squareAndAdd(val1,val2):
return helpers.square(val1)+helpers.square(val2)
包的部件可以被单独导入(例如,导入pypackage.exports),或者包本身可以被导入(导入pypackage)。在后一种情况下,导入语句返回其内容由在包目录层次结构的顶层的文件init.py指定的对象。例如,为了在导入包pypackage时仅使函数squareAndAdd()可用,init.py的内容应当类似如下。
该逻辑可以是init.py:
from.exports import squareAndAdd
Python生态***没有与JavaScript的browserify或webpack的直接对应物。在运行时通过从模块搜索路径搜索并加载模块和包来解析依赖项。通过创建virtualenv,可以实现应用的依赖项的更好封装。virtualenv包括应用程序的所有依赖项,并且virtualenv内的应用程序执行修改模块搜索路径,使得只有安装在virtualenv内的依赖项版本是可见的。要安装在virtualenv中的依赖项版本经由requirements.txt文件,或者替代地与pipenv实用程序相结合的Pipfile来指定。
Python MLE模块是包含Python模块或包,以及安装在virtualenv中的所有或一些依赖项的zip文件。捆绑的依赖项被放置在部署的zip的顶层的.bundleddeps目录中。当执行MLE模块时,捆绑的依赖项被放置在模块搜索路径上。未捆绑的任何依赖项应该通过语言模块内导入来满足。
调用规范的SIGNATURE子句可以引用Python MLE模块中定义的任何函数:
·如果Python MLE模块包含Python模块,则这包括在该模块中定义的所有函数,以及
·如果Python MLE模块包含Python包,则这包括由顶层的包(通过其init.py文件)或由其任何子模块或子包定义的函数。
子模块或子包中的函数可以使用Python的通常的点标记法(例如,上面讨论的示例包pypackage的exports.squareAndAdd)来引用。当调用这样的调用规范时,MLE以类似于Python导入语句的方式加载命名的模块或包,在返回的模块对象中查找命名的函数并调用它。注意,调用规范可能不引用在任何捆绑的依赖项中定义的函数。
18.8Java MLE模块
Java MLE模块包含Java模块。Java模块是更好地封装Java代码的方式。具体地,Java模块可以包含一个或多个Java包。在Java模块中定义的包默认在该模块内部。只有那些明确导出的包(通过在模块的module-info中这样标记它们)才能从模块外部访问。例如,Java模块(比如说,jmodule)可以包含两个包,com.oracle.jmodule.dependencies和com.oracle.jmodule.exports,每个包具有单一的类,如下所示。
该逻辑可以是Helpers.java:
该逻辑可以是Exports.java:
其中,包com.oracle.jmodule.exports可以通过位于该模块的顶层的module-info.java文件导出:
这可以是module-info.java:
module jmodule{
exports com.oracle.jmodule.exports;
}
Java模块可能需要其他Java模块。例如,Java模块(比如说,moduleA)可以通过在其module-info中包括适当的requires指令来要求另一个Java模块(比如说,moduleB):
module moduleA{
requires moduleB;
}
于是,当执行ModuleA时,ModuleB应当存在于模块路径上,从而ModuleA可以访问由ModuleB导出的任何包。
Java MLE模块是包含Java模块以及它所需的一些或全部模块的zip文件。这些捆绑的依赖项被放置在部署的zip的顶层的.bundleddeps目录中,并且在执行MLE模块时被放置在模块路径上。任何未捆绑的所需模块都应当可以通过语言模块内导入获得。
调用规范的SIGNATURE子句可以引用Java MLE模块的导出包中的类的任何公共静态方法。对于上面所示的例子,函数应当通过其完全限定的名称(例如,com.oracle.jmodule.exports.Exports.squareAndAdd)来引用。当调用这样的调用规范时,MLE加载命名的类并调用指定的静态方法。
18.9调用规范的创建
通过为部署的MLE模块导出的函数创建PL/SQL调用规范,可以使导出的函数可供来自PL/SQL和SQL的调用使用。这些MLE函数然后可以从可以调用PL/SQL函数或过程的任何地方(例如,在SQL查询中,从包括匿名块的PL/SQL程序内、作为虚拟列)调用。
让我们再看一下上面描述的部署的模块jsmodule的例子。MLE模块jsmodule导出两个函数:函数doNothing()接受一个输入字符串自变量,不做任何事情,而函数concat()接受两个字符串自变量作为输入,并返回级联的字符串作为结果。
由于doNothing()不返回任何东西,因此不能为其创建PL/SQL函数。相反,创建PL/SQL过程:
CREATE OR REPLACE PROCEDURE
doNothing(str IN VARCHAR2)AS MLE MODULE jsmodule
SIGNATURE'doNothing(str string)';
上述调用规范在当前用户的模式中创建名为doNothing()的PL/SQL过程。执行该函数将执行JavaScript模块jsmodule中的导出函数doNothing()。特定于MLE的子句MLEMODULE<module name>指定导出底层MLE语言函数的MLE模块的名称。SIGNATURE子句指定要调用的导出函数的名称(doNothing()),以及其自变量类型。在SIGNATURE子句中指定的类型是特定于MLE语言的。在JavaScript中实现的MLE函数使用SIGNATURE子句中的TypeScript类型。在这种情况下,该函数接受JavaScript字符串;在调用底层JavaScript实现之前,PL/SQL VARCHAR2字符串被转换为JavaScript字符串。
另一个导出函数concat()可以类似地用于创建PL/SQL函数:
CREATE OR REPLACE FUNCTION concat
RETURN VARCHAR2
AS MLE MODULE jsmodule
SIGNATURE'concat(str1 string,str2 string)';
在这种情况下,调用规范另外指定创建的函数的PL/SQL返回类型。由JavaScript函数concat()返回的(类型为字符串的)值被转换为RDBMS数据类型(VARCHAR2)。所创建的过程和函数可以照常调用:
SQL>CALL doNothing('unused');
SQL>SELECT concat('Hello,','World!')FROM dual;SELECT CONCAT('HELLO','World!')FROM DUAL
------------------------------------------
Hello,World!
18.10对OUT和IN/OUT参数的支持
正如常规PL/SQL函数和存储的过程一样,除IN参数以外,MLE函数还支持IN/OUT和OUT参数。在MLE函数的PL/SQL调用规范中,这些参数照常被声明为IN/OUT和OUT参数。底层MLE语言实现中的这些参数的处理是特定于语言的。
由于JavaScript没有输出参数的概念,因此JavaScript实现改为接受包装参数值的对象。具体地,这些包装器对象的形状由通用接口InOut和Out(分别用于IN/OUT和OUT参数)描述,如下所示。
InOut<T>接口:
interface InOut<T>{
value:T;
}
Out<T>接口:
interface Out<T>{value:T;
}
例如,接受单个VARCHAR2 IN/OUT参数,用Universe替换所有出现的World,并返回原始字符串中World的出现次数的MLE函数:
CREATE OR REPLACE PROCEDURE
substituteWorld(str INOUT VARCHAR2)RETURN NUMBER AS MLE
MODULE inOutParamExample
SIGNATURE'substituteWorld(str InOut<string>)';
底层JavaScript模块栏可以如下实现:
调用规范的SIGNATURE子句将JavaScript函数的参数类型列出为InOut<string>。于是,输入VARCHAR2值被转换为JavaScript字符串,该JavaScript字符串然后被包装在对象中并被传递给JavaScript函数substituteWorld()。
18.11JavaScript MLE模块的调用规范
调用规范的SIGNATURE子句可以引用JavaScript MLE模块的导出函数之一。当调用这样的调用规范时,MLE以类似于require()函数的方式加载模块:评估模块的内容,在module.exports对象中查找并调用命名的函数。
18.12Python MLE模块的调用规范
调用规范的SIGNATURE子句可以引用Python MLE模块中定义的任何函数:
·如果Python MLE模块包含Python模块,则这包括在该模块中定义的所有函数,以及
·如果Python MLE模块包含Python包,则这包括由顶层的包(通过其init.py文件)或由其任何子模块或子包定义的函数。
子模块或子包中的函数可以使用Python的通常的点标记法(例如,上面讨论的示例包pypackage的exports.squareAndAdd)来引用。当调用这样的调用规范时,MLE以类似于Python导入语句的方式加载命名的模块或包,在返回的模块对象中查找命名的函数并调用它。注意,调用规范可能不引用在任何捆绑的依赖项中定义的函数。
18.13Java MLE模块的调用规范
调用规范的SIGNATURE子句可以引用Java MLE模块的导出包中的类的任何公共静态方法。对于上面所示的例子,函数应当通过其完全限定的名称(例如,com.oracle.jmodule.exports.Exports.squareAndAdd)来引用。当调用这样的调用规范时,MLE加载命名的类并调用指定的静态方法。
18.14模块元数据
MLE模块可以以版本字符串和自由形式JSON值元数据的形式携带可选的元数据。这两种元数据都是纯信息性的,并不影响MLE的行为。当创建MLE模块时,可以指定版本字符串:
CREATE MLE MODULE scott."validator"
LANGUAGE JAVASCRIPT
VERSION'10.11.0'
AS module.exports.func=function(){...}
MLE模块的JSON元数据可以使用ALTER MLE MODULE DDL来设定或替换:
ALTER MLE MODULE mymodule SET METADATA
<json-valued-metadata>
MLE不固定JSON元数据字段的特定用法。
18.15MLE调用规范的运行时状态隔离
经由调用规范对MLE函数的PL/SQL调用在执行上下文中执行,所述执行上下文由MLE模块以及由代表其执行该调用的用户确定。在会话中,MLE对从SQL或PL/SQL调用的每个MLE模块使用专用执行上下文。MLE还通过用户分离MLE模块的执行上下文。在会话的持续时间内,代表同一用户对由同一模块导出的MLE函数的所有SQL或PL/SQL调用都在同一执行上下文中执行。当用户在会话中首次调用由模块从SQL或PL/SQL导出的函数时,MLE模块的执行上下文是惰性地创建的。
因此,代表不同用户执行的并具有不同权限级别的MLE模块的运行时状态是完全分离的。另外,从SQL或PL/SQL调用的单独的MLE模块的运行时状态是完全分离的。
这通过具有两个MLE模块,ModuleA和ModuleB的例子来最好地举例说明。ModuleA导出两个函数,funcl()和func2(),而ModuleB导出一个函数,func3()(签名缩写):
从代表User1执行的SQL或PL/SQL对funcl()和func2()的所有调用都使用一个执行上下文,而从User2对相同函数的调用使用单独的执行上下文。同样地,User1对func3()的调用使用与对func1()和func2()的调用分开的执行上下文,因为func3()由不同的MLE模块(ModuleB)导出。
从而,如果对于MLE模块导出的函数的PL/SQL调用规范被声明(例如,DDL)为定义者的权利,则会话中存在用于该模块的一个执行上下文,因为所有的执行都是在定义者的权利下发生的。另一方面,对于作为调用者的权利的调用规范,每个调用用户将有单独的执行上下文。
注意,如果一个MLE模块(比如说,ModuleB)由另一个MLE模块(比如说,ModuleA)导入,则来自ModuleB的代码在与ModuleA相同的执行上下文中执行。在这种情况下,ModuleB的代码被加载到ModuleA的执行上下文中。
18.16MLE模块间导入
MLE模块导出的函数可以使用调用规范从SQL和PL/SQL调用。同时,MLE模块中的功能可以被MLE模块本身之外的其他MLE语言代码重用。现有执行上下文中的MLE语言代码可以使用语言的原生导入机制导入同一语言中的MLE模块的代码。
以下是导出一种函数格式的JavaScript MLE模块scott.hello:
通过使用调用规范,可以从SQL和PL/SQL直接使用MLE模块scott.hello:
CREATE FUNCTION scott.hello_format(name IN VARCHAR2)
RETURNS VARCHAR2 AS MLE MODULE scott."hello"SIGNATURE
'format';
SELECT scott.hello_format('Larry')FROM dual;
该查询返回字符串'Hello,Larry!'。
MLE JavaScript运行时提供熟悉的JavaScript函数require()来导入JavaScriptMLE模块。当执行调用require('hello')时,MLE将导入名称'hello'解析到MLE模块模式对象scott.hello,加载附加到scott.hello的源作为UMD模块并返回结果。
通过使用在本文中其他地方所述的环境机制,导入名称被解析到MLE模块模式对象。同样地,MLE模块scott.hello的功能可以由其他MLE模块使用。这里,MLE模块scott.mymodule中的代码导入scott.hello:
通过使用环境scott.myenv,导入名称'hello'被解析到MLE模块模式对象scott.hello。通过环境的导入名称的解析在本文中其他地方描述。
调用规范scott.print_hello然后可以从PL/SQL调用:
BEGIN
scott.print_hello('Larry');
END;
执行该PL/SQL块产生以下输出:
Hello,Larry!(call spec)
18.17模块导入和执行上下文
当MLE模块的代码被导入时,它在与导入代码相同的执行上下文中运行。在第一种情形下,MLE模块hello导出的函数格式是从SQL调用的。这里,MLE模块hello的代码在专用执行上下文中运行。在第二种情形下,MLE模块hello的代码由MLE模块mymodule导入。这里,模块mymodule导出的函数printHello是从PL/SQL调用的。从而,与REF一致,mymodule在专用执行上下文中执行。另一方面,模块hello从mymodule导入到现有的执行上下文中。
MLE对执行上下文的使用可以总结如下:
·从SQL和PL/SQL对MLE模块导出的函数的调用是在MLE模块和代表其执行该调用的用户的专用执行上下文中执行的。
·在现有执行上下文中由MLE语言代码导入的MLE模块在与导入代码相同的执行上下文中运行。所导入模块中的代码以与导入代码相同的权限运行。
18.18上下文环境
在本示例实现中,环境或上下文环境可以是访客虚拟环境。MLE使用执行上下文来执行MLE语言代码。如前所述,执行上下文既用于执行动态MLE代码段,又用于执行对PL/SQL调用规范的调用。MLE允许经由环境来配置执行上下文的某些性质。执行上下文可被配置成使用特定的环境。然后利用在环境中定义的所有性质建立执行上下文。具体地,环境允许设定语言选项以便定制MLE语言在执行上下文中的运行时,并且使特定MLE模块能够在执行上下文中被导入并管理依赖项。
下面描述如何创建环境以及如何使用环境来定义动态MLE上下文的性质以及MLE模块的执行上下文。还描述了如何使用环境来配置语言选项和启用MLE模块导入。环境是可以自己管理并跨多个执行上下文重用的第一类模式对象。可以使用CREATE MLE ENV DDL语句来创建环境。它可以被创建为新鲜的、空的环境:
CREATE MLE ENV scott."myenv";
或者,环境也可以被创建为现有环境的独立副本。
CREATE MLE ENV scott."myenv"CLONE<other-env>;
注意,当克隆环境时,对原始环境的后续修改不传播到克隆环境。环境的克隆对于创建由MLE提供的默认环境的修改版本是特别有用的。
不能针对现有的执行上下文修改在环境中定义的上下文性质。只有在创建上下文时的环境设定对于执行上下文才是有效的。用于来自SQL或PL/SQL的MLE模块调用的上下文是根据需要隐式地创建的。
18.19默认环境
MLE提供指定执行上下文的默认属性的默认环境对象。如果在MLE模块上没有明确地指定环境,则隐含地使用默认环境。默认环境设定默认语言选项。它还为在本文中别处所述的内置MLE模块提供导入映射。
在数据库层面,使用初始化参数MLE_DEFAULT_ENV来定义默认环境。该参数指定默认环境的模式对象的名称。对默认环境的访问需要被授予给PUBLIC。参数MLE_DEFAULT_ENV可以使用ALTER SESSION SET MLE_DEFAULT_ENV=<...>命令在会话的持续时间内来修改。像任何初始化参数一样,MLE_DEFAULT_ENV的当前有效设定可以使用SHOW PARAMETERS命令或v$parameters视图来获得。除MLE的第一发布之外,未来的发布可以配置例如设定新的语言选项或带来新的内置MLE模块的新的默认环境。然而,这将只提供新的环境对象并更改MLE_DEFAULT_ENV的默认设定。用于以前的默认环境的模式对象将保持不变。现有的MLE模块引用具体的模式对象,不受新的默认环境的影响。
18.20在MLE模块上指定环境
经由调用规范从PL/SQL调用的MLE模块在它自己的执行上下文中执行。当从PL/SQL被调用时,每个MLE模块指定定义执行上下文的性质的环境。然而,注意当MLE模块由其他MLE模块导入时,不使用为该MLE模块定义的环境。
当使用CREATE MLE MODULE DDL语句创建MLE模块时,定义MLE模块的环境:
CREATE MLE MODULE mymodule LANGUAGE JAVASCRIPT ENV scott."myenv"AS...;
如果ENV子句被省略,则使用默认环境。当创建MLE模块时,(明确地或隐含地指定的)环境被存储为模块定义的一部分。如果MLE模块是在没有明确地指定环境的情况下创建的,则在实例或会话层面选择新的默认环境对MLE模块来说是无效的。这允许MLE在未来的发布中提供新的默认环境而不破坏应用代码。现有的MLE模块需要被修改以明确地使用新的环境。可以使用ALTER MLE MODULE命令来更改现有MLE模块对象的环境:
ALTER MLE MODULE mymodule ENV myenv
18.21语言选项
MLE允许通过设定语言选项来定制MLE语言的运行时。例如,语言选项可以启用或禁用未被语言标准覆盖的内置对象(builtins)。它们也可用于选择语言标准的特定版本。MLE语言选项可以直接映射到GraalVM语言选项。然而,MLE只允许被认为是稳定的、面向用户的和受支持的GraalVM语言选项的白名单子集。
经由环境上的语言选项为执行上下文配置语言选项。创建的每个执行上下文设定在其环境中定义的所有语言选项。使用ALTER MLE ENV DDL语句在环境上定义语言选项。例如,可以修改现有环境以启用配置Graal JavaScript语言选项的JavaScript“strict”模式,如下所示:
ALTER MLE ENV scott."myenv"SET LANGUAGE OPTIONS
'js.strict=true';
SET LANGUAGE OPTIONS替换在环境上配置的现有语言选项。可以作为<option-name(选项名称)>=<option-value(选项值)>对的逗号分隔列表,设定多个语言选项。
18.22导入解析
在现有执行上下文中可以导入MLE模块的代码。回到上面的使用JavaScriptrequire()函数导入另一个MLE模块的例子。为了执行对require()的调用,MLE需要将导入名称'hello'解析到模式对象scott.hello。这需要从导入名称到模式对象的映射。
环境将导入名称映射到MLE模块模式对象。环境定义可在使用该环境的执行上下文中导入的MLE模块,以及可以用其导入这些MLE模块的导入名称。具体地,假设环境包含从导入名称'hello'到MLE模块scott.hello的映射。在使用该环境的任何执行上下文中,JavaScript代码可以执行require('hello),并且包含在scott.hello中的UMD模块被加载。可以使用ALTER MLE ENV DDL语句将导入映射添加到环境中。对于上面的例子,导入名称'hello'被添加到上面定义的环境中:
ALTER MLE ENV scott."myenv"
ADD IMPORT hello MODULE scott."hello";
环境中的导入名称必须是唯一的。如果导入名称被添加到已包含该名称的环境中,则抛出错误。环境定义了可以在给定的执行上下文中导入的完整MLE模块集。该环境必须明确地包括所有传递依赖项。
环境将导入名称与实际的MLE模块解耦。通过更新环境,可以将在环境中定义的导入名称重定向到新的MLE模块。这允许引入依赖项的新版本。确保依赖项的新版本与使用环境的代码兼容是环境的所有者的职责。通过使用ALTER MLE ENV命令,导入映射可以从环境中移除,或者被修改为指向不同的MLE模块。
18.23JavaScript的导入名称
JavaScript MLE模块是单个UMD模块。在MLE JavaScript运行时中,环境定义UMD模块的搜索路径:在环境中定义的映射到JavaScript MLE模块(即,UMD模块)的任何导入名称都可以用require解析。例如,在MLE JavaScript运行时中执行require('validator')首先咨询执行上下文的环境,以查找导入名称validator的映射。如果映射涉及JavaScriptMLE模块(例如,scott.validator),则包含在该MLE模块中的UMD模块被检索,由UMD模块加载器加载,并返回结果值。如果导入名称validator的映射不存在或者引用不同MLE语言中的MLE模块,则抛出PL/SQL运行时错误。
18.24Python的模块导入
Python MLE模块是单个Python模块或Python包。在创建执行上下文时,如下使用虚拟环境:对于虚拟环境中引用Python MLE模块的所有映射,按照在映射中使用的导入名称提取代码单元(即,.py模块或.zip压缩包)并将代码单元放置在执行上下文的虚拟文件***中的目录中。随后,用所有这样的目录扩展Python引擎的sys.path搜索路径。从而,Python导入时名称的解析按照基于sys.path的常规Python规则工作。
18.25内置MLE模块
MLE提供内置模块。一个突出的例子是MLE SQL驱动程序。MLE可以采用相同的导入机制,与用户定义的MLE模块类似地处理内置模块。唯一的区别在于内置模块与***模式关联。
18.26创建MLE语言
通过使用CREATE MLE LANGUAGE DDL,可以将新的MLE语言添加到数据库中:
CREATE MLE LANGUAGE[<schema>.]MYLANGUAGE;
添加的语言应该得到包含在数据库中的MLE版本的支持。MLE语言对象在不同的MLE命名空间中创建。在自己的模式中创建新的MLE语言需要CREATE MLE LANGUAGE权限,而在任意模式中创建新的MLE语言需要CREATE ANY MLE LANGUAGE权限。
18.27删除MLE语言
通过使用DROP MLE LANGUAGE DDL,可以从数据库中删除MLE语言:
DROP MLE LANGUAGE[<schema>.]MYLANGUAGE;
在自己的模式中删除MLE语言需要DROP MLE LANGUAGE权限,而在任意模式中删除MLE语言需要DROP ANY MLE LANGUAGE权限。
18.28管理环境
可以使用CREATE MLE ENV DDL语句来创建环境。可以作为新鲜的、空的环境,或者通过克隆现有环境来创建环境。克隆环境创建不受对原始环境的后续改变的影响的独立副本。可以使用DROP MLE ENV DDL语句来删除现有环境,如下所示。
DROP MLE ENV[<schema>.]<name>;
可以使用ALTER MLE ENV DDL语句来修改现有环境。可以添加、移除或改变导入名称的映射。另外,可以设定语言选项。
ADD IMPORT子句添加从导入名称到MLE模块模式对象的新映射。如果环境已包含该导入名称,则抛出错误。
DROP IMPORT子句从环境中移除导入名称。如果环境不包含指定的导入名称,则抛出错误。
ALTER IMPORT修改导入映射,使得导入名称引用不同的MLE模块模式对象。如果环境不包含该导入名称,则抛出错误。
MLE环境上的LANGUAGE OPTIONS子句指定要为使用该环境创建的所有执行上下文设定的语言选项。语言选项是作为由逗号分隔的键值对组成的字符串文字指定的。语言选项只在运行时当使用MLE环境创建执行上下文时才被解析。如果在上下文创建时,语言选项字符串结果是无效的(无效格式、不支持的选项),则抛出错误。
18.29创建MLE模块
使用CREATE MLE MODULE DDL来创建MLE模块:
CREATE[OR REPLACE]MLE MODULE[<module-schema>.]<name>
LANGUAGE[<language-schema>.]<mle-language>[ENV
[<language-schema>.]<mle-env>]
[VERSION'<version-string>']
{USING
{BFILE(<directory object name>,<server file name>)|
{CLOB|BLOB|BFILE}<selection clause>}|
AS<module text>}
CREATE OR REPLACE子句指定应当创建新的MLE模块(CREATE)或替换现有MLE模块(CREATE OR REPLACE)。
如果具有给定名称的MLE模块已经存在,则CREATE MLE MODULE(没有REPLACE子句)抛出错误。通过CREATE OR REPLACE MLE MODULE,如果现有模块存在的话,现有模块被替换,否则创建新的模块。当MLE模块被替换时,不需要重新授予该MLE模块的权限。
用户在他们自己的模式中创建或替换MLE模块需要CREATE MLE MODULE权限,而在其他用户的模式中创建或替换MLE模块则需要CREATE ANY MLE MODULE权限。
要创建的模块的名称可以是完全限定的,即包括模式和创建的模块在该模式内的名称两者。如果模式未被指定,则在当前用户的模式中创建模块。除非用双引号括起来,否则<module-schema>、<name>、<language-schema>和<mle-language>被自动转换为大写。与MLE语言类似,MLE模块在MLE命名空间中创建。
LANGUAGE子句指定所创建模块的MLE语言。指定的语言应当是经由CREATE MLELANGUAGE DDL创建的语言之一。如果使用不支持的MLE语言,则抛出错误。
可选的ENV子句指定所创建模块的MLE环境。如果指定的环境模式对象不存在,则抛出错误。
可选的VERSION子句指定MLE模块的版本字符串。
USING子句使得能够从包含在CLOB、BLOB或BFILE中的代码创建MLE模块。
BFILE子句指定保持要部署的MLE模块的内容的文件的目录(<directory objectname>)和文件名(<server_file_name>)。目录对象应当已经使用例如CREATE DIRECTORY语句创建了。
CLOB|BLOB|BFILE子句指定子查询,该子查询的结果应当是保持要部署的MLE模块的内容的指定类型(CLOB、BLOB或BFILE)的单行和单列。只有当所部署的MLE模块只包含文本数据时,CLOB选项才可用。对于JavaScript,目前支持的唯一MLE语言就是如此,但是对于未来添加的其他MLE语言可能并不是这样。对于包含在BLOB和BFILE中的MLE模块,任何文本数据都假设是在数据库字符集中编码的。
AS子句用于将所部署的MLE模块的内容指定为在DDL语句中内联的字符序列。与CLOB一样,AS子句只有在MLE模块的源只包含文本数据时才可用。字符序列不应封装在引号中。相反,字符序列仅由DDL语句的结尾定界。
通过使用DROP MLE MODULE DDL,删除先前部署的MLE模块:
DROP MLE MODULE[<schema>.]<name>
DROP语句指定要删除的模块的名称以及模式(可选)。如果没有指定模式,则假设当前用户的模式。如果要删除的模块不存在,则DROP MLE MODULE语句引发错误。
通过ALTER MLE MODULE DDL,可分配或改变部署的MLE模块的属性:
ALTER MLE MODULE[<schema>.]<name>SET
{ENV<mle-env>|METADATA<json>}
ALTER MLE MODULE语句指定要改变的模块的名称以及模式(可选)。如果没有指定模式,则假设当前用户的模式。如果模块不存在,或者如果指定了无效的属性,则ALTER MLEMODULE语句引发错误。
SET ENV子句为MLE模块配置新的环境。按照新环境配置随后为MLE模块创建的任何执行上下文。在以下情况下抛出错误:
·如果指定的环境不存在,则抛出错误。
·如果环境不存在于与正被改变的MLE模块相同的模式中,则抛出错误。
18.30MLE调用规范的创建
通过部署的MLE模块导出的函数可以用于创建PL/SQL调用规范,所述PL/SQL调用规范可以从能够调用常规PL/SQL函数和过程的所有地方调用。这些调用规范的创建使用熟悉的CREATE FUNCTION和CREATE PROCEDURE语法,以及一些特定于MLE的元素:
CREATE[OR REPLACE]{FUNCTION|PROCEDURE}
[<schema>.]<call_spec_name>[(param_declaration[,]...)
]
[RETURN datatype]
[{invoker_rights_clause|DETERMINISTIC|
parallel_enable_clause|result_cache_clause}]
{AS|IS}MLE MODULE[<schema>.]<module_name>
SIGNATURE'<function_name_in_module>[(
mle_param_declaration)]';
CREATE FUNCTION和CREATE PROCEDURE语句的大多数组件具有与在创建PL/SQLUDF或存储的过程时它们的对应物相同的语义:
OR REPLACE指定如果函数已经存在,则应当重新创建该函数。该子句可以用于变更现有函数的定义,而不删除、重新创建和重新授予先前对于该函数授予的对象权限。先前对于重新定义的函数/过程被授予权限的用户仍然可以访问该函数,而不需要重新授予权限。
schema指定将包含调用规范的模式。如果模式被省略,则在当前用户的模式中创建调用规范。
call_spec_name指定要创建的调用规范的名称。与使用MLE命名空间的MLE模块和MLE语言不同,调用规范在默认命名空间中创建。
param_declaration指定调用规范的参数。
RETURN datatype只用于UDF,并指定函数的返回值的数据类型。返回值可以具有PL/SQL支持的任何数据类型。只指定数据类型;长度、精度或比例信息应被省略。invoker_rights_clause指定函数是调用者的权利还是定义者的权利。
AUTHID CURRENT_USER创建调用者权利函数,即,该函数以CURRENT_USER的权限执行。
AUTHID DEFINER创建定义者权利函数,即,函数/过程以该函数/过程所驻留于的模式的所有者的权限执行,并且外部名称在该模式中解析。这是默认的。
DETERMINISTIC只用于UDF,并指示每当用其参数的相同值调用该函数时,该函数都返回相同的结果值。与PL/SQL函数一样,该子句不应当用于以可能影响函数的返回结果的任何方式访问数据库的函数。如果数据库选择不重新执行该函数,则这样做的结果将不会被捕捉。
parallel_enable_clause只用于UDF,并且是指示该函数可以从并行查询操作的并行执行服务器执行的优化提示。
MLE MODULE和SIGNATURE子句是特定于MLE的,如下所示。MLE MODULE子句指定为调用规范导出底层MLE语言函数的已部署MLE模块。提供的<module_name>是导出在SIGNATURE子句中指定的MLE语言函数的已部署MLE模块的名称,并且可以是也可以不是完全限定的。指定的模块应当始终在与正在创建的调用规范相同的模式中。如果指定的MLE模块不存在或者在与所创建的调用规范不同的模式中,则抛出错误。
SIGNATURE子句包含将由该调用规范创建的MLE函数映射到由指定的MLE模块导出的特定函数所需的所有信息。特别地,它包括三条信息:
·function_name_in_module指定MLE模块中的导出函数的名称
·mle_param_declaration指定函数的MLE语言参数类型(与PL/SQL参数类型相反)(可选)
·function_name_in_module可以包括任何字母数字字符以及下划线('_')和句号('.')。
注意,当MLE函数首次被执行时,惰性地发生SIGNATURE子句的语法分析和解析。只有在此时才报告SIGNATURE子句中的任何解析或语法错误,而不是在创建调用规范时。
mle_param_declaration具有以下形式:
mle_param_declaration::=[<argument_name>
<MLE-language-type>[,]...]
MLE-language-type可以是MLE语言的内置类型(例如,JavaScript的字符串或数字)或MLE提供的类型(例如,OracleNumber或OracleDate)。
mle_param_declaration可以从SIGNATURE子句中完全省略。在这种情况下,使用默认的PL/SQL-MLE语言类型映射。用于指定SIGNATURE子句的编码应当与数据库字符集相同。
19.0数据库概述
本发明的实施例用于数据库管理***(DBMS)的上下文中。于是,提供示例DBMS的描述。
通常,诸如数据库服务器之类的服务器是集成软件组件和用于执行集成软件组件的计算资源(比如存储器、节点及节点上的进程)的分配的组合,其中软件和计算资源的组合专用于代表服务器的客户端提供特定类型的功能。数据库服务器管理和便利对特定数据库的访问,处理客户端访问数据库的请求。
通过向数据库服务器提交使数据库服务器对存储在数据库中的数据进行操作的命令,用户与DBMS的数据库服务器进行交互。用户可以是在与数据库服务器进行交互的客户端计算机上运行的一个或多个应用。本文中,多个用户也可以被统称为用户。
数据库包含存储在持久性存储机构,比如一组硬盘上的数据和数据库字典。数据库由它自己的独立数据库字典定义。数据库字典包括定义包含在数据库中的数据库对象的元数据。实际上,数据库字典定义数据库的大部分。数据库对象包括表、表列和表空间。表空间是用于存储各种类型的数据库对象(比如表)的数据的一组一个或多个文件。如果数据库对象的数据存储在表空间中,则数据库字典将数据库对象映射到保持数据库对象的数据的一个或多个表空间。
DBMS参考数据库字典,以确定如何执行提交给DBMS的数据库命令。数据库命令可以访问由字典定义的数据库对象。
数据库命令可以是数据库语句的形式。为了让数据库服务器处理数据库语句,数据库语句必须符合数据库服务器所支持的数据库语言。许多数据库服务器支持的数据库语言的一个非限制性例子是SQL,包括由诸如Oracle之类的数据库服务器(例如OracleDatabase 11g)支持的专有形式的SQL。SQL数据定义语言(“DDL”)指令被发送到数据库服务器,以创建或配置数据库对象,比如表、视图或复杂类型。数据操纵语言(“DML”)指令被发送到DBMS,以管理存储在数据库结构内的数据。例如,SELECT、INSERT、UPDATE和DELETE是存在于一些SQL实现中的DML指令的常见例子。SQL/XML是当在对象关系数据库中操纵XML数据时使用的SQL的常见扩展。
多节点数据库管理***由共享对同一数据库的访问的互连节点组成。一般,节点经由网络互连,并且程度不同地共享对共享存储装置的访问,例如共享对一组盘驱动器和存储在其上的数据块的访问。多节点数据库***中的节点可以为经由网络互连的一组计算机(例如工作站、个人计算机)的形式。或者,节点可以是网格的节点,所述网格由为与机架上的其他服务器刀片互连的服务器刀片形式的节点组成。
多节点数据库***中的每个节点托管数据库服务器。诸如数据库服务器之类的服务器是集成软件组件和用于在处理器上执行集成软件组件的计算资源(比如存储器、节点及节点上的进程)的分配的组合,软件和计算资源的组合专用于代表一个或多个客户端进行特定功能。
可以分配来自多节点数据库***中的多个节点的资源,以运行特定的数据库服务器的软件。软件和来自节点的资源的分配的每种组合是本文中称为“服务器实例”或“实例”的服务器。数据库服务器可以包含多个数据库实例,其中的一些或全部运行在独立的计算机(包括独立的服务器刀片)上。
19.1查询处理
查询是当被执行时,使服务器对一组数据进行一个或多个操作的表达式、命令或命令集。查询可以指定要从其确定(一个或多个)结果集的(一个或多个)源数据对象,比如(一个或多个)表、(一个或多个)列、(一个或多个)视图或(一个或多个)快照。例如,(一个或多个)源数据对象可以出现在结构化查询语言(“SQL”)查询的FROM子句中。SQL是用于查询数据库对象的公知示例语言。本文中使用的术语“查询”用于指代表示查询的任何形式,包括数据库语句形式的查询和用于内部查询表示的任何数据结构。术语“表”指的是由查询引用或定义并表示一组行的任何源对象,比如数据库表格、视图、或内联查询块,比如内联视图或子查询。
查询可以在(一个或多个)对象被加载时,逐行地对来自(一个或多个)源数据对象的数据进行操作,或者在(一个或多个)对象被加载之后对(一个或多个)整个源数据对象进行操作。通过某个或某些操作产生的结果集可以供(一个或多个)其他操作使用,并且以这种方式,结果集可基于某些标准被过滤掉或缩小,和/或与(一个或多个)其他结果集和/或(一个或多个)其他源数据对象结合或组合。
子查询是查询的一部分或组件,所述一部分或组件与该查询的其他(一个或多个)部分或(一个或多个)组件不同,并且可以与该查询的(一个或多个)其他部分或(一个或多个)组件分开地(即,作为单独的查询)进行评估。查询的(一个或多个)其他部分或(一个或多个)组件可以形成外部查询,该外部查询可以包括也可以不包括其他子查询。在针对外部查询计算结果时,嵌套在外部查询中的子查询可以被单独地评估一次或多次,同时为外部查询计算结果。
通常,查询分析器接收查询语句并生成查询语句的内部查询表示。一般,内部查询表示是表示查询语句的各个组件和结构的一组互连数据结构。
内部查询表示可以是节点图的形式,每个互接的数据结构对应于节点,并且对应于所表示的查询语句的组件。内部表示通常在存储器中生成,用于评估、操纵和变换。
硬件概述
按照一个实施例,本文中所述的技术由一个或多个专用计算设备实现。所述专用计算设备可被硬连线以实现所述技术,或者可包括被永久编程以实现所述技术的数字电子设备,比如一个或多个专用集成电路(ASIC)或现场可编程门阵列(FPGA),或者可包括被编程为按照固件、存储器、其他存储装置或它们的组合中的程序指令实现所述技术的一个或多个通用硬件处理器。这样的专用计算设备还可以将定制的硬连线逻辑、ASIC或FPGA与定制的编程相结合,以实现所述技术。所述专用计算设备可以是桌上型计算机***、便携式计算机***、手持设备、连网设备、或者包含硬连线和/或程序逻辑,以实现所述技术的任何其他设备。
例如,图18是图解说明可在其上实现本发明的实施例的计算机***1800的框图。计算机***1800包括总线1802或用于传送信息的其他通信机构,以及与总线1802耦接,用于处理信息的硬件处理器1804。例如,硬件处理器1804可以是通用微处理器。
计算机***1800还包括耦接到总线1802,用于存储信息和由处理器1804执行的指令的主存储器1806,比如随机存取存储器(RAM)或其他动态存储设备。主存储器1806还可以用于在由处理器1804执行的指令的执行期间,存储临时变量或其他中间信息。当被存储在处理器1804可访问的非临时性存储介质中时,这种指令使计算机***1800变成为进行在指令中指定的操作而定制的专用机器。
计算机***1800还包括耦接到总线1802,用于为处理器1804存储静态信息和指令的只读存储器(ROM)1808或其他静态存储设备。诸如磁盘、光盘或固态驱动器之类的存储设备1810被设置,并耦接到总线1802,用于存储信息和指令。
计算机***1800可经由总线1802耦接到显示器1812,比如阴极射线管(CRT),以便向计算机用户显示信息。包括字母数字键和其他键的输入设备1814耦接到总线1802,以便把信息和命令选择传送给处理器1804。另一种用户输入设备是光标控制器1816,比如鼠标、跟踪球或光标方向键,以向处理器1804传送方向信息和命令选择,和控制显示器1812上的光标移动。这种输入设备一般具有使该设备可以指定平面中的位置的两个轴,即第一轴(例如x)和第二轴(例如y)上的两个自由度。
计算机***1800可利用与计算机***结合,使计算机***1800成为或者把计算机***1800编程为专用机器的定制硬连线逻辑、一个或多个ASIC或FPGA、固件和/或程序逻辑来实现本文中所述的技术。按照一个实施例,响应处理器1804执行包含在主存储器1806中的一个或多个指令的一个或多个序列,计算机***1800执行本文中的技术。这种指令可从其他存储介质,比如存储设备1810读入到主存储器1806中。包含在主存储器1806中的指令序列的执行使处理器1804进行本文中所述的处理步骤。在备选实施例中,代替软件指令或者与软件指令结合,可以使用硬连线电路。
本文中使用的术语“存储介质”指的是存储使机器以特定方式工作的数据和/或指令的任何非临时性介质。这种存储介质可包含非易失性介质和/或易失性介质。例如,非易失性介质包括光盘、磁盘或固态驱动器,比如存储设备1810。易失性介质包括动态存储器,比如主存储器1806。例如,存储介质的常见形式包括软盘、柔性盘、硬盘、固态驱动器、磁带、或者任何其他磁数据存储介质、CD-ROM、任何其他光数据存储介质、具有各种小孔图案的任何物理介质、RAM、PROM、EPROM、FLASH-EPROM、NVRAM、任何其他存储芯片或盒式存储器。
存储介质不同于传输介质,不过可以与传输介质结合使用。传输介质参与在存储介质之间传送信息。例如,传输介质包括同轴电缆、铜线和光纤,包括构成总线1802的导线。传输介质还可以采取声波或光波,比如在无线电波和红外数据通信期间生成的声波或光波的形式。
在将一个或多个指令的一个或多个序列传送给处理器1804以便执行时,可能涉及到各种形式的介质。例如,指令最初可以携带在远程计算机的磁盘或固态驱动器上。远程计算机可把指令载入其动态存储器中,并利用调制解调器,通过电话线路发送所述指令。计算机***1800本地的调制解调器可在电话线路上接收所述数据,并使用红外发射器把数据转换成红外信号。红外探测器可接收携带在红外信号中的数据,适当的电路可把所述数据放在总线1802上。总线1802把所述数据运送到主存储器1806,处理器1804从主存储器1806取回并执行指令。主存储器1806接收的指令可在由处理器1804执行之前或之后,视情况存储在存储设备1810上。
计算机***1800还包括耦接到总线1802的通信接口1818。通信接口1818提供耦接到网络链路1820的双向数据通信,网络链路1820连接到本地网络1822。例如,通信接口1818可以是综合业务数字网(ISDN)卡、线缆调制解调器、卫星调制解调器、或者提供与对应类型的电话线路的数据通信连接的调制解调器。再例如,通信接口1818可以是提供与兼容LAN的数据通信连接的局域网(LAN)卡。也可以实现无线链路。在任意这样的实现中,通信接口1818发送和接收携带表示各种信息的数字数据流的电信号、电磁信号或光信号。
网络链路1820一般提供通过一个或多个网络,到其他数据设备的数据通信。例如,网络链路1820可提供通过本地网络1822,到主计算机1824或者到由因特网服务提供商(ISP)1826操作的数据设备的连接。ISP1826又通过现在通常称为“因特网”1828的全球分组数据通信网络,提供数据通信服务。本地网络1822和因特网1828都使用携带数字数据流的电信号、电磁信号或光信号。通过各种网络的信号,和在网络链路1820上并通过通信接口1818的往来于计算机***1800运送数字数据的信号是传输介质的示例形式。
计算机***1800可通过(一个或多个)网络、网络链路1820和通信接口1818,发送消息和接收数据,包括程序代码。在因特网例子中,服务器1830可通过因特网1828、ISP1826、本地网络1822和通信接口1818,传送所请求的应用程序的代码。
接收的代码可在被接收时由处理器1804执行,和/或被存储在存储设备1810或者其他非易失性存储装置中供以后执行。
软件概述
图19是可用于控制计算***1800的操作的基本软件***1900的框图。软件***1900及其组件(包括它们的连接、关系和功能)仅仅是示例性的,而不是要限制(一个或多个)示例实施例的实现。适合于实现(一个或多个)示例实施例的其他软件***可以具有不同的组件,包括具有不同的连接、关系和功能的组件。
软件***1900是为指导计算***1800的操作而提供的。可以存储在***存储器(RAM)1806中和存储在固定存储装置(例如,硬盘或闪存)1810上的软件***1900包括内核或操作***(OS)1910。
OS 1910管理计算机操作的低级方面,包括管理进程的执行、存储器分配、文件输入和输出(I/O)以及设备I/O。表示为1902A、1902B、1902C...1902N的一个或多个应用程序可以被“加载”(例如,从固定存储装置1810转移到存储器1806中)以便由***1900执行。打算在计算机***1800上使用的应用或其他软件也可以被存储为一组可下载的计算机可执行指令,例如,用于从因特网位置(例如,Web服务器、app商店或其他在线服务)下载和安装。
软件***1900包括图形用户界面(GUI)1915,用于以图形方式(例如,“点击”或“触摸手势”)接收用户命令和数据。***1900又可以按照来自操作***1910和/或(一个或多个)应用1902的指令作用于这些输入。GUI 1915还用于显示来自OS 1910和(一个或多个)应用1902的操作结果,用户可以对操作结果提供额外的输入或终止会话(例如,注销)。
OS 1910可以直接在计算机***1800的裸硬件1920(例如,(一个或多个)处理器1804)上执行。或者,可以将管理程序或虚拟机监视器(VMM)1930置于裸硬件1920和OS 1910之间。在这种配置中,VMM1930充当OS 1910和计算机***1800的裸硬件1920之间的软件“缓冲垫”或虚拟化层。
VMM 1930实例化并运行一个或多个虚拟机实例(“访客机器”)。每个访客机器包括“访客”操作***,比如OS 1910,以及设计成在访客操作***上执行的一个或多个应用,比如(一个或多个)应用1902。VMM1930向访客操作***呈现虚拟操作平台,并管理访客操作***的执行。
在一些情况下,VMM 1930可以允许访客操作***像直接运行在计算机***1900的裸硬件1920上一样地运行。在这些情况下,配置成直接在裸硬件1920上执行的访客操作***的相同版本也可以在VMM 1930上执行,而无需修改或重新配置。换句话说,在一些情况下,VMM 1930可以向访客操作***提供完全的硬件和CPU虚拟化。
在其他情况下,考虑到效率,访客操作***可以被专门设计或配置成在VMM 1930上执行。在这些情况下,访客操作***“知晓”它在虚拟机监视器上执行。换句话说,在一些情况下,VMM 1930可以向访客操作***提供半虚拟化。
计算机***进程包括硬件处理器时间的分配,以及(物理和/或虚拟)存储器的分配,存储器的分配用于存储由所述硬件处理器执行的指令,用于存储由执行所述指令的所述硬件处理器生成的数据,和/或用于在计算机***进程不运行时,在硬件处理器时间的分配之间存储硬件处理器状态(例如,寄存器的内容)。计算机***进程在操作***的控制下运行,并且可以在正在计算机***上执行的其他程序的控制下运行。
云计算
术语“云计算”在本文中通常用于描述计算模型,所述计算模型使得能够按需访问诸如计算机网络、服务器、软件应用和服务之类的计算资源共享池,并且允许以最小的管理工作量或服务提供商交互来快速提供和释放资源。
云计算环境(有时称为云环境或云)可以以各种不同的方式实现,以最佳地适应不同的需求。例如,在公有云环境中,底层计算基础设施由使其他组织或公众可以获得其云服务的组织拥有。相反,私有云环境通常仅供单个组织使用或在单个组织内部使用。社区云用于由社区内的几个组织共享;而混合云包括通过数据和应用可移植性绑定在一起的两种或更多种类型的云(例如私有云、社区云或公有云)。
通常,云计算模型使以前可能由组织自己的信息技术部门提供的那些职责中的一些职责可以改为在云环境内作为服务层来交付,以供(按照云的公有/私有性质,在组织内部或组织外部的)消费者使用。取决于具体实现,由每个云服务层或在每个云服务层内提供的组件或特征的精确定义可能有所不同,不过常见的例子包括:软件即服务(SaaS),其中消费者使用运行在云基础设施上的软件应用,而SaaS提供商管理或控制底层云基础设施和应用。平台即服务(PaaS),其中消费者可以使用PaaS提供商所支持的软件编程语言和开发工具来开发、部署和以其他方式控制他们自己的应用,而PaaS提供商管理或控制云环境的其他方面(即,运行时执行环境以下的一切)。基础设施即服务(IaaS),其中消费者可以部署和运行任意软件应用,和/或提供处理、存储、网络和其他基本计算资源,而IaaS提供商管理或控制底层物理云基础设施(即,操作***层以下的一切)。数据库即服务(DBaaS),其中消费者使用运行在云基础设施上的数据库服务器或数据库管理***,而DBaaS提供商管理或控制底层云基础设施和应用。
上述基本计算机硬件和软件以及云计算环境是为了举例说明可用于实现(一个或多个)示例实施例的基本底层计算机组件而给出的。然而,(一个或多个)示例实施例不一定局限于任何特定的计算环境或计算设备配置。相反,(一个或多个)示例实施例可以在鉴于本公开,本领域技术人员会理解为能够支持在本文中给出的(一个或多个)示例实施例的特征和功能的任何类型的***体系结构或处理环境中实现。
在上面的说明书中,参考了可能因实现而异的众多具体细节描述了本发明的实施例。因而,说明书和附图应被认为是例证性的而不是限制性的。本发明范围,以及申请人拟作为本发明范围的内容的唯一且排他的指示物是从本申请提出的一组权利要求在提出这些权利要求的具体形式方面的字面上的等同范围,包括任何后续修正。
Claims (20)
1.一种方法,包括:
将访客编程语言的实现***到数据库管理***(DBMS)的部署中;
执行数据定义语言(DDL)语句以在DBMS中注册访客编程语言;
执行在DBMS中调用访客编程语言的数据操纵语言(DML)语句。
2.按照权利要求1所述的方法,其中:
所述DDL语句包含访客编程语言的名称;
所述在DBMS中注册访客编程语言包括在DBMS的数据库字典中,将访客编程语言的名称绑定到访客编程语言的所述实现。
3.按照权利要求1所述的方法,其中所述在DBMS调用中访客编程语言包括调用在DBMS的数据库字典中定义的存储的过程和/或用户定义函数(UDF)。
4.按照权利要求1所述的方法,其中访客编程语言的实现包括对于访客编程语言包含解析器或语法的至少一个文件。
5.按照权利要求1所述的方法,其中所述执行DDL语句导致将访客编程语言的实现***到所述部署中。
6.按照权利要求1所述的方法,其中:
访客编程语言的所述实现包括至少一个文件;
所述方法还包括从远程客户端计算机接收DDL语句;
自动执行DDL语句包括将所述至少一个文件从远程客户端计算机上传到DBMS。
7.按照权利要求1所述的方法,其中所述在DBMS中调用访客编程语言包括:a)Futamura投影,b)小于整个子例程的即时编译(JIT),和/或c)生成具有一个或多个去优化点的推测代码。
8.一种方法,包括:
执行单个数据定义语言(DDL)语句,以在数据库管理***(DBMS)中为访客编程语言定义多个子例程;
执行第二DDL语句,以在DBMS中将所述多个子例程中的特定子例程注册为用户定义函数(UDF)或存储的过程;
执行数据操纵语言(DML)语句,以在DBMS中调用所述特定子例程。
9.按照权利要求8所述的方法,其中:
为访客编程语言定义所述多个子例程的所述单个DDL语句包括访客编程语言的名称;
执行所述单个DDL语句以定义所述多个子例程包括在DBMS的数据库字典中解析访客编程语言的名称。
10.按照权利要求8所述的方法,其中:
定义所述多个子例程的所述单个DDL语句包括新的访客模块的名称;
执行所述单个DDL语句以定义所述多个子例程包括:
生成所述新的访客模块;以及
在DBMS的数据库字典中,将所述名称绑定到所述新的访客模块。
11.按照权利要求10所述的方法,还包括执行数据控制语言(DCL)语句,以准许访问所述新的访客模块。
12.按照权利要求8所述的方法,还包括执行第三单个DDL语句,以替换DBMS中的访客编程语言的所述多个子例程。
13.按照权利要求8所述的方法,其中:
注册所述特定子例程的所述第二DDL语句包括在所述特定子例程的稍后调用期间要切换到的用户账户的指定;
所述用户账户包括执行所述单个DDL语句以定义所述多个子例程的用户账户。
14.按照权利要求8所述的方法,其中注册所述特定子例程的所述第二DDL语句对于所述特定子例程包括:自变量类型、自变量方向、幂等性的指示和/或线程安全性的指示。
15.按照权利要求14所述的方法,其中:
所述自变量方向至少包括OUT;
访客编程语言原生不支持所述自变量方向。
16.按照权利要求14所述的方法,其中所述注册所述特定子例程包括生成从所述特定子例程的所述自变量类型到原生于所述DML的数据类型的映射。
17.一种或多种存储指令的非临时性计算机可读介质,所述指令当由一个或多个处理器执行时,导致:
将访客编程语言的实现***到数据库管理***(DBMS)的部署中;
执行数据定义语言(DDL)语句以在DBMS中注册访客编程语言;
执行在DBMS中调用访客编程语言的数据操纵语言(DML)语句。
18.一种或多种存储指令的非临时性计算机可读介质,所述指令当由一个或多个处理器执行时,导致:
执行单个数据定义语言(DDL)语句,以在数据库管理***(DBMS)中为访客编程语言定义多个子例程;
执行第二DDL语句,以在DBMS中将所述多个子例程中的特定子例程注册为用户定义函数(UDF)或存储的过程;
执行数据操纵语言(DML)语句,以在DBMS中调用所述特定子例程。
19.按照权利要求18所述的一种或多种非临时性计算机可读介质,其中:
定义所述多个子例程的所述单个DDL语句包括新的访客模块的名称;
所述执行所述单个DDL语句以定义所述多个子例程包括:
生成所述新的访客模块;以及
在DBMS的数据库字典中,将所述名称绑定到所述新的访客模块。
20.按照权利要求18所述的一种或多种非临时性计算机可读介质,其中注册所述特定子例程的所述第二DDL语句对于所述特定子例程包括:自变量类型、自变量方向、幂等性的指示和/或线程安全性的指示。
Applications Claiming Priority (3)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
US16/556,847 | 2019-08-30 | ||
US16/556,847 US11531652B2 (en) | 2019-08-30 | 2019-08-30 | Database modularization of pluggable guest languages |
PCT/US2020/045898 WO2021041032A1 (en) | 2019-08-30 | 2020-08-12 | Database modularization of pluggable guest languages |
Publications (1)
Publication Number | Publication Date |
---|---|
CN114341831A true CN114341831A (zh) | 2022-04-12 |
Family
ID=72235004
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202080060981.2A Pending CN114341831A (zh) | 2019-08-30 | 2020-08-12 | 可插拔访客语言的数据库模块化 |
Country Status (3)
Country | Link |
---|---|
US (1) | US11531652B2 (zh) |
CN (1) | CN114341831A (zh) |
WO (1) | WO2021041032A1 (zh) |
Families Citing this family (13)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US11461324B2 (en) | 2019-08-29 | 2022-10-04 | Oracle International Corporation | First futamura projection in the context of SQL expression evaluation |
US11294894B2 (en) | 2019-08-30 | 2022-04-05 | Oracle International Corporation | Dynamic resolution of dependencies for database guest languages |
US11531652B2 (en) | 2019-08-30 | 2022-12-20 | Oracle International Corporation | Database modularization of pluggable guest languages |
US11361026B2 (en) | 2020-06-30 | 2022-06-14 | Snowflake Inc. | Accessing files in a database stage using a user defined function |
US10997243B1 (en) | 2020-06-30 | 2021-05-04 | Snowflake Inc. | Supporting unstructured, semi-structured, and structured files |
US20220237503A1 (en) * | 2021-01-26 | 2022-07-28 | International Business Machines Corporation | Machine learning model deployment within a database management system |
US11645243B2 (en) * | 2021-06-07 | 2023-05-09 | Snowflake Inc. | Accessing files in a database stage using a user defined function |
US20230012013A1 (en) * | 2021-07-08 | 2023-01-12 | Data I/O Corporation | Secure device programming system with hardware security module and security interop layer |
US11726894B2 (en) * | 2021-08-12 | 2023-08-15 | Sap Se | Runtime entropy-based software operators |
CN113742316A (zh) * | 2021-09-08 | 2021-12-03 | 辽宁振兴银行股份有限公司 | 一种批量执行sql语句同步Mysql数据库的装置及方法 |
CN113849156B (zh) * | 2021-09-17 | 2022-06-28 | 中国科学院软件研究所 | OpenHarmony操作***应用的无代码智能开发***及其使用方法 |
WO2023249775A1 (en) * | 2022-06-22 | 2023-12-28 | Microsoft Technology Licensing, Llc | System and method for scalable data processing operations |
US11829359B1 (en) | 2022-07-29 | 2023-11-28 | Microsoft Technology Licensing, Llc | System and method for scalable data processing operations |
Family Cites Families (33)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US4930071A (en) | 1987-06-19 | 1990-05-29 | Intellicorp, Inc. | Method for integrating a knowledge-based system with an arbitrary database system |
JPH01162979A (ja) * | 1987-12-19 | 1989-06-27 | Ricoh Co Ltd | データベース管理システムの機能拡張装置 |
US5761493A (en) * | 1990-04-30 | 1998-06-02 | Texas Instruments Incorporated | Apparatus and method for adding an associative query capability to a programming language |
EP0534466B1 (en) * | 1991-09-27 | 2002-04-10 | BMC Software, Inc. | Change definition language for computer database system |
JP3510042B2 (ja) * | 1996-04-26 | 2004-03-22 | 株式会社日立製作所 | データベース管理方法及びシステム |
US5893104A (en) * | 1996-07-09 | 1999-04-06 | Oracle Corporation | Method and system for processing queries in a database system using index structures that are not native to the database system |
US5987463A (en) * | 1997-06-23 | 1999-11-16 | Oracle Corporation | Apparatus and method for calling external routines in a database system |
US6236997B1 (en) * | 1997-06-23 | 2001-05-22 | Oracle Corporation | Apparatus and method for accessing foreign databases in a heterogeneous database system |
US5995974A (en) * | 1997-08-27 | 1999-11-30 | Informix Software, Inc. | Database server for handling a plurality of user defined routines (UDRs) expressed in a plurality of computer languages |
US6360228B1 (en) * | 1999-06-02 | 2002-03-19 | Oracle Corporation | Transactional framework for executing statements involving non-native code |
US7206805B1 (en) * | 1999-09-09 | 2007-04-17 | Oracle International Corporation | Asynchronous transcription object management system |
US6725213B1 (en) * | 1999-10-29 | 2004-04-20 | Oracle International Corporation | Method and mechanism for providing external procedures to a database system |
US7047252B2 (en) * | 2003-12-02 | 2006-05-16 | Oracle International Corporation | Complex computation across heterogenous computer systems |
US6976029B2 (en) * | 2004-02-10 | 2005-12-13 | Microsoft Corporation | System and method for providing user defined types in a database system |
US20070038662A1 (en) * | 2005-08-04 | 2007-02-15 | Peter Bendel | Method and system for managing external routines in a database management system |
JP2007249785A (ja) * | 2006-03-17 | 2007-09-27 | Fujitsu Ltd | コンパイルプログラム、仮想データベースリモートアクセス用プログラムの製造方法、及び仮想データベースのリモートアクセス方法 |
US7953674B2 (en) * | 2007-05-17 | 2011-05-31 | Microsoft Corporation | Fuzzing system and method for exhaustive security fuzzing within an SQL server |
US11036565B2 (en) * | 2008-06-09 | 2021-06-15 | Rex Young | Service virtual machine |
US8793240B2 (en) | 2011-08-26 | 2014-07-29 | Oracle International Corporation | Generation of machine code for a database statement by specialization of interpreter code |
US8943290B2 (en) | 2012-03-27 | 2015-01-27 | Oracle International Corporation | Automatic management of heterogeneous memory resources |
US9135293B1 (en) | 2013-05-20 | 2015-09-15 | Symantec Corporation | Determining model information of devices based on network device identifiers |
US11556396B2 (en) * | 2015-05-08 | 2023-01-17 | Seth Lytle | Structure linked native query database management system and methods |
GB201517003D0 (en) * | 2015-09-25 | 2015-11-11 | Ibm | Secure invocation of a stored procedures in a dbms |
US10339137B2 (en) | 2015-12-07 | 2019-07-02 | Futurewei Technologies, Inc. | System and method for caching and parameterizing IR |
US10061872B1 (en) | 2016-09-01 | 2018-08-28 | Bentley Systems, Incorporated | Techniques for suppressing unwanted clashes |
US10013275B2 (en) * | 2016-11-17 | 2018-07-03 | Red Hat, Inc. | Executing code referenced from a microservice registry |
US20180189328A1 (en) * | 2016-12-30 | 2018-07-05 | Teradata Us, Inc. | Method and system for providing data access and local processing across disparate data systems |
US11360976B2 (en) | 2017-08-31 | 2022-06-14 | Oracle International Corporation | Deployment of javascript and typescript stored procedures and user-defined functions into database management systems |
US10120926B1 (en) | 2018-05-31 | 2018-11-06 | Capital One Services, Llc | Attribute sharing platform for data processing systems |
US10877737B2 (en) * | 2018-12-26 | 2020-12-29 | Paypal, Inc. | Automatic translation of computer code |
US11461324B2 (en) | 2019-08-29 | 2022-10-04 | Oracle International Corporation | First futamura projection in the context of SQL expression evaluation |
US11531652B2 (en) | 2019-08-30 | 2022-12-20 | Oracle International Corporation | Database modularization of pluggable guest languages |
US10983815B1 (en) * | 2019-10-31 | 2021-04-20 | Jpmorgan Chase Bank, N.A. | System and method for implementing a generic parser module |
-
2019
- 2019-08-30 US US16/556,847 patent/US11531652B2/en active Active
-
2020
- 2020-08-12 CN CN202080060981.2A patent/CN114341831A/zh active Pending
- 2020-08-12 WO PCT/US2020/045898 patent/WO2021041032A1/en active Application Filing
Also Published As
Publication number | Publication date |
---|---|
US20210064588A1 (en) | 2021-03-04 |
WO2021041032A1 (en) | 2021-03-04 |
US11531652B2 (en) | 2022-12-20 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US11531652B2 (en) | Database modularization of pluggable guest languages | |
US11360976B2 (en) | Deployment of javascript and typescript stored procedures and user-defined functions into database management systems | |
US11385889B2 (en) | Inferring intra package and module dependencies | |
US8863082B2 (en) | Transformational context-aware data source management | |
CN114286994A (zh) | 数据库访客语言的依赖性的动态解析 | |
KR20060097577A (ko) | 시스템 데이터 인터페이스, 관련 아키텍처, 프린트 시스템데이터 인터페이스 및 관련 프린트 시스템 아키텍처 | |
CN114258539A (zh) | 用于客人语言的数据库环境 | |
US10303449B2 (en) | Compiling non-native constants | |
MacDonald et al. | Pro Asp. net 2.0 in C# 2005 | |
Ward et al. | The Integrated Rule-Oriented Data System (iRODS 3.0) Micro-Service Workbook | |
JP5108309B2 (ja) | ユーザ定義タイプの継承をサポートするためのシステムおよび方法 | |
US20240126727A1 (en) | Techniques for comprehensively supporting json schema in a rdbms | |
US20240126726A1 (en) | Techniques for comprehensively supporting json schema in a rdbms | |
Wang | Jsoniq and rumbledb on snowflake | |
van Rossum | Python Setup and Usage | |
Cosmina et al. | Spring Data Access with JDBC | |
MacDonald | Pro ASP. NET 1.1 in C#: From professional to expert | |
Meneni | Using Shared Memory as a Means to Provide Data Concurrency Across Vm’s in a Cloud Architecture | |
Villela et al. | About Static. NET Assembly | |
MacLean et al. | Exploring Android Persistence and Content Providers | |
Martí Fraiz | dataClay: next generation object storage | |
Pulakhandam et al. | ODP. NET Developers Guide: Oracle Database 10g Development with Visual Studio 2005 and the Oracle Data Provider for. NET | |
Saur | Dynamic upgrades for high availability systems | |
Alpern et al. | Oracle Database Application Developer's Guide-Fundamentals, 10g Release 1 (10.1) Part No. B10795-01 Copyright© 1996, 2003 Oracle Corporation. All rights reserved. Primary Authors: Drew Adams, Eric Paapanen Contributing Authors: M. Cowan, R. Moran, J. Russell, R. Strohm | |
Alpern et al. | Oracle Database Application Developer’s Guide-Fundamentals, 10g Release 2 (10.2) Part No. B14251-01 Copyright© 1996, 2005, Oracle. All rights reserved. Primary Author: Lance Ashdown Contributing Authors: D. Adams, M. Cowan, R. Moran, E. Paapanen, J. Russell, R. Strohm |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination |