blob: a948d16d7b3f1f006ce0e465199975a98848e4ac [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas.query
import org.apache.atlas.repository.graphdb.AtlasGraph
import org.apache.atlas.discovery.graph.DefaultGraphPersistenceStrategy
import org.apache.atlas.query.Expressions._
import org.apache.atlas.repository.graph.{AtlasGraphProvider, GraphBackedMetadataRepository}
import org.apache.atlas.typesystem.types.TypeSystem
import org.testng.annotations._
import org.apache.atlas.repository.graph.AtlasGraphProvider
import org.apache.atlas.{DBSandboxer, TestUtils}
import org.apache.atlas.graph.GraphSandboxUtil
class GremlinTest extends BaseGremlinTest {
var g: AtlasGraph[_,_] = null
var gp: GraphPersistenceStrategies = null;
@BeforeMethod
def resetRequestContext() {
TestUtils.resetRequestContext()
}
@BeforeClass
def beforeAll() {
TypeSystem.getInstance().reset()
var repo = new GraphBackedMetadataRepository(null, new AtlasGraphProvider().get())
TestUtils.setupGraphProvider(repo)
//force graph to be initialized first
AtlasGraphProvider.getGraphInstance()
//create types and indices up front. Without this, some of the property keys (particularly __traitNames and __superTypes)
//get ended up created implicitly with some graph backends with the wrong multiplicity. This also makes the queries
//we execute perform better :-)
QueryTestsUtils.setupTypesAndIndices()
gp = new DefaultGraphPersistenceStrategy(repo)
g = QueryTestsUtils.setupTestGraph(repo)
}
@AfterClass
def afterAll() {
AtlasGraphProvider.cleanup()
}
@Test def testClass {
val r = QueryProcessor.evaluate(_class("DB"), g, gp)
validateJson(r, """{
| "query": "DB",
| "dataType": {
| "superTypes": [
|
| ],
| "hierarchicalMetaTypeName": "org.apache.atlas.typesystem.types.ClassType",
| "typeName": "DB",
| "attributeDefinitions": [
| {
| "name": "name",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "owner",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "createTime",
| "dataTypeName": "int",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
|
| },
| {
| "name": "clusterName",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| }
| ]
| },
| "rows": [
| {
| "$typeName$": "DB",
| "$id$": {
| "$typeName$": "DB",
| "version": 0
| },
| "owner": "John ETL",
| "name": "Sales",
| "createTime": 1000,
| "clusterName": "test"
| },
| {
| "$typeName$": "DB",
| "$id$": {
| "$typeName$": "DB",
| "version": 0
| },
| "owner": "Jane BI",
| "name": "Reporting",
| "createTime": 1500,
| "clusterName": "test"
| }
| ]
| }""".stripMargin)
}
@Test def testName {
val r = QueryProcessor.evaluate(_class("DB").field("name"), g, gp)
validateJson(r, "{\n \"query\":\"DB.name\",\n \"dataType\":\"string\",\n \"rows\":[\n \"Sales\",\n \"Reporting\"\n ]\n}")
}
@Test def testFilter {
var r = QueryProcessor.evaluate(_class("DB").where(id("name").`=`(string("Reporting"))), g, gp)
validateJson(r, """{
| "query": "DB where (name = \"Reporting\")",
| "dataType": {
| "superTypes": [],
| "hierarchicalMetaTypeName": "org.apache.atlas.typesystem.types.ClassType",
| "typeName": "DB",
| "attributeDefinitions": [
| {
| "name": "name",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "owner",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "createTime",
| "dataTypeName": "int",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "clusterName",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| }
| ]
| },
| "rows": [
| {
| "$typeName$": "DB",
| "$id$": {
| "$typeName$": "DB",
| "version": 0
| },
| "owner": "Jane BI",
| "name": "Reporting",
| "createTime": 1500,
| "clusterName": "test"
| }
| ]
|}""".stripMargin)
}
@Test def testFilter2 {
var r = QueryProcessor.evaluate(_class("DB").where(id("DB").field("name").`=`(string("Reporting"))), g, gp)
validateJson(r, """{
| "query": "DB where (name = \"Reporting\")",
| "dataType": {
| "superTypes": [],
| "hierarchicalMetaTypeName": "org.apache.atlas.typesystem.types.ClassType",
| "typeName": "DB",
| "attributeDefinitions": [
| {
| "name": "name",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "owner",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "createTime",
| "dataTypeName": "int",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "clusterName",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| }
| ]
| },
| "rows": [
| {
| "$typeName$": "DB",
| "$id$": {
| "$typeName$": "DB",
| "version": 0
| },
| "owner": "Jane BI",
| "name": "Reporting",
| "createTime": 1500,
| "clusterName": "test"
| }
| ]
|}""".stripMargin)
}
@Test def testSelect {
val r = QueryProcessor.evaluate(_class("DB").where(id("name").`=`(string("Reporting"))).
select(id("name"), id("owner")), g, gp)
validateJson(r, """{
| "query": "DB where (name = \"Reporting\") as _src1 select _src1.name as _src1.name, _src1.owner as _src1.owner",
| "dataType": {
| "typeName": "__tempQueryResultStruct1",
| "attributeDefinitions": [
| {
| "name": "_src1.name",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "_src1.owner",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| }
| ]
| },
| "rows": [
| {
| "$typeName$": "__tempQueryResultStruct1",
| "_src1.owner": "Jane BI",
| "_src1.name": "Reporting"
| }
| ]
|}""".stripMargin)
}
@Test def testIsTrait {
val r = QueryProcessor.evaluate(_class("Table").where(isTrait("Dimension")), g, gp)
validateJson(r, """{
| "query":"Table where Table is Dimension",
| "dataType":{
| "superTypes":[
|
| ],
| "hierarchicalMetaTypeName":"org.apache.atlas.typesystem.types.ClassType",
| "typeName":"Table",
| "attributeDefinitions":[
| {
| "name":"name",
| "dataTypeName":"string",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"db",
| "dataTypeName":"DB",
| "multiplicity":{
| "lower":1,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"sd",
| "dataTypeName":"StorageDescriptor",
| "multiplicity":{
| "lower":1,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"created",
| "dataTypeName":"date",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| }
| ]
| },
| "rows":[
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"product_dim",
| "$traits$":{
| "Dimension":{
| "$typeName$":"Dimension"
| }
| }
| },
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"time_dim",
| "$traits$":{
| "Dimension":{
| "$typeName$":"Dimension"
| }
| }
| },
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"customer_dim",
| "$traits$":{
| "Dimension":{
| "$typeName$":"Dimension"
| }
| }
| }
| ]
|}""".stripMargin)
}
@Test def testhasField {
val r = QueryProcessor.evaluate(_class("DB").where(hasField("name")), g, gp)
validateJson(r, """{
| "query":"DB where DB has name",
| "dataType":{
| "superTypes":[
|
| ],
| "hierarchicalMetaTypeName":"org.apache.atlas.typesystem.types.ClassType",
| "typeName":"DB",
| "attributeDefinitions":[
| {
| "name":"name",
| "dataTypeName":"string",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"owner",
| "dataTypeName":"string",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"createTime",
| "dataTypeName":"int",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"clusterName",
| "dataTypeName":"string",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| }
| ]
| },
| "rows":[
| {
| "$typeName$":"DB",
| "$id$":{
| "$typeName$":"DB",
| "version":0
| },
| "owner":"John ETL",
| "name":"Sales",
| "createTime":1000,
| "clusterName":"test"
| },
| {
| "$typeName$":"DB",
| "$id$":{
| "$typeName$":"DB",
| "version":0
| },
| "owner":"Jane BI",
| "name":"Reporting",
| "createTime":1500,
| "clusterName":"test"
| }
| ]
|}""".stripMargin)
}
@Test def testFieldReference {
val r = QueryProcessor.evaluate(_class("DB").field("Table"), g, gp)
validateJson(r, """{
| "query":"DB Table",
| "dataType":{
| "superTypes":[ ],
| "hierarchicalMetaTypeName":"org.apache.atlas.typesystem.types.ClassType",
| "typeName":"Table",
| "attributeDefinitions":[
| {
| "name":"name",
| "dataTypeName":"string",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"db",
| "dataTypeName":"DB",
| "multiplicity":{
| "lower":1,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"sd",
| "dataTypeName":"StorageDescriptor",
| "multiplicity":{
| "lower":1,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"created",
| "dataTypeName":"date",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| }
| ]
| },
| "rows":[
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"sales_fact"
| },
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"product_dim",
| "$traits$":{
| "Dimension":{
| "$typeName$":"Dimension"
| }
| }
| },
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"time_dim",
| "$traits$":{
| "Dimension":{
| "$typeName$":"Dimension"
| }
| }
| },
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"customer_dim",
| "$traits$":{
| "Dimension":{
| "$typeName$":"Dimension"
| }
| }
| },
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"sales_fact_daily_mv"
| },
| {
| "$typeName$":"Table",
| "$id$":{
| "$typeName$":"Table",
| "version":0
| },
| "created":"2014-12-11T02:35:58.440Z",
| "sd":{
| "$typeName$":"StorageDescriptor",
| "version":0
| },
| "db":{
| "$typeName$":"DB",
| "version":0
| },
| "name":"sales_fact_monthly_mv"
| }
| ]
|}""".stripMargin)
}
@Test def testBackReference {
val r = QueryProcessor.evaluate(
_class("DB").as("db").field("Table").where(id("db").field("name").`=`(string("Reporting"))), g, gp)
validateJson(r, null)
}
@Test def testArith {
val r = QueryProcessor.evaluate(_class("DB").where(id("name").`=`(string("Reporting"))).
select(id("name"), id("createTime") + int(1)), g, gp)
validateJson(r, "{\n \"query\":\"DB where (name = \\\"Reporting\\\") as _src1 select _src1.name as _src1.name, (_src1.createTime + 1) as (_src1.createTime + 1)\",\n \"dataType\":{\n \"typeName\":\"__tempQueryResultStruct3\",\n \"attributeDefinitions\":[\n {\n \"name\":\"_src1.name\",\n \"dataTypeName\":\"string\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n },\n {\n \"name\":\"(_src1.createTime + 1)\",\n \"dataTypeName\":\"int\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n }\n ]\n },\n \"rows\":[\n {\n \"$typeName$\":\"__tempQueryResultStruct3\",\n \"(_src1.createTime + 1)\":1501,\n \"_src1.name\":\"Reporting\"\n }\n ]\n}")
}
@Test def testComparisonLogical {
val r = QueryProcessor.evaluate(_class("DB").where(id("name").`=`(string("Reporting")).
and(id("createTime") > int(0))), g, gp)
validateJson(r, """{
| "query": "DB where (name = \"Reporting\") and (createTime > 0)",
| "dataType": {
| "superTypes": [
|
| ],
| "hierarchicalMetaTypeName": "org.apache.atlas.typesystem.types.ClassType",
| "typeName": "DB",
| "attributeDefinitions": [
| {
| "name": "name",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "owner",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "createTime",
| "dataTypeName": "int",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| },
| {
| "name": "clusterName",
| "dataTypeName": "string",
| "multiplicity": {
| "lower": 0,
| "upper": 1,
| "isUnique": false
| },
| "isComposite": false,
| "isUnique": false,
| "isIndexable": false,
| "reverseAttributeName": null
| }
| ]
| },
| "rows": [
| {
| "$typeName$": "DB",
| "$id$": {
| "$typeName$": "DB",
| "version": 0
| },
| "owner": "Jane BI",
| "name": "Reporting",
| "createTime": 1500,
| "clusterName": "test"
| }
| ]
|}""".stripMargin)
}
@Test def testJoinAndSelect1 {
val r = QueryProcessor.evaluate(
_class("DB").as("db1").where(id("name").`=`(string("Sales"))).field("Table").as("tab").
where(isTrait("Dimension")).
select(id("db1").field("name").as("dbName"), id("tab").field("name").as("tabName")), g, gp
)
validateJson(r, "{\n \"query\":\"DB as db1 where (name = \\\"Sales\\\") Table as tab where DB as db1 where (name = \\\"Sales\\\") Table as tab is Dimension as _src1 select db1.name as dbName, tab.name as tabName\",\n \"dataType\":{\n \"typeName\":\"__tempQueryResultStruct5\",\n \"attributeDefinitions\":[\n {\n \"name\":\"dbName\",\n \"dataTypeName\":\"string\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n },\n {\n \"name\":\"tabName\",\n \"dataTypeName\":\"string\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n }\n ]\n },\n \"rows\":[\n {\n \"$typeName$\":\"__tempQueryResultStruct5\",\n \"dbName\":\"Sales\",\n \"tabName\":\"product_dim\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct5\",\n \"dbName\":\"Sales\",\n \"tabName\":\"time_dim\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct5\",\n \"dbName\":\"Sales\",\n \"tabName\":\"customer_dim\"\n }\n ]\n}")
}
@Test def testJoinAndSelect2 {
val r = QueryProcessor.evaluate(
_class("DB").as("db1").where((id("db1").field("createTime") > int(0))
.or(id("name").`=`(string("Reporting")))).field("Table").as("tab")
.select(id("db1").field("name").as("dbName"), id("tab").field("name").as("tabName")), g, gp
)
validateJson(r, "{\n \"query\":\"DB as db1 where (createTime > 0) or (name = \\\"Reporting\\\") Table as tab select db1.name as dbName, tab.name as tabName\",\n \"dataType\":{\n \"typeName\":\"__tempQueryResultStruct6\",\n \"attributeDefinitions\":[\n {\n \"name\":\"dbName\",\n \"dataTypeName\":\"string\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n },\n {\n \"name\":\"tabName\",\n \"dataTypeName\":\"string\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n }\n ]\n },\n \"rows\":[\n {\n \"$typeName$\":\"__tempQueryResultStruct6\",\n \"dbName\":\"Sales\",\n \"tabName\":\"sales_fact\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct6\",\n \"dbName\":\"Sales\",\n \"tabName\":\"product_dim\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct6\",\n \"dbName\":\"Sales\",\n \"tabName\":\"time_dim\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct6\",\n \"dbName\":\"Sales\",\n \"tabName\":\"customer_dim\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct6\",\n \"dbName\":\"Reporting\",\n \"tabName\":\"sales_fact_daily_mv\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct6\",\n \"dbName\":\"Reporting\",\n \"tabName\":\"sales_fact_monthly_mv\"\n }\n ]\n}")
}
@Test def testJoinAndSelect3 {
val r = QueryProcessor.evaluate(
_class("DB").as("db1").where((id("db1").field("createTime") > int(0))
.and(id("db1").field("name").`=`(string("Reporting")))
.or(id("db1").hasField("owner"))).field("Table").as("tab")
.select(id("db1").field("name").as("dbName"), id("tab").field("name").as("tabName")), g, gp
)
validateJson(r, "{\n \"query\":\"DB as db1 where (createTime > 0) and (name = \\\"Reporting\\\") or db1 has owner Table as tab select db1.name as dbName, tab.name as tabName\",\n \"dataType\":{\n \"typeName\":\"__tempQueryResultStruct7\",\n \"attributeDefinitions\":[\n {\n \"name\":\"dbName\",\n \"dataTypeName\":\"string\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n },\n {\n \"name\":\"tabName\",\n \"dataTypeName\":\"string\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n }\n ]\n },\n \"rows\":[\n {\n \"$typeName$\":\"__tempQueryResultStruct7\",\n \"dbName\":\"Sales\",\n \"tabName\":\"sales_fact\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct7\",\n \"dbName\":\"Sales\",\n \"tabName\":\"product_dim\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct7\",\n \"dbName\":\"Sales\",\n \"tabName\":\"time_dim\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct7\",\n \"dbName\":\"Sales\",\n \"tabName\":\"customer_dim\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct7\",\n \"dbName\":\"Reporting\",\n \"tabName\":\"sales_fact_daily_mv\"\n },\n {\n \"$typeName$\":\"__tempQueryResultStruct7\",\n \"dbName\":\"Reporting\",\n \"tabName\":\"sales_fact_monthly_mv\"\n }\n ]\n}")
}
@Test def testJoinAndSelect4 {
val r = QueryProcessor.evaluate(
_class("DB").as("db1").where(id("name").`=`(string("Sales"))).field("Table").as("tab").
where(isTrait("Dimension")).
select(id("db1").as("dbO"), id("tab").field("name").as("tabName")), g, gp
)
validateJson(r, "{\n \"query\":\"DB as db1 where (name = \\\"Sales\\\") Table as tab where DB as db1 where (name = \\\"Sales\\\") Table as tab is Dimension as _src1 select db1 as dbO, tab.name as tabName\",\n \"dataType\":{\n \"typeName\":\"\",\n \"attributeDefinitions\":[\n {\n \"name\":\"dbO\",\n \"dataTypeName\":\"DB\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n },\n {\n \"name\":\"tabName\",\n \"dataTypeName\":\"string\",\n \"multiplicity\":{\n \"lower\":0,\n \"upper\":1,\n \"isUnique\":false\n },\n \"isComposite\":false,\n \"isUnique\":false,\n \"isIndexable\":false,\n \"reverseAttributeName\":null\n }\n ]\n },\n \"rows\":[\n {\n \"$typeName$\":\"\",\n \"dbO\":{\n \"$typeName$\":\"DB\",\n \"version\":0\n },\n \"tabName\":\"product_dim\"\n },\n {\n \"$typeName$\":\"\",\n \"dbO\":{\n \"$typeName$\":\"DB\",\n \"version\":0\n },\n \"tabName\":\"time_dim\"\n },\n {\n \"$typeName$\":\"\",\n \"dbO\":{\n \"$typeName$\":\"DB\",\n \"version\":0\n },\n \"tabName\":\"customer_dim\"\n }\n ]\n}")
}
@Test def testArrayComparision {
val p = QueryParser
val e = p("Partition as p where values = ['2015-01-01']," +
" table where name = 'sales_fact_daily_mv'," +
" db where name = 'Reporting' and clusterName = 'test' select p").right.get
val r = QueryProcessor.evaluate(e, g, gp)
validateJson(r, """{
| "query":"Partition as p where (values = [\"2015-01-01\"]) table where (name = \"sales_fact_daily_mv\") db where (name = \"Reporting\") and (clusterName = \"test\") as _src1 select p as p",
| "dataType":{
| "typeName":"__tempQueryResultStruct2",
| "attributeDefinitions":[
| {
| "name":"p",
| "dataTypeName":"Partition",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| }
| ]
| },
| "rows":[
| {
| "$typeName$":"__tempQueryResultStruct2",
| "p":{
| "$typeName$":"Partition",
| "version":0
| }
| }
| ]
|}""".stripMargin)
}
@Test def testArrayComparisionWithSelectOnArray {
val p = QueryParser
val e = p("Partition as p where values = ['2015-01-01']," +
" table where name = 'sales_fact_daily_mv'," +
" db where name = 'Reporting' and clusterName = 'test' select p.values").right.get
val r = QueryProcessor.evaluate(e, g, gp)
validateJson(r,
"""{
| "query":"Partition as p where (values = [\"2015-01-01\"]) table where (name = \"sales_fact_daily_mv\") db where (name = \"Reporting\") and (clusterName = \"test\") as _src1 select p.values as p.values",
| "dataType":{
| "typeName":"__tempQueryResultStruct2",
| "attributeDefinitions":[
| {
| "name":"p.values",
| "dataTypeName":"array<string>",
| "multiplicity":{
| "lower":0,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| }
| ]
| },
| "rows":[
| {
| "$typeName$":"__tempQueryResultStruct2",
| "p.values":[
| "2015-01-01"
| ]
| }
| ]
|}
""".stripMargin)
}
@Test def testArrayInWhereClause {
val p = QueryParser
val e = p("Partition as p where values = ['2015-01-01']").right.get
val r = QueryProcessor.evaluate(e, g, gp)
validateJson(r, """{
| "query":"Partition as p where (values = [\"2015-01-01\"])",
| "dataType":{
| "superTypes":[
|
| ],
| "hierarchicalMetaTypeName":"org.apache.atlas.typesystem.types.ClassType",
| "typeName":"Partition",
| "attributeDefinitions":[
| {
| "name":"values",
| "dataTypeName":"array<string>",
| "multiplicity":{
| "lower":1,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| },
| {
| "name":"table",
| "dataTypeName":"Table",
| "multiplicity":{
| "lower":1,
| "upper":1,
| "isUnique":false
| },
| "isComposite":false,
| "isUnique":false,
| "isIndexable":false,
| "reverseAttributeName":null
| }
| ]
| },
| "rows":[
| {
| "$typeName$":"Partition",
| "$id$":{
| "$typeName$":"Partition",
| "version":0
| },
| "values":[
| "2015-01-01"
| ],
| "table":{
| "$typeName$":"Table",
| "version":0
| }
| }
| ]
|}""".stripMargin)
}
@Test def testArrayWithStruct {
// val p = new QueryParser
// val e = p("from LoadProcess select inputTables").right.get
// val r = QueryProcessor.evaluate(e, g)
val r = QueryProcessor.evaluate(_class("LoadProcess").field("inputTables"), g, gp)
validateJson(r)
}
@Test(expectedExceptions = Array(classOf[ExpressionException]))
def testNegativeInvalidType {
val p = QueryParser
val e = p("from blah").right.get
QueryProcessor.evaluate(e, g, gp)
}
@Test def testJoinAndSelect5 {
val p = QueryParser
val e = p("Table as t where name = 'sales_fact' db where name = 'Sales' and owner = 'John ETL' select t").right.get
val r = QueryProcessor.evaluate(e, g, gp)
validateJson(r)
}
}