/*
 * 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.
 */

drop  dataverse tpch if exists;
create  dataverse tpch;

use tpch;


create type tpch.LineItemType as
 closed {
  l_orderkey : int64,
  l_partkey : int64,
  l_suppkey : int64,
  l_linenumber : int64,
  l_quantity : int64,
  l_extendedprice : double,
  l_discount : double,
  l_tax : double,
  l_returnflag : string,
  l_linestatus : string,
  l_shipdate : string,
  l_commitdate : string,
  l_receiptdate : string,
  l_shipinstruct : string,
  l_shipmode : string,
  l_comment : string
}

create type tpch.OrderType as
 closed {
  o_orderkey : int64,
  o_custkey : int64,
  o_orderstatus : string,
  o_totalprice : double,
  o_orderdate : string,
  o_orderpriority : string,
  o_clerk : string,
  o_shippriority : int64,
  o_comment : string
}

create type tpch.CustomerType as
 closed {
  c_custkey : int64,
  c_name : string,
  c_address : string,
  c_nationkey : int64,
  c_phone : string,
  c_acctbal : double,
  c_mktsegment : string,
  c_comment : string
}

create type tpch.SupplierType as
 closed {
  s_suppkey : int64,
  s_name : string,
  s_address : string,
  s_nationkey : int64,
  s_phone : string,
  s_acctbal : double,
  s_comment : string
}

create type tpch.NationType as
 closed {
  n_nationkey : int64,
  n_name : string,
  n_regionkey : int64,
  n_comment : string
}

create type tpch.RegionType as
 closed {
  r_regionkey : int64,
  r_name : string,
  r_comment : string
}

create type tpch.PartType as
 closed {
  p_partkey : int64,
  p_name : string,
  p_mfgr : string,
  p_brand : string,
  p_type : string,
  p_size : int64,
  p_container : string,
  p_retailprice : double,
  p_comment : string
}

create type tpch.PartSuppType as
 closed {
  ps_partkey : int64,
  ps_suppkey : int64,
  ps_availqty : int64,
  ps_supplycost : double,
  ps_comment : string
}

drop nodegroup group_test if exists;
create  nodegroup group_test  on
    asterix_nc1;

create dataset LineItem(LineItemType)
  primary key l_orderkey, l_linenumber on group_test;
create dataset Orders(OrderType)
  primary key o_orderkey on group_test;

create index lineitem_shipdateIx on LineItem (l_shipdate);
create index lineitem_receiptdateIx on LineItem (l_receiptdate);
create index lineitem_fk_orders on LineItem (l_orderkey);
create index lineitem_fk_part on LineItem (l_partkey);
create index lineitem_fk_supplier on LineItem (l_suppkey);
create index orders_fk_customer on Orders (o_custkey);
create index orders_orderdateIx on Orders (o_orderdate);
