From 1c45439ed13f0f8937a17a6736fce342881ea97a Mon Sep 17 00:00:00 2001 From: Pratik Joseph Dabre Date: Fri, 20 Sep 2024 15:26:43 -0700 Subject: [PATCH 1/7] Add config property 'tpcds.use-varchar-type' Co-authored-by: Pramod Satya --- .../presto/tpcds/TpcdsConnectorFactory.java | 13 ++++++++++++- .../facebook/presto/tpcds/TpcdsMetadata.java | 18 ++++++++++++------ .../facebook/presto/tpcds/TpcdsRecordSet.java | 7 +++++-- .../tpcds/TestTpcdsMetadataStatistics.java | 2 +- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsConnectorFactory.java b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsConnectorFactory.java index 814e56e3136d9..4fed5910872af 100644 --- a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsConnectorFactory.java +++ b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsConnectorFactory.java @@ -64,6 +64,7 @@ public ConnectorHandleResolver getHandleResolver() public Connector create(String catalogName, Map config, ConnectorContext context) { int splitsPerNode = getSplitsPerNode(config); + boolean useVarcharType = useVarcharType(config); NodeManager nodeManager = context.getNodeManager(); return new Connector() { @@ -76,7 +77,7 @@ public ConnectorTransactionHandle beginTransaction(IsolationLevel isolationLevel @Override public ConnectorMetadata getMetadata(ConnectorTransactionHandle transactionHandle) { - return new TpcdsMetadata(); + return new TpcdsMetadata(useVarcharType); } @Override @@ -109,6 +110,16 @@ private int getSplitsPerNode(Map properties) } } + private boolean useVarcharType(Map properties) + { + try { + return parseBoolean(firstNonNull(properties.get("tpcds.use-varchar-type"), String.valueOf(false))); + } + catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid property tpcds.use-varchar-type"); + } + } + private boolean isWithNoSexism(Map properties) { return parseBoolean(firstNonNull(properties.get("tpcds.with-no-sexism"), String.valueOf(false))); diff --git a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsMetadata.java b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsMetadata.java index d571057317e39..745191d13b4b1 100644 --- a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsMetadata.java +++ b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsMetadata.java @@ -64,13 +64,16 @@ public class TpcdsMetadata private final Set tableNames; private final TpcdsTableStatisticsFactory tpcdsTableStatisticsFactory = new TpcdsTableStatisticsFactory(); - public TpcdsMetadata() + private final boolean useVarcharType; + + public TpcdsMetadata(boolean useVarcharType) { ImmutableSet.Builder tableNames = ImmutableSet.builder(); for (Table tpcdsTable : Table.getBaseTables()) { tableNames.add(tpcdsTable.getName().toLowerCase(ENGLISH)); } this.tableNames = tableNames.build(); + this.useVarcharType = useVarcharType; } @Override @@ -134,14 +137,14 @@ public ConnectorTableMetadata getTableMetadata(ConnectorSession session, Connect Table table = Table.getTable(tpcdsTableHandle.getTableName()); String schemaName = scaleFactorSchemaName(tpcdsTableHandle.getScaleFactor()); - return getTableMetadata(schemaName, table); + return getTableMetadata(schemaName, table, useVarcharType); } - private static ConnectorTableMetadata getTableMetadata(String schemaName, Table tpcdsTable) + private static ConnectorTableMetadata getTableMetadata(String schemaName, Table tpcdsTable, boolean useVarcharType) { ImmutableList.Builder columns = ImmutableList.builder(); for (Column column : tpcdsTable.getColumns()) { - columns.add(new ColumnMetadata(column.getName(), getPrestoType(column.getType()))); + columns.add(new ColumnMetadata(column.getName(), getPrestoType(column.getType(), useVarcharType))); } SchemaTableName tableName = new SchemaTableName(schemaName, tpcdsTable.getName()); return new ConnectorTableMetadata(tableName, columns.build()); @@ -189,7 +192,7 @@ public Map> listTableColumns(ConnectorSess for (String schemaName : getSchemaNames(session, Optional.ofNullable(prefix.getSchemaName()))) { for (Table tpcdsTable : Table.getBaseTables()) { if (prefix.getTableName() == null || tpcdsTable.getName().equals(prefix.getTableName())) { - ConnectorTableMetadata tableMetadata = getTableMetadata(schemaName, tpcdsTable); + ConnectorTableMetadata tableMetadata = getTableMetadata(schemaName, tpcdsTable, useVarcharType); tableColumns.put(new SchemaTableName(schemaName, tpcdsTable.getName()), tableMetadata.getColumns()); } } @@ -243,7 +246,7 @@ public static double schemaNameToScaleFactor(String schemaName) } } - public static Type getPrestoType(ColumnType tpcdsType) + public static Type getPrestoType(ColumnType tpcdsType, boolean useVarcharType) { switch (tpcdsType.getBase()) { case IDENTIFIER: @@ -255,6 +258,9 @@ public static Type getPrestoType(ColumnType tpcdsType) case DECIMAL: return createDecimalType(tpcdsType.getPrecision().get(), tpcdsType.getScale().get()); case CHAR: + if (useVarcharType) { + return createVarcharType(tpcdsType.getPrecision().get()); + } return createCharType(tpcdsType.getPrecision().get()); case VARCHAR: return createVarcharType(tpcdsType.getPrecision().get()); diff --git a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsRecordSet.java b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsRecordSet.java index a3821d2cdc307..2d6c461fbd54a 100644 --- a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsRecordSet.java +++ b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsRecordSet.java @@ -57,7 +57,10 @@ public TpcdsRecordSet(Results results, List columns) this.columns = ImmutableList.copyOf(columns); ImmutableList.Builder columnTypes = ImmutableList.builder(); for (Column column : columns) { - columnTypes.add(getPrestoType(column.getType())); + // The TPCDS config tpcds.use-varchar-type is set to true only for native execution, since char type is + // currently unsupported in Presto native. This function is only used by the Presto java TPCDS connector + // so the argument useVarcharType is false here. + columnTypes.add(getPrestoType(column.getType(), false)); } this.columnTypes = columnTypes.build(); } @@ -103,7 +106,7 @@ public long getReadTimeNanos() @Override public Type getType(int field) { - return getPrestoType(columns.get(field).getType()); + return getPrestoType(columns.get(field).getType(), false); } @Override diff --git a/presto-tpcds/src/test/java/com/facebook/presto/tpcds/TestTpcdsMetadataStatistics.java b/presto-tpcds/src/test/java/com/facebook/presto/tpcds/TestTpcdsMetadataStatistics.java index 5d732fff6e1b8..432ef7c665f43 100644 --- a/presto-tpcds/src/test/java/com/facebook/presto/tpcds/TestTpcdsMetadataStatistics.java +++ b/presto-tpcds/src/test/java/com/facebook/presto/tpcds/TestTpcdsMetadataStatistics.java @@ -45,7 +45,7 @@ public class TestTpcdsMetadataStatistics { private static final EstimateAssertion estimateAssertion = new EstimateAssertion(0.01); private static final ConnectorSession session = null; - private final TpcdsMetadata metadata = new TpcdsMetadata(); + private final TpcdsMetadata metadata = new TpcdsMetadata(false); @Test public void testNoTableStatsForNotSupportedSchema() From 2b01e44aed89e4d275f8d195eda2250ff6684a84 Mon Sep 17 00:00:00 2001 From: Pratik Joseph Dabre Date: Fri, 24 Jan 2025 15:43:24 -0800 Subject: [PATCH 2/7] [native] Dsdgen codegen files --- .../presto_cpp/external/dsdgen/LICENSE | 320 ++ .../external/dsdgen/dsdgen-c/CMakeLists.txt | 66 + .../external/dsdgen/dsdgen-c/StringBuffer.cpp | 158 + .../external/dsdgen/dsdgen-c/address.cpp | 360 ++ .../dsdgen/dsdgen-c/build_support.cpp | 442 ++ .../external/dsdgen/dsdgen-c/date.cpp | 610 +++ .../dsdgen/dsdgen-c/dbgen_version.cpp | 113 + .../external/dsdgen/dsdgen-c/decimal.cpp | 347 ++ .../external/dsdgen/dsdgen-c/dist.cpp | 1142 +++++ .../external/dsdgen/dsdgen-c/error_msg.cpp | 237 + .../external/dsdgen/dsdgen-c/genrand.cpp | 703 +++ .../external/dsdgen/dsdgen-c/join.cpp | 455 ++ .../external/dsdgen/dsdgen-c/list.cpp | 272 ++ .../external/dsdgen/dsdgen-c/load.cpp | 87 + .../external/dsdgen/dsdgen-c/misc.cpp | 103 + .../external/dsdgen/dsdgen-c/nulls.cpp | 86 + .../external/dsdgen/dsdgen-c/parallel.cpp | 197 + .../external/dsdgen/dsdgen-c/permute.cpp | 103 + .../external/dsdgen/dsdgen-c/pricing.cpp | 459 ++ .../external/dsdgen/dsdgen-c/r_params.cpp | 707 +++ .../external/dsdgen/dsdgen-c/scaling.cpp | 785 ++++ .../external/dsdgen/dsdgen-c/scd.cpp | 382 ++ .../external/dsdgen/dsdgen-c/skip_days.cpp | 49 + .../external/dsdgen/dsdgen-c/sparse.cpp | 97 + .../dsdgen/dsdgen-c/tdef_functions.cpp | 69 + .../external/dsdgen/dsdgen-c/tdefs.cpp | 185 + .../external/dsdgen/dsdgen-c/text.cpp | 185 + .../dsdgen/dsdgen-c/w_call_center.cpp | 347 ++ .../dsdgen/dsdgen-c/w_catalog_page.cpp | 124 + .../dsdgen/dsdgen-c/w_catalog_returns.cpp | 144 + .../dsdgen/dsdgen-c/w_catalog_sales.cpp | 376 ++ .../external/dsdgen/dsdgen-c/w_customer.cpp | 164 + .../dsdgen/dsdgen-c/w_customer_address.cpp | 86 + .../dsdgen-c/w_customer_demographics.cpp | 99 + .../external/dsdgen/dsdgen-c/w_datetbl.cpp | 159 + .../dsdgen-c/w_household_demographics.cpp | 78 + .../dsdgen/dsdgen-c/w_income_band.cpp | 61 + .../external/dsdgen/dsdgen-c/w_inventory.cpp | 137 + .../external/dsdgen/dsdgen-c/w_item.cpp | 308 ++ .../external/dsdgen/dsdgen-c/w_promotion.cpp | 148 + .../external/dsdgen/dsdgen-c/w_reason.cpp | 58 + .../external/dsdgen/dsdgen-c/w_ship_mode.cpp | 83 + .../external/dsdgen/dsdgen-c/w_store.cpp | 393 ++ .../dsdgen/dsdgen-c/w_store_returns.cpp | 114 + .../dsdgen/dsdgen-c/w_store_sales.cpp | 259 ++ .../external/dsdgen/dsdgen-c/w_timetbl.cpp | 70 + .../external/dsdgen/dsdgen-c/w_warehouse.cpp | 97 + .../external/dsdgen/dsdgen-c/w_web_page.cpp | 250 ++ .../dsdgen/dsdgen-c/w_web_returns.cpp | 123 + .../external/dsdgen/dsdgen-c/w_web_sales.cpp | 326 ++ .../external/dsdgen/dsdgen-c/w_web_site.cpp | 313 ++ .../dsdgen/include/dsdgen-c/StringBuffer.h | 30 + .../dsdgen/include/dsdgen-c/address.h | 46 + .../dsdgen/include/dsdgen-c/append_info.h | 44 + .../dsdgen/include/dsdgen-c/build_support.h | 88 + .../dsdgen/include/dsdgen-c/columns.h | 942 ++++ .../external/dsdgen/include/dsdgen-c/config.h | 156 + .../dsdgen/include/dsdgen-c/constants.h | 310 ++ .../external/dsdgen/include/dsdgen-c/date.h | 54 + .../dsdgen/include/dsdgen-c/dbgen_version.h | 23 + .../external/dsdgen/include/dsdgen-c/dcomp.h | 62 + .../dsdgen/include/dsdgen-c/decimal.h | 36 + .../external/dsdgen/include/dsdgen-c/dist.h | 3985 +++++++++++++++++ .../dsdgen/include/dsdgen-c/error_msg.h | 76 + .../dsdgen/include/dsdgen-c/genrand.h | 84 + .../dsdgen/include/dsdgen-c/grammar.h | 30 + .../dsdgen/include/dsdgen-c/grammar_support.h | 35 + .../external/dsdgen/include/dsdgen-c/list.h | 46 + .../external/dsdgen/include/dsdgen-c/load.h | 18 + .../dsdgen/include/dsdgen-c/mathops.h | 29 + .../external/dsdgen/include/dsdgen-c/misc.h | 29 + .../external/dsdgen/include/dsdgen-c/nulls.h | 20 + .../dsdgen/include/dsdgen-c/parallel.h | 23 + .../external/dsdgen/include/dsdgen-c/params.h | 25 + .../dsdgen/include/dsdgen-c/permute.h | 22 + .../dsdgen/include/dsdgen-c/porting.h | 144 + .../dsdgen/include/dsdgen-c/pricing.h | 29 + .../dsdgen/include/dsdgen-c/r_params.h | 53 + .../dsdgen/include/dsdgen-c/scaling.h | 28 + .../external/dsdgen/include/dsdgen-c/scd.h | 52 + .../dsdgen/include/dsdgen-c/skip_days.h | 22 + .../external/dsdgen/include/dsdgen-c/sparse.h | 20 + .../dsdgen/include/dsdgen-c/streams.h | 18 + .../external/dsdgen/include/dsdgen-c/tables.h | 92 + .../dsdgen/include/dsdgen-c/tdef_functions.h | 46 + .../external/dsdgen/include/dsdgen-c/tdefs.h | 30 + .../dsdgen/include/dsdgen-c/template.h | 46 + .../dsdgen/include/dsdgen-c/tpcds.idx.h | 266 ++ .../dsdgen/include/dsdgen-c/w_call_center.h | 31 + .../dsdgen/include/dsdgen-c/w_catalog_page.h | 24 + .../include/dsdgen-c/w_catalog_returns.h | 23 + .../dsdgen/include/dsdgen-c/w_catalog_sales.h | 27 + .../dsdgen/include/dsdgen-c/w_customer.h | 24 + .../include/dsdgen-c/w_customer_address.h | 24 + .../dsdgen-c/w_customer_demographics.h | 30 + .../dsdgen/include/dsdgen-c/w_datetbl.h | 28 + .../dsdgen-c/w_household_demographics.h | 23 + .../dsdgen/include/dsdgen-c/w_income_band.h | 18 + .../dsdgen/include/dsdgen-c/w_inventory.h | 20 + .../external/dsdgen/include/dsdgen-c/w_item.h | 30 + .../dsdgen/include/dsdgen-c/w_promotion.h | 24 + .../dsdgen/include/dsdgen-c/w_reason.h | 21 + .../dsdgen/include/dsdgen-c/w_ship_mode.h | 23 + .../dsdgen/include/dsdgen-c/w_store.h | 20 + .../dsdgen/include/dsdgen-c/w_store_returns.h | 23 + .../dsdgen/include/dsdgen-c/w_store_sales.h | 27 + .../dsdgen/include/dsdgen-c/w_timetbl.h | 24 + .../dsdgen/include/dsdgen-c/w_warehouse.h | 23 + .../dsdgen/include/dsdgen-c/w_web_page.h | 19 + .../dsdgen/include/dsdgen-c/w_web_returns.h | 19 + .../dsdgen/include/dsdgen-c/w_web_sales.h | 38 + .../dsdgen/include/dsdgen-c/w_web_site.h | 26 + .../external/dsdgen/include/tpcds.idx | Bin 0 -> 640585 bytes 113 files changed, 20684 insertions(+) create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/LICENSE create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/CMakeLists.txt create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/StringBuffer.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/address.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/build_support.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/date.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/dbgen_version.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/decimal.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/dist.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/error_msg.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/genrand.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/join.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/list.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/load.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/misc.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/nulls.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/parallel.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/permute.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/pricing.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/r_params.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/scaling.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/scd.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/skip_days.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/sparse.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/tdef_functions.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/tdefs.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/text.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_call_center.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_page.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_returns.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_sales.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer_address.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer_demographics.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_datetbl.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_household_demographics.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_income_band.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_inventory.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_item.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_promotion.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_reason.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_ship_mode.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store_returns.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store_sales.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_timetbl.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_warehouse.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_page.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_returns.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_sales.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_site.cpp create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/StringBuffer.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/address.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/append_info.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/build_support.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/columns.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/config.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/constants.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/date.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dbgen_version.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dcomp.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/decimal.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dist.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/error_msg.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/genrand.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/grammar.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/grammar_support.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/list.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/load.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/mathops.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/misc.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/nulls.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/parallel.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/params.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/permute.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/porting.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/pricing.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/r_params.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/scaling.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/scd.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/skip_days.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/sparse.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/streams.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tables.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tdef_functions.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tdefs.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/template.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tpcds.idx.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_call_center.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_page.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_returns.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_sales.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer_address.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer_demographics.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_datetbl.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_household_demographics.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_income_band.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_inventory.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_item.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_promotion.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_reason.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_ship_mode.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store_returns.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store_sales.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_timetbl.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_warehouse.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_page.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_returns.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_sales.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_site.h create mode 100644 presto-native-execution/presto_cpp/external/dsdgen/include/tpcds.idx diff --git a/presto-native-execution/presto_cpp/external/dsdgen/LICENSE b/presto-native-execution/presto_cpp/external/dsdgen/LICENSE new file mode 100644 index 0000000000000..92af24a54f553 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/LICENSE @@ -0,0 +1,320 @@ +END USER LICENSE AGREEMENT +VERSION 2.2 + +READ THE TERMS AND CONDITIONS OF THIS AGREEMENT ("AGREEMENT") CAREFULLY +BEFORE INSTALLING OR USING THE ACCOMPANYING SOFTWARE. BY INSTALLING OR +USING THE SOFTWARE OR RELATED DOCUMENTATION, YOU AGREE TO BE BOUND BY +THE TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO THE TERMS OF THIS +AGREEMENT, DO NOT INSTALL OR USE THE SOFTWARE. IF YOU ARE ACCESSING THE +SOFTWARE ON BEHALF OF YOUR ORGANIZATION, YOU REPRESENT AND WARRANT THAT +YOU HAVE SUFFICIENT AUTHORITY TO BIND YOUR ORGANIZATION TO THIS +AGREEMENT. + +USE AND RE-EXPORT OF THE SOFTWARE IS SUBJECT TO THE UNITED STATES EXPORT +CONTROL ADMINISTRATION REGULATIONS. THE SOFTWARE MAY NOT BE USED BY +UNLICENSED PERSONS OR ENTITIES, AND MAY NOT BE RE- EXPORTED TO ANOTHER +COUNTRY. SEE EXPORT ASSURANCE (CLAUSE 13) OF THIS LICENSE. + +This is a legal agreement between you (or, if you are accessing the +software on behalf of your organization, your organization) ("You" or +"User") and the Transaction Processing Performance Council ("TPC"). This +Agreement states the terms and conditions upon which TPC offers to +license the Software, including, but not limited to, the source code, +scripts, executable programs, drivers, libraries and data files +associated with such programs, and modifications thereof (the +"Software"), and online, electronic or printed documentation +("Documentation," together with the Software, "Materials"). + +LICENSE + +1. Definitions + +"Executive Summary" shall mean a short summary of a TPC Benchmark Result +that shows the configuration, primary metrics, performance data, and +pricing details. The exact requirements for the Executive Summary are +defined in each TPC Benchmark Standard. +"Full Disclosure Report (FDR)" shall mean a document that describes The +TPC Benchmark Result in sufficient detail such that the Result could be +recreated. The exact requirements for the FDR are defined in each TPC +Benchmark Standard. +"TPC Benchmark Result (Result)" shall mean a performance test submitted +to the TPC attested to meet the requirements of a TPC Benchmark Standard +at the time of submission. A Result is documented by an Executive +Summary and, if required, a FDR. +"TPC Benchmark Standard" shall mean a TPC Benchmark Specification and +any associated code or binaries approved by the TPC. The various TPC +Benchmark Standards can be found at +http://www.tpc.org/information/current_specifications.asp. +"TPC Policies" shall mean the guiding principles for how the TPC +conducts its operations and business. The current TPC Policies can be +found at http://www.tpc.org/information/current_specifications.asp. + +2. Ownership. The Materials are licensed, not sold, to You for use only +under the terms of this Agreement. As between You and TPC (and, to the +extent applicable, its licensors), TPC retains all rights, title and +interest to and ownership of the Materials and reserves all rights not +expressly granted to You. + +3. License Grant. Subject to Your compliance in all material respects +with the terms and conditions of this Agreement, TPC grants You a +restricted, non-exclusive, revocable license to install and use the +Materials, but only as expressly permitted herein. You may only use the +Software on computer systems under Your direct control. You may download +multiple copies of the Materials and make verbatim copies of the +original of the Software so long as Your use of such copies complies +with the terms of this Agreement. +a. Use by Individual. If You are accessing the Materials as an +individual, only You (as an individual) may access and use the +Materials. +b. Use by Organization. If You are accessing the Materials on behalf of +Your organization, only You and those within Your organization may use +the Materials. Your organization must identify a contact person to TPC +and conduct communications with TPC through that contact person. + +4. Restrictions. The following restrictions apply to all use of the +Materials by You. +a. General: You may not: +(1) use, copy, print, modify, adapt, create derivative works from, +market, deliver, rent, lease, sublicense, make, have made, assign, +pledge, transfer, sell, offer to sell, import, reproduce, distribute, +publicly perform, publicly display or otherwise grant rights to the +Materials, or any copy thereof, in whole or in part, except as expressly +permitted under this Agreement; or +(2) use the Materials in any way that does not comply with all +applicable laws and regulations. +b. Modification: You may modify the Software. +c. Public Disclosure: You may not publicly disclose any performance +results produced while using the Software except in the following +circumstances: +(1) as part of a TPC Benchmark Result. For purposes of this Agreement, a +"TPC Benchmark Result" is a performance test submitted to the TPC, +documented by a Full Disclosure Report and Executive Summary, claiming +to meet the requirements of an official TPC Benchmark Standard. You +agree that TPC Benchmark Results may only be published in accordance +with the TPC Policies. viewable at http: //www.tpc.org +(2) as part of an academic or research effort that does not imply or +state a marketing position +(3) any other use of the Software, provided that any performance results +must be clearly identified as not being comparable to TPC Benchmark +Results unless specifically authorized by TPC. + +5. License Modification. Requests for modification of this license shall +be addressed to info@tpc.org. You may not remove or modify this license +without permission. + +6. Copyright. The Materials are owned by TPC and/or its licensors, and +are protected by United States copyright laws and international treaty +provisions. You may not remove the copyright notice from the original or +any copy of the Materials, and You must apply the notice if You extract +part of the Materials not bearing a notice. + +7. Use of Name. You acknowledge and agree that TPC owns all trademark +and trade name rights in the names, trademarks and logos used by TPC in +the Materials. User shall preserve any notices regarding such ownership. +User may only use such names, trademarks and logos in accordance with +the usage guidelines specified by the TPC Policies. + +8. Merger or Integration. Any portion of the Materials merged into or +integrated with other software or documentation will continue to be +subject to the terms and conditions of this Agreement. + +9. Limited Grants of Sublicense. You may distribute the Software as +provided or as modified as permitted under clause 4 b. of this +Agreement, provided You comply with all of the terms of this Agreement +and the following conditions: + +a. If You distribute any portion of the Software in its original form +You may do so only under this Agreement by including a complete copy of +this Agreement with Your distribution, and if You distribute the +Software in modified form, You may only do so under a license that at a +minimum provides all of the protections and conditions of use contained +within this Agreement; + +b. You must include on each copy of the Software that You distribute the +following legend in all caps, at the top of the label and license, and +in a font not less than 12 point and no less prominent than any other +printing: "THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC."; + +c. You must retain all copyright, patent, trademark, and attribution +notices that are present in the Software; and + +d. You may not charge a fee for the distribution of this Software, +including any modifications permitted under clause 4.b. + +10. Term and Termination. +a. Term. The license granted to You is effective until terminated. +b. Termination. +(1) By You. You may terminate this Agreement at any time by returning +the Materials (including any portions or copies thereof) to TPC or +providing written notice to the TPC that all copies of the Materials +within Your custody or control have been deleted or destroyed. +(2) By TPC. In the event You materially fail to comply with any term or +condition of this Agreement, and You fail to remedy such non-compliance +within 30 days after the receipt of notice to that effect, then TPC +shall have the right to terminate this Agreement immediately upon +written notice at the end of such 30-day period. +c. Effect of Termination. Termination of this Agreement in accordance +with this clause 10 will not terminate the rights of end users +sublicensed by You pursuant to this Agreement. Moreover, upon +termination and at TPC's written request, You agree to either (1) return +the Materials (including any portions or copies thereof) to TPC or (2) +immediately destroy all copies of the Materials within Your custody or +control and inform the TPC of the destruction of the Materials. Upon +termination, TPC may also enforce any rights provided by law. The +provisions of this Agreement that protect the proprietary rights of TPC +and its Licensors will continue in force after termination. + +11. No Warranty; Materials Provided "As Is". TO THE MAXIMUM EXTENT +PERMITTED BY APPLICABLE LAW, THE MATERIALS ARE PROVIDED "AS IS" AND WITH +ALL FAULTS, AND TPC (AND ITS LICENSORS) AND THE AUTHORS AND DEVELOPERS +OF THE MATERIALS HEREBY DISCLAIM ALL WARRANTIES, REPRESENTATIONS AND +CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT +LIMITED TO, ANY IMPLIED WARRANTIES, DUTIES OR CONDITIONS RELATING TO +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, ACCURACY OR +COMPLETENESS OF RESPONSES, RESULTS, WORKMANLIKE EFFORT, LACK OF VIRUSES, +LACK OF NEGLIGENCE, TITLE, QUIET ENJOYMENT, QUIET POSSESSION, +CORRESPONDENCE TO DESCRIPTION OR NONINFRINGEMENT. USER RECOGNIZES THAT +THE MATERIALS ARE THE RESULT OF A COOPERATIVE, NON-PROFIT EFFORT AND +THAT TPC DOES NOT CONDUCT A TYPICAL BUSINESS. USER ACCEPTS THE MATERIALS +"AS IS" AND WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. + +Without limitation, TPC (and its licensors) do not warrant that the +functions contained in the Software or Materials will meet Your +requirements or that the operation of the Software will be +uninterrupted, error-free or free from malicious code. For purposes of +this paragraph, "malicious code" means any program code designed to +contaminate other computer programs or computer data, consume computer +resources, modify, destroy, record, or transmit data, or in some other +fashion usurp the normal operation of the computer, computer system, or +computer network, including viruses, Trojan horses, droppers, worms, +logic bombs, and the like. TPC (and its licensors) shall not be liable +for the accuracy of any information provided by TPC or third-party +technical support personnel, or any damages caused, either directly or +indirectly, by acts taken or omissions made by You as a result of such +technical support. + +You assume full responsibility for the selection of the Materials to +achieve Your intended results, and for the installation, use and results +obtained from the Materials. You also assume the entire risk as it +applies to the quality and performance of the Materials. Should the +Materials prove defective, You (and not TPC) assume the entire liability +of any and all necessary servicing, repair or correction. Some +countries/states do not allow the exclusion of implied warranties, so +the above exclusion may not apply to You. TPC (and its licensors) +further disclaims all warranties of any kind if the Materials were +customized, repackaged or altered in any way by any party other than TPC +(or its licensors). + +12. Disclaimer of Liability. TPC (and its licensors) assumes no +liability with respect to the Materials, including liability for +infringement of intellectual property rights, negligence, or any other +liability. TPC is not aware of any infringement of copyright or patent +that may result from its grant of rights to User of the Materials. If +User receives any notice of infringement, such notice shall be +immediately communicated to TPC who will have sole discretion to take +action to evaluate the claim and, if practicable, modify the Materials +as necessary to avoid infringement. In the event that TPC determines +that the Materials cannot be modified to avoid such infringement (or any +other infringement claim communicated to TPC), TPC may terminate this +Agreement immediately. User shall suspend use of the Materials until +modifications to avoid claims of infringement have been completed. User +waives any claim against TPC in the event of such infringement claims by +others. + +13. Export Assurance. Use and re-export of the Materials and related +technical information is subject to the Export Administration +Regulations (EAR) of the United States Department of Commerce. User +hereby agrees that User (a) assumes responsibility for compliance with +the EAR in its use of the Materials and technical information, and (b) +will not export, re-export, or otherwise disclose directly or +indirectly, the Materials, technical data, or any direct product of the +Materials or technical data in violation of the EAR. + +14. Limitation of Remedies And Damages. IN NO EVENT WILL TPC OR ITS +LICENSORS OR LICENSEE BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL OR +CONSEQUENTIAL DAMAGES OR FOR ANY LOST PROFITS, LOST SAVINGS, LOST +REVENUES OR LOST DATA ARISING FROM OR RELATING TO THE MATERIALS OR THIS +AGREEMENT, EVEN IF TPC OR ITS LICENSORS OR LICENSEE HAVE BEEN ADVISED OF +THE POSSIBILITY OF SUCH DAMAGES. IN NO EVENT WILL TPC'S OR ITS +LICENSORS' LIABILITY OR DAMAGES TO YOU OR ANY OTHER PERSON EVER EXCEED +U.S. ONE HUNDRED DOLLARS (US $100), REGARDLESS OF THE FORM OF THE CLAIM. +IN NO EVENT WILL LICENSEE'S LIABILITY OR DAMAGES TO TPC OR ANY OTHER +PERSON EVER EXCEED $1,000,000, REGARDLESS OF THE FORM OF THE CLAIM. Some +countries/states do not allow the limitation or exclusion of liability +for incidental or consequential damages, so the above limitation or +exclusion may not apply to You. + +15. U.S. Government Restricted Rights. All Software and related +documentation are provided with restricted rights. Use, duplication or +disclosure by the U.S. Government is subject to restrictions as set +forth in subdivision (b)(3)(ii) of the Rights in Technical Data and +Computer Software Clause at 252.227-7013. If You are using the Software +outside of the United States, You will comply with the applicable local +laws of Your country, U.S. export control law, and the English version +of this Agreement. + +16. Contractor/Manufacturer. The Contractor/Manufacturer for the +Software is: + +Transaction Processing Performance Council +572B Ruger Street, P.O. Box 29920 +San Francisco, CA 94129 + +17. General. This Agreement is binding on You as well as Your employees, +employers, contractors and agents, and on any successors and assignees. +This Agreement is governed by the laws of the State of California +(except to the extent federal law governs copyrights and trademarks) +without respect to any provisions of California law that would cause +application of the law of another state or country. The parties agree +that the United Nations Convention on Contracts for the International +Sale of Goods will not govern this Agreement. This Agreement is the +entire agreement between us regarding the subject matter hereof and +supersedes any other understandings or agreements with respect to the +Materials or the subject matter hereof. If any provision of this +Agreement is deemed invalid or unenforceable by any court having +jurisdiction, that particular provision will be deemed modified to the +extent necessary to make the provision valid and enforceable, and the +remaining provisions will remain in full force and effect. + +SPECIAL PROVISIONS APPLICABLE TO THE EUROPEAN UNION + +If You acquired the Materials in the European Union (EU), the following +provisions also apply to You. If there is any inconsistency between the +terms of the Software License Agreement set out earlier and the +following provisions, the following provisions shall take precedence. + +1. Distribution. You may sublicense modifications of the Software +covered in this Agreement if they meet the requirements of clause 9 +above. + +2. Limited Warranty. EXCEPT AS STATED EARLIER IN THIS AGREEMENT, AND AS +PROVIDED UNDER THE HEADING "STATUTORY RIGHTS", THE SOFTWARE IS PROVIDED +AS-IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES, NONINFRINGEMENT, +OR CONDITIONS OF MERCHANTABILITY, QUALITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +3. Limitation of Remedy and Damages. THE LIMITATIONS OF REMEDIES AND +DAMAGES IN THE SOFTWARE LICENSE AGREEMENT SHALL NOT APPLY TO PERSONAL +INJURY (INCLUDING DEATH) TO ANY PERSON CAUSED BY TPC'S NEGLIGENCE AND +ARE SUBJECT TO THE PROVISION SET OUT UNDER THE HEADING "STATUTORY +RIGHTS". + +4. Statutory Rights: Irish law provides that certain conditions and +warranties may be implied in contracts for the sale of goods and in +contracts for the supply of services. Such conditions and warranties are +hereby excluded, to the extent such exclusion, in the context of this +transaction, is lawful under Irish law. Conversely, such conditions and +warranties, insofar as they may not be lawfully excluded, shall apply. +Accordingly nothing in this Agreement shall prejudice any rights that +You may enjoy by virtue of Sections 12, 13, 14 or 15 of the Irish Sale +of Goods Act 1893 (as amended). + +5. General. This Agreement is governed by the laws of the Republic of +Ireland. The local language version of this agreement shall apply to +Materials acquired in the EU. This Agreement is the entire agreement +between us with respect to the subject matter hereof and You agree that +TPC will not have any liability for any untrue statement or +representation made by it, its agents or anyone else (whether innocently +or negligently) upon which You relied upon entering this Agreement, +unless such untrue statement or representation was made fraudulently. \ No newline at end of file diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/CMakeLists.txt b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/CMakeLists.txt new file mode 100644 index 0000000000000..73c88cda44daf --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/CMakeLists.txt @@ -0,0 +1,66 @@ +# +# Copyright owned by the Transaction Processing Performance Council. +# +# A copy of the license is included under external/dsdgen/LICENSE +# in this repository. +# +# You may not use this file except in compliance with the License. +# +# THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. +# + +add_library( + dsdgen_c OBJECT + skip_days.cpp + address.cpp + build_support.cpp + date.cpp + dbgen_version.cpp + decimal.cpp + dist.cpp + error_msg.cpp + genrand.cpp + join.cpp + list.cpp + load.cpp + misc.cpp + nulls.cpp + parallel.cpp + permute.cpp + pricing.cpp + r_params.cpp + scaling.cpp + scd.cpp + sparse.cpp + StringBuffer.cpp + tdef_functions.cpp + tdefs.cpp + text.cpp + w_call_center.cpp + w_catalog_page.cpp + w_catalog_returns.cpp + w_catalog_sales.cpp + w_customer.cpp + w_customer_address.cpp + w_customer_demographics.cpp + w_datetbl.cpp + w_household_demographics.cpp + w_income_band.cpp + w_inventory.cpp + w_item.cpp + w_promotion.cpp + w_reason.cpp + w_ship_mode.cpp + w_store.cpp + w_store_returns.cpp + w_store_sales.cpp + w_timetbl.cpp + w_warehouse.cpp + w_web_page.cpp + w_web_returns.cpp + w_web_sales.cpp + w_web_site.cpp) + +include_directories(${CMAKE_SOURCE_DIR}/presto_cpp/external/dsdgen/include) +include_directories( + ${CMAKE_SOURCE_DIR}/presto_cpp/external/dsdgen/include/dsdgen-c) diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/StringBuffer.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/StringBuffer.cpp new file mode 100644 index 0000000000000..f2ca1f0fda685 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/StringBuffer.cpp @@ -0,0 +1,158 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include +#include +#include "config.h" +#include "porting.h" +#ifndef USE_STDLIB_H +#include +#endif +#include "StringBuffer.h" + +/* + * Routine: InitBuffer + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +StringBuffer_t* InitBuffer(int nSize, int nIncrement) { + StringBuffer_t* pBuf = nullptr; + + pBuf = static_cast(malloc(sizeof(struct STRING_BUFFER_T))); + MALLOC_CHECK(pBuf); + if (pBuf == NULL) + return (NULL); + memset(static_cast(pBuf), 0, sizeof(struct STRING_BUFFER_T)); + + pBuf->pText = static_cast(malloc(sizeof(char) * nSize)); + MALLOC_CHECK(pBuf->pText); + if (pBuf->pText == NULL) + return (NULL); + memset(static_cast(pBuf->pText), 0, sizeof(char) * nSize); + + pBuf->nIncrement = nIncrement; + pBuf->nBytesAllocated = nSize; + pBuf->nFlags = SB_INIT; + + return (pBuf); +} + +/* + * Routine: AddBuffer + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int AddBuffer(StringBuffer_t* pBuf, char* pStr) { + int nRemaining = pBuf->nBytesAllocated - pBuf->nBytesUsed, + nRequested = strlen(pStr); + + if (!nRequested) + return (0); + + while (nRequested >= nRemaining) { + pBuf->pText = static_cast(realloc( + static_cast(pBuf->pText), + pBuf->nBytesAllocated + pBuf->nIncrement)); + if (!pBuf->pText) + return (-1); + pBuf->nBytesAllocated += pBuf->nIncrement; + nRemaining += pBuf->nIncrement; + } + + strncat(pBuf->pText, pStr, pBuf->nBytesAllocated); + if (pBuf->nBytesUsed == 0) /* first string adds a terminator */ + pBuf->nBytesUsed = 1; + pBuf->nBytesUsed += nRequested; + + return (0); +} + +/* + * Routine: ResetStringBuffer + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int ResetBuffer(StringBuffer_t* pBuf) { + pBuf->nBytesUsed = 0; + if (pBuf->nBytesAllocated) + pBuf->pText[0] = '\0'; + + return (0); +} + +/* + * Routine: GetBuffer + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +char* GetBuffer(StringBuffer_t* pBuf) { + return (pBuf->pText); +} + +/* + * Routine: FreeBuffer + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void FreeBuffer(StringBuffer_t* pBuf) { + if (!pBuf) + return; + if (pBuf->pText) + free(static_cast(pBuf->pText)); + free(static_cast(pBuf)); + + return; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/address.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/address.cpp new file mode 100644 index 0000000000000..60b6df1540326 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/address.cpp @@ -0,0 +1,360 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "address.h" +#include +#include "columns.h" +#include "config.h" +#include "dist.h" +#include "genrand.h" +#include "permute.h" +#include "porting.h" +#include "r_params.h" +#include "scaling.h" +#include "tables.h" +#include "tdefs.h" + +static int s_nCountyCount = 0; +static int s_nCityCount = 0; + +void resetCountCount(void) { + s_nCountyCount = 0; + s_nCityCount = 0; + + return; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int mk_address(ds_addr_t* pAddr, int nColumn, DSDGenContext& dsdGenContext) { + int i = 0, nRegion = 0; + char *szZipPrefix = nullptr, szAddr[100]; + int nMaxCities, nMaxCounties; + tdef* pTdef; + + nMaxCities = static_cast(get_rowcount(ACTIVE_CITIES, dsdGenContext)); + nMaxCounties = static_cast(get_rowcount(ACTIVE_COUNTIES, dsdGenContext)); + + /* street_number is [1..1000] */ + genrand_integer( + &pAddr->street_num, DIST_UNIFORM, 1, 1000, 0, nColumn, dsdGenContext); + + /* street names are picked from a distribution */ + pick_distribution( + &pAddr->street_name1, "street_names", 1, 1, nColumn, dsdGenContext); + pick_distribution( + &pAddr->street_name2, "street_names", 1, 2, nColumn, dsdGenContext); + + /* street type is picked from a distribution */ + pick_distribution( + &pAddr->street_type, "street_type", 1, 1, nColumn, dsdGenContext); + + /* suite number is alphabetic 50% of the time */ + genrand_integer(&i, DIST_UNIFORM, 1, 100, 0, nColumn, dsdGenContext); + if (i & 0x01) { + auto result = sprintf(pAddr->suite_num, "Suite %d", (i >> 1) * 10); + if (result < 0) + perror("sprintf failed"); + } else { + auto result = sprintf(pAddr->suite_num, "Suite %c", ((i >> 1) % 25) + 'A'); + if (result < 0) + perror("sprintf failed"); + } + + pTdef = getTdefsByNumber( + getTableFromColumn(nColumn, dsdGenContext), dsdGenContext); + + /* city is picked from a distribution which maps to large/medium/small */ + if (pTdef->flags & FL_SMALL) { + i = static_cast(get_rowcount( + getTableFromColumn(nColumn, dsdGenContext), dsdGenContext)); + genrand_integer( + &i, + DIST_UNIFORM, + 1, + (nMaxCities > i) ? i : nMaxCities, + 0, + nColumn, + dsdGenContext); + dist_member(&pAddr->city, "cities", i, 1, dsdGenContext); + } else + pick_distribution(&pAddr->city, "cities", 1, 6, nColumn, dsdGenContext); + + /* county is picked from a distribution, based on population and keys the + * rest */ + if (pTdef->flags & FL_SMALL) { + i = (int)get_rowcount( + getTableFromColumn(nColumn, dsdGenContext), dsdGenContext); + genrand_integer( + &nRegion, + DIST_UNIFORM, + 1, + (nMaxCounties > i) ? i : nMaxCounties, + 0, + nColumn, + dsdGenContext); + dist_member(&pAddr->county, "fips_county", nRegion, 2, dsdGenContext); + } else + nRegion = pick_distribution( + &pAddr->county, "fips_county", 2, 1, nColumn, dsdGenContext); + + /* match state with the selected region/county */ + dist_member(&pAddr->state, "fips_county", nRegion, 3, dsdGenContext); + + /* match the zip prefix with the selected region/county */ + pAddr->zip = city_hash(0, pAddr->city); + /* 00000 - 00600 are unused. Avoid them */ + dist_member( + static_cast(&szZipPrefix), + "fips_county", + nRegion, + 5, + dsdGenContext); + if (!(szZipPrefix[0] - '0') && (pAddr->zip < 9400)) + pAddr->zip += 600; + pAddr->zip += (szZipPrefix[0] - '0') * 10000; + + auto result = sprintf( + szAddr, + "%d %s %s %s", + pAddr->street_num, + pAddr->street_name1, + pAddr->street_name2, + pAddr->street_type); + if (result < 0) + perror("sprintf failed"); + pAddr->plus4 = city_hash(0, szAddr); + dist_member(&pAddr->gmt_offset, "fips_county", nRegion, 6, dsdGenContext); + strcpy(pAddr->country, "United States"); + + return (0); +} + +/* + * Routine: mk_streetnumber + * Purpose: + * one of a set of routines that creates addresses + * Algorithm: + * Data Structures: + * + * Params: + * nTable: target table (and, by extension, address) to allow differing + *distributions dest: destination for the random number Returns: Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20030422 jms should be replaced if there is no table variation + */ +int mk_streetnumber(int nTable, int* dest, DSDGenContext& dsdGenContext) { + genrand_integer(dest, DIST_UNIFORM, 1, 1000, 0, nTable, dsdGenContext); + + return (0); +} + +/* + * Routine: mk_suitenumber() + * Purpose: + * one of a set of routines that creates addresses + * Algorithm: + * Data Structures: + * + * Params: + * nTable: target table (and, by extension, address) to allow differing + *distributions dest: destination for the random number Returns: Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20010615 JMS return code is meaningless + */ +int mk_suitenumber(int nTable, char* dest, DSDGenContext& dsdGenContext) { + int i; + + genrand_integer(&i, DIST_UNIFORM, 1, 100, 0, nTable, dsdGenContext); + if (i <= 50) { + genrand_integer(&i, DIST_UNIFORM, 1, 1000, 0, nTable, dsdGenContext); + auto result = sprintf(dest, "Suite %d", i); + if (result < 0) + perror("sprintf failed"); + } else { + genrand_integer(&i, DIST_UNIFORM, 0, 25, 0, nTable, dsdGenContext); + auto result = sprintf(dest, "Suite %c", i + 'A'); + if (result < 0) + perror("sprintf failed"); + } + + return (0); +} + +/* + * Routine: mk_streetname() + * Purpose: + * one of a set of routines that creates addresses + * Algorithm: + * use a staggered distibution and the 150 most common street names in the + *US Data Structures: + * + * Params: + * nTable: target table (and, by extension, address) to allow differing + *distributions dest: destination for the street name Returns: Called By: Calls: + * Assumptions: + * Side Effects: + * TODO: 20010615 JMS return code is meaningless + */ +int mk_streetname(int nTable, char* dest, DSDGenContext& dsdGenContext) { + char *pTemp1 = nullptr, *pTemp2 = nullptr; + + pick_distribution( + static_cast(&pTemp1), + "street_names", + (int)1, + (int)1, + nTable, + dsdGenContext); + pick_distribution( + static_cast(&pTemp2), + "street_names", + (int)1, + (int)2, + nTable, + dsdGenContext); + + if (pTemp1 && pTemp2) { + if (strlen(pTemp2)) { + auto result = sprintf(dest, "%s %s", pTemp1, pTemp2); + if (result < 0) + perror("sprintf failed"); + } else + strcpy(dest, pTemp1); + } + + return (0); +} + +/* + * Routine: mk_city + * Purpose: + * one of a set of routines that creates addresses + * Algorithm: + * use a staggered distibution of 1000 most common place names in the US + * Data Structures: + * + * Params: + * nTable: target table (and, by extension, address) to allow differing + *distributions dest: destination for the city name Returns: Called By: Calls: + * Assumptions: + * Side Effects: + * TODO: 20030423 jms should be replaced if there is no per-table variation + */ +int mk_city(int nTable, char** dest, DSDGenContext& dsdGenContext) { + pick_distribution( + static_cast(dest), + "cities", + static_cast(1), + static_cast(get_int("_SCALE_INDEX", dsdGenContext)), + 11, + dsdGenContext); + + return (0); +} + +/* + * Routine: city_hash() + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int city_hash(int nTable, char* name) { + char* cp; + int hash_value = 0, res = 0; + + for (cp = name; *cp; cp++) { + hash_value *= 26; + hash_value -= 'A'; + hash_value += *cp; + if (hash_value > 1000000) { + hash_value %= 10000; + res += hash_value; + hash_value = 0; + } + } + hash_value %= 1000; + res += hash_value; + res %= 10000; /* looking for a 4 digit result */ + + return (res); +} + +/* + * Routine: + * one of a set of routines that creates addresses + * Algorithm: + * use a compound distribution of the 3500 counties in the US + * Data Structures: + * + * Params: + * nTable: target table (and, by extension, address) to allow differing + *distributions dest: destination for the city name nRegion: the county selected + * city: the city name selected + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20010615 JMS return code is meaningless + */ +int mk_zipcode( + int nTable, + char* dest, + int nRegion, + char* city, + DSDGenContext& dsdGenContext) { + char* szZipPrefix = nullptr; + int nCityCode; + int nPlusFour; + + if (szZipPrefix) { + dist_member( + static_cast(&szZipPrefix), + "fips_county", + nRegion, + 5, + dsdGenContext); + nCityCode = city_hash(nTable, city); + genrand_integer( + &nPlusFour, DIST_UNIFORM, 1, 9999, 0, nTable, dsdGenContext); + auto result = + sprintf(dest, "%s%04d-%04d", szZipPrefix, nCityCode, nPlusFour); + if (result < 0) + perror("sprintf failed"); + } + + return (0); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/build_support.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/build_support.cpp new file mode 100644 index 0000000000000..f1191b0d6f5dc --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/build_support.cpp @@ -0,0 +1,442 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include +#include "config.h" +#include "porting.h" +#ifndef WIN32 +#include +#endif +#include +#include "StringBuffer.h" +#include "build_support.h" +#include "columns.h" +#include "constants.h" +#include "decimal.h" +#include "dist.h" +#include "error_msg.h" +#include "genrand.h" +#include "r_params.h" +#include "scaling.h" +#include "tables.h" +#include "tdefs.h" + +/* + * Routine: hierarchy_item + * Purpose: + * select the hierarchy entry for this level + * Algorithm: Assumes a top-down ordering + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +void hierarchy_item( + int h_level, + ds_key_t* id, + char** name, + ds_key_t kIndex, + DSDGenContext& dsdGenContext) { + static int nLastCategory = -1, nLastClass = -1, nBrandBase; + int nBrandCount = 0; + static char* szClassDistName = nullptr; + + switch (h_level) { + case I_CATEGORY: + nLastCategory = + pick_distribution(name, "categories", 1, 1, h_level, dsdGenContext); + *id = nLastCategory; + nBrandBase = nLastCategory; + nLastClass = -1; + break; + case I_CLASS: + if (nLastCategory == -1) + ReportErrorNoLine( + DBGEN_ERROR_HIERACHY_ORDER, "I_CLASS before I_CATEGORY", 1); + dist_member( + &szClassDistName, "categories", nLastCategory, 2, dsdGenContext); + nLastClass = pick_distribution( + name, szClassDistName, 1, 1, h_level, dsdGenContext); + nLastCategory = -1; + *id = nLastClass; + break; + case I_BRAND: { + if (nLastClass == -1) + ReportErrorNoLine( + DBGEN_ERROR_HIERACHY_ORDER, "I_BRAND before I_CLASS", 1); + dist_member(&nBrandCount, szClassDistName, nLastClass, 2, dsdGenContext); + *id = kIndex % nBrandCount + 1; + mk_word( + *name, + "brand_syllables", + nBrandBase * 10 + nLastClass, + 45, + I_BRAND, + dsdGenContext); + int idValue = static_cast(*id); + char sTemp[6 + std::to_string(idValue).size()]; + auto result = sprintf(sTemp, " #%d", idValue); + if (result < 0) + perror("sprintf failed"); + strcat(*name, sTemp); + *id += (nBrandBase * 1000 + nLastClass) * 1000; + break; + } + default: + auto result = printf( + "ERROR: Invalid call to hierarchy_item with argument '%d'\n", + h_level); + if (result < 0) + perror("sprintf failed"); + exit(1); + } + + return; +} + +/* + * Routine: mk_companyname() + * Purpose: + * yet another member of a set of routines used for address creation + * Algorithm: + * create a hash, based on an index value, so that the same result can be + *derived reliably and then build a word from a syllable set Data Structures: + * + * Params: + * char * dest: target for resulting name + * int nTable: to allow differing distributions + * int nCompany: index value + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20010615 JMS return code is meaningless + * 20030422 JMS should be replaced if there is no per-table variation + */ +int mk_companyname( + char* dest, + int nTable, + int nCompany, + DSDGenContext& dsdGenContext) { + mk_word(dest, "syllables", nCompany, 10, CC_COMPANY_NAME, dsdGenContext); + + return (0); +} + +/* + * Routine: set_locale() + * Purpose: + * generate a reasonable lattitude and longitude based on a region and the + *USGS data on 3500 counties in the US Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20011230 JMS set_locale() is just a placeholder; do we need geographic + *coords? + */ +int set_locale(int nRegion, decimal_t* longitude, decimal_t* latitude) { + static int init = 0; + static decimal_t dZero; + + if (!init) { + strtodec(&dZero, "0.00"); + init = 1; + } + + memcpy(longitude, &dZero, sizeof(decimal_t)); + memcpy(latitude, &dZero, sizeof(decimal_t)); + + return (0); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void bitmap_to_dist( + void* pDest, + const char* distname, + ds_key_t* modulus, + int vset, + int stream, + DSDGenContext& dsdGenContext) { + int32_t m, s; + unsigned int len = strlen(distname); + char msg[len + 31]; + + if ((s = distsize(distname, dsdGenContext)) == -1) { + auto result = sprintf(msg, "Invalid distribution name '%s'", distname); + if (result < 0) + perror("sprintf failed"); + INTERNAL(msg); + } + m = static_cast((*modulus % s) + 1); + *modulus /= s; + + dist_member(pDest, distname, m, vset, dsdGenContext); + + return; +} + +/* + * Routine: void dist_to_bitmap(int *pDest, char *szDistName, int nValueSet, int + * nWeightSet, int nStream) Purpose: Reverse engineer a composite key based on + * distributions Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void dist_to_bitmap( + int* pDest, + const char* szDistName, + int nValue, + int nWeight, + int nStream, + DSDGenContext& dsdGenContext) { + *pDest *= distsize(szDistName, dsdGenContext); + *pDest += pick_distribution( + NULL, szDistName, nValue, nWeight, nStream, dsdGenContext); + + return; +} + +/* + * Routine: void random_to_bitmap(int *pDest, int nDist, int nMin, int nMax, int + * nMean, int nStream) Purpose: Reverse engineer a composite key based on an + * integer range Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void random_to_bitmap( + int* pDest, + int nDist, + int nMin, + int nMax, + int nMean, + int nStream, + DSDGenContext& dsdGenContext) { + *pDest *= nMax; + *pDest += + genrand_integer(NULL, nDist, nMin, nMax, nMean, nStream, dsdGenContext); + + return; +} + +/* + * Routine: mk_word() + * Purpose: + * generate a gibberish word from a given syllable set + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +void mk_word( + char* dest, + const char* syl_set, + ds_key_t src, + int char_cnt, + int col, + DSDGenContext& dsdGenContext) { + ds_key_t i = src, nSyllableCount; + char* cp = nullptr; + + *dest = '\0'; + while (i > 0) { + nSyllableCount = distsize(syl_set, dsdGenContext); + dist_member( + &cp, + syl_set, + static_cast(i % nSyllableCount) + 1, + 1, + dsdGenContext); + i /= nSyllableCount; + if (static_cast(strlen(dest) + strlen(cp)) <= char_cnt) + strcat(dest, cp); + else + break; + } + + return; +} + +/* + * Routine: mk_surrogate() + * Purpose: create a character based surrogate key from a 64-bit value + * Algorithm: since the RNG routines produce a 32bit value, and surrogate keys + *can reach beyond that, use the RNG output to generate the lower end of a + *random string, and build the upper end from a ds_key_t Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: ltoc() + * Assumptions: output is a 16 character string. Space is not checked + * Side Effects: + * TODO: + * 20020830 jms may need to define a 64-bit form of htonl() for portable shift + *operations + */ +void ltoc(char* szDest, unsigned long nVal) { + char szXlate[16] = { + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P'}; + + char c; + for (int i = 0; i < 8; i++) { + c = szXlate[(static_cast(nVal) & 0xF)]; + *szDest++ = c; + nVal >>= 4; + } + *szDest = '\0'; +} + +void mk_bkey(char* szDest, ds_key_t kPrimary, int nStream) { + unsigned long nTemp; + + nTemp = static_cast(kPrimary >> 32); + ltoc(szDest, nTemp); + + nTemp = + static_cast(static_cast(kPrimary) & 0xFFFFFFFF); + ltoc(szDest + 8, nTemp); + + return; +} + +/* + * Routine: embed_string(char *szDest, char *szDist, int nValue, int nWeight, + * int nStream, DSDGenContext& dsdGenContext) Purpose: Algorithm: Data + * Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int embed_string( + char* szDest, + const char* szDist, + int nValue, + int nWeight, + int nStream, + DSDGenContext& dsdGenContext) { + int nPosition = 0; + char* szWord = nullptr; + + pick_distribution(&szWord, szDist, nValue, nWeight, nStream, dsdGenContext); + nPosition = genrand_integer( + NULL, + DIST_UNIFORM, + 0, + strlen(szDest) - strlen(szWord) - 1, + 0, + nStream, + dsdGenContext); + memcpy(&szDest[nPosition], szWord, sizeof(char) * strlen(szWord)); + + return (0); +} + +/* + * Routine: adjust the valid date window for source schema tables, based on + * based on the update count, update window size, etc. + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void setUpdateDateRange( + int nTable, + date_t* pMinDate, + date_t* pMaxDate, + DSDGenContext& dsdGenContext) { + static int nUpdateNumber; + + if (!dsdGenContext.setUpdateDateRange_init) { + nUpdateNumber = get_int("UPDATE", dsdGenContext); + dsdGenContext.setUpdateDateRange_init = 1; + } + + switch (nTable) /* no per-table changes at the moment; but could be */ + { + default: + strtodt(pMinDate, WAREHOUSE_LOAD_DATE); + pMinDate->julian += UPDATE_INTERVAL * (nUpdateNumber - 1); + jtodt(pMinDate, pMinDate->julian); + jtodt(pMaxDate, pMinDate->julian + UPDATE_INTERVAL); + break; + } + + return; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/date.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/date.cpp new file mode 100644 index 0000000000000..ff02dd94e01e6 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/date.cpp @@ -0,0 +1,610 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include +#include "config.h" +#include "porting.h" +#ifndef USE_STDLIB_H +#include +#endif +#include +#include +#include "date.h" +#include "dist.h" +#include "mathops.h" + +#define D_CHARS "ymdYMD24" /* valid characters in a DBGDATE setting */ +#define MIN_DATE_INT 18000101 + +static int m_days[2][13] = { + {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, + {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}}; +static char* qtr_start[5] = {NULL, "01-01", "04-01", "07-01", "10-01"}; +char* weekday_names[8] = { + NULL, + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday"}; +/* + * Routine: mk_date(void) + * Purpose: initialize a date_t + * Algorithm: + * Data Structures: + * Params: + * Returns: date_t * + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +date_t* mk_date(void) { + auto res = (date_t*)malloc(sizeof(struct DATE_T)); + MALLOC_CHECK(res); + + res->flags = 0; + res->year = 0; + res->month = 0; + res->day = 0; + res->julian = 0; + + return (res); +} +/* + * Routine: strtotime(char *str) + * Purpose: convert a string from the time to the number of seconds since + * midnight Algorithm: Data Structures: Params: Returns: int Called By: Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int strtotime(char* str) { + int hour, min, sec, res = 0; + + if (sscanf(str, "%d:%d:%d", &hour, &min, &sec) != 3) { + if (sscanf(str, "%d:%d", &hour, &min) != 2) { + INTERNAL("Invalid time format"); + } + sec = 0; + } + + if (hour > 23 || hour < 0) + INTERNAL("Invalid time format"); + if (min > 59 || min < 0) + INTERNAL("Invalid time format"); + if (sec > 59 || sec < 0) + INTERNAL("Invalid time format"); + + res = hour * 3600 + min * 60 + sec; + + return (res); +} + +/* + * Routine: strtodate(char *str) + * Purpose: initialize a date_t + * Algorithm: + * Data Structures: + * Params: + * Returns: date_t * + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +date_t* strtodate(char* str) { + auto res = (date_t*)(malloc(sizeof(struct DATE_T))); + MALLOC_CHECK(res); + + if (sscanf(str, "%d-%d-%d", &res->year, &res->month, &res->day) != 3) + INTERNAL("Badly formed string in call to strtodate()"); + res->flags = 0; + res->julian = dttoj(res); + + return (res); +} + +/* + * Routine: jtodt(int src, date_t *dest) + * Purpose: convert a number of julian days to a date_t + * Algorithm: Fleigel and Van Flandern (CACM, vol 11, #10, Oct. 1968, p. 657) + * Data Structures: + * + * Params: source integer: days since big bang + * Returns: date_t *; NULL on failure + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +int jtodt(date_t* dest, int src) { + long i = 0, j = 0, l = 0, n = 0; + + if (src < 0) + return (-1); + + dest->julian = src; + l = src + 68569; + n = static_cast(floor((4 * l) / 146097)); + l = l - static_cast(floor((146097 * n + 3) / 4)); + i = static_cast(floor((4000 * (l + 1) / 1461001))); + l = l - static_cast(floor((1461 * i) / 4) + 31); + j = static_cast(floor((80 * l) / 2447)); + dest->day = l - static_cast(floor((2447 * j) / 80)); + l = static_cast(floor(j / 11)); + dest->month = j + 2 - 12 * l; + dest->year = 100 * (n - 49) + i + l; + + return (0); +} + +/* + * Routine: dttoj(date_t *) + * Purpose: convert a date_t to a number of julian days + * Algorithm: http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int dttoj(date_t* dt) { + int y, m, res = 0; + + y = dt->year; + m = dt->month; + if (m <= 2) { + m += 12; + y -= 1; + } + + /* + * added 1 to get dttoj and jtodt to match + */ + res = dt->day + (153 * m - 457) / 5 + 365 * y + + static_cast(floor(y / 4)) - static_cast(floor(y / 100)) + + static_cast(floor(y / 400)) + 1721118 + 1; + + return (res); +} + +/* + * Routine: strtodt() + * Purpose: Convert an ascii string to a date_t structure + * Algorithm: + * Data Structures: + * + * Params: char *s, date_t *dest + * Returns: int; 0 on success + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: Need to allow for date formats other than Y4MD- + */ +int strtodt(date_t* dest, char* s) { + int nRetCode = 0; + + if (s == NULL) { + dest = NULL; + return (-1); + } + + if (sscanf(s, "%4d-%d-%d", &dest->year, &dest->month, &dest->day) != 3) { + auto result = fprintf( + stderr, "ERROR: Invalid string to date conversion in strtodt\n"); + if (result < 0) + perror("sprintf failed"); + nRetCode = -1; + } + + dest->julian = dttoj(dest); + + return (nRetCode); +} + +/* + * Routine: dttostr(date_t *d) + * Purpose: convert a date_t structure to a string + * Algorithm: + * Data Structures: + * + * Params: + * Returns: char *; NULL on failure + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20000110 Need to handle more than Y4MD- + */ +char* dttostr(date_t* d) { + static char* res = nullptr; + static int init = 0; + + if (!init) { + res = (char*)malloc(sizeof(char) * 11); + MALLOC_CHECK(res); + init = 1; + } + + if (d == NULL) + return (NULL); + + if (strlen(res) == 11) { + auto result = sprintf(res, "%4d-%02d-%02d", d->year, d->month, d->day); + if (result < 0) + perror("sprintf failed"); + } + + return (res); +} + +/* + * Routine: date_init + * Purpose: set the date handling parameters + * Algorithm: + * Data Structures: + * + * Params: None + * Returns: int; 0 on success + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int date_init(void) { + auto result = printf("date_init is not yet complete\n"); + if (result < 0) + perror("sprintf failed"); + exit(1); + return (0); +} + +/* + * Routine: date_t_op(int op, date_t *operand1, date_t *operand2) + * Purpose: execute arbitrary binary operations on date_t's + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20010806 jms Return code is meaningless + */ +int date_t_op(date_t* dest, int op, date_t* d1, date_t* d2) { + int tJulian; + char tString[11]; + date_t tDate; + + switch (op) { + case OP_FIRST_DOM: /* set to first day of month */ + tJulian = d1->julian - d1->day + 1; + jtodt(dest, tJulian); + break; + case OP_LAST_DOM: /* set to last day of month */ + tJulian = d1->julian - d1->day + m_days[is_leap(d1->year)][d1->month]; + jtodt(dest, tJulian); + break; + case OP_SAME_LY: + if (is_leap(d1->year) && (d1->month == 2) && (d1->day == 29)) { + auto result = sprintf(tString, "%d-02-28", d1->year - 1); + if (result < 0) + perror("sprintf failed"); + } else { + auto result = + sprintf(tString, "%4d-%02d-%02d", d1->year - 1, d1->month, d1->day); + if (result < 0) + perror("sprintf failed"); + } + strtodt(dest, tString); + break; + case OP_SAME_LQ: + switch (d1->month) { + case 1: + case 2: + case 3: { + auto result = sprintf(tString, "%4d-%s", d1->year, qtr_start[1]); + if (result < 0) + perror("sprintf failed"); + strtodt(&tDate, tString); + tJulian = d1->julian - tDate.julian; + sprintf(tString, "%4d-%s", d1->year - 1, qtr_start[4]); + if (result < 0) + perror("sprintf failed"); + strtodt(&tDate, tString); + tJulian += tDate.julian; + jtodt(dest, tJulian); + break; + } + case 4: + case 5: + case 6: { + auto result = sprintf(tString, "%4d-%s", d1->year, qtr_start[2]); + if (result < 0) + perror("sprintf failed"); + strtodt(&tDate, tString); + tJulian = d1->julian - tDate.julian; + sprintf(tString, "%4d-%s", d1->year, qtr_start[1]); + if (result < 0) + perror("sprintf failed"); + strtodt(&tDate, tString); + tJulian += tDate.julian; + jtodt(dest, tJulian); + break; + } + case 7: + case 8: + case 9: { + auto result = sprintf(tString, "%4d-%s", d1->year, qtr_start[3]); + if (result < 0) + perror("sprintf failed"); + strtodt(&tDate, tString); + tJulian = d1->julian - tDate.julian; + sprintf(tString, "%4d-%s", d1->year, qtr_start[2]); + if (result < 0) + perror("sprintf failed"); + strtodt(&tDate, tString); + tJulian += tDate.julian; + jtodt(dest, tJulian); + break; + } + case 10: + case 11: + case 12: { + auto result = sprintf(tString, "%4d-%s", d1->year, qtr_start[4]); + if (result < 0) + perror("sprintf failed"); + strtodt(&tDate, tString); + tJulian = d1->julian - tDate.julian; + sprintf(tString, "%4d-%s", d1->year, qtr_start[3]); + if (result < 0) + perror("sprintf failed"); + strtodt(&tDate, tString); + tJulian += tDate.julian; + jtodt(dest, tJulian); + break; + } + } + break; + } + + return (0); +} + +/* + * Routine: itodt(date_t *d, int src) + * Purpose: convert a number of days to a date_t + * Algorithm: NOTE: sets only julian field + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int itodt(date_t* dest, int src) { + dest->julian = src; + + return (0); +} + +/* + * Routine: set_dow(date *d) + * Purpose: perpetual calendar stuff + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +int set_dow(date_t* d) { + int doomsday[4] = {3, 2, 0, 5}; + int known[13] = {0, 3, 0, 0, 4, 9, 6, 11, 8, 5, 10, 7, 12}; + int last_year = -1, dday; + int res = 0, q = 0, r = 0, s = 0; + + if (d->year != last_year) { + if (is_leap(d->year)) { + /* adjust the known dates for january and february */ + known[1] = 4; + known[2] = 1; + } else { + known[1] = 3; + known[2] = 0; + } + + /* calculate the doomsday for the century */ + dday = d->year / 100; + dday -= 15; + dday %= 4; + dday = doomsday[dday]; + + /* and then calculate the doomsday for the year */ + q = d->year % 100; + r = q % 12; + q /= 12; + s = r / 4; + dday += q + r + s; + dday %= 7; + last_year = d->year; + } + + res = d->day; + res -= known[d->month]; + while (res < 0) + res += 7; + while (res > 6) + res -= 7; + + res += dday; + res %= 7; + + return (res); +} + +/* + * Routine: is_leap(year) + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int is_leap(int year) { + return ( + ((year % 100) == 0) ? ((((year % 400) % 2) == 0) ? 1 : 0) + : ((year % 4) == 0) ? 1 + : 0); +} + +/* + * Routine: day_number(date_t *) + * Purpose: + * Algorithm: NOTE: this is NOT the ordinal day in the year, but the ordinal + *reference into the calendar distribution for the day; in particular, this + *needs to skip over the leap day Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int day_number(date_t* d) { + return (m_days[is_leap(d->year)][d->month] + d->day); +} + +/* + * Routine: getDateWeightFromJulian(jDay, nDistribution) + * Purpose: return the weight associated with a particular julian date and + * distribution Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int getDateWeightFromJulian( + int jDay, + int nDistribution, + DSDGenContext& dsdGenContext) { + date_t dTemp; + jtodt(&dTemp, jDay); + int nDay; + nDay = day_number(&dTemp); + + return (dist_weight( + NULL, + "calendar", + nDay, + nDistribution + is_leap(dTemp.year), + dsdGenContext)); +} + +/* + * Routine: date_part(date_t *, int part) + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int date_part(date_t* d, int part) { + switch (part) { + case 1: + return (d->year); + case 2: + return (d->month); + case 3: + return (d->day); + default: + INTERNAL("Invalid call to date_part()"); + return (-1); + } +} + +#ifdef TEST +main() { + date_t* d; + int ret; + + d = mk_date(); + strtodt(d, "1776-07-04"); + ret = set_dow(d); + printf("set_dow(\"1776-07-04\"): wanted 4 got %d\n", ret); + if (ret != 4) { + exit(1); + } + strtodt(d, "2000-01-01"); + ret = set_dow(d); + printf("set_dow(\"2000-01-01\"): wanted 6 got %d\n", ret); + if (ret != 6) { + exit(1); + } + + strtodt(d, "1970-01-01"); + if ((ret = dttoj(d)) != 2440588) { + printf("dttoj returned %d\n", ret); + exit(1); + } + + d->year = 1; + d->month = 11; + d->date = 11; + jtodt(d, 2440588); + if ((d->year != 1970) || (d->month != 1) || (d->date != 1)) { + printf("jtodt failed got: "); + printf("%4d-%02d-%02d", d->year, d->month, d->date); + exit(1); + } + return (0); +} +#endif /* TEST */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/dbgen_version.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/dbgen_version.cpp new file mode 100644 index 0000000000000..1b12de84597d4 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/dbgen_version.cpp @@ -0,0 +1,113 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "dbgen_version.h" +#include +#include +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "dist.h" +#include "misc.h" +#include "porting.h" +#include "tables.h" + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int mk_dbgen_version( + void* pDest, + ds_key_t kIndex, + DSDGenContext& dsdGenContext) { + time_t ltime = time_t(); + struct tm* pTimeStamp = nullptr; + struct DBGEN_VERSION_TBL* r; + + if (pDest == NULL) + r = &dsdGenContext.g_dbgen_version; + else + r = static_cast(pDest); + + if (!dsdGenContext.mk_dbgen_version_init) { + memset(&dsdGenContext.g_dbgen_version, 0, sizeof(struct DBGEN_VERSION_TBL)); + dsdGenContext.mk_dbgen_version_init = 1; + } + + time(<ime); /* Get time in seconds */ + pTimeStamp = localtime(<ime); /* Convert time to struct */ + + auto result = sprintf( + r->szDate, + "%4d-%02d-%02d", + pTimeStamp->tm_year + 1900, + pTimeStamp->tm_mon + 1, + pTimeStamp->tm_mday); + if (result < 0) + perror("sprintf failed"); + result = sprintf( + r->szTime, + "%02d:%02d:%02d", + pTimeStamp->tm_hour, + pTimeStamp->tm_min, + pTimeStamp->tm_sec); + if (result < 0) + perror("sprintf failed"); + result = sprintf( + r->szVersion, "%d.%d.%d%s", VERSION, RELEASE, MODIFICATION, PATCH); + if (result < 0) + perror("sprintf failed"); + strcpy(r->szCmdLineArgs, "--this_table_is_rather_pointless"); + + return (0); +} +// +///* +// * Routine: +// * Purpose: +// * Algorithm: +// * Data Structures: +// * +// * Params: +// * Returns: +// * Called By: +// * Calls: +// * Assumptions: +// * Side Effects: +// * TODO: None +// */ +// int pr_dbgen_version(void *pSrc) { +// struct DBGEN_VERSION_TBL *r; +// +// if (pSrc == NULL) +// r = &g_dbgen_version; +// else +// r = pSrc; +// +// print_start(DBGEN_VERSION); +// print_varchar(DV_VERSION, r->szVersion, 1); +// print_varchar(DV_CREATE_DATE, r->szDate, 1); +// print_varchar(DV_CREATE_TIME, r->szTime, 1); +// print_varchar(DV_CMDLINE_ARGS, r->szCmdLineArgs, 0); +// print_end(DBGEN_VERSION); +// +// return (0); +//} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/decimal.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/decimal.cpp new file mode 100644 index 0000000000000..898277ec5adee --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/decimal.cpp @@ -0,0 +1,347 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "config.h" +#include "porting.h" +#ifndef USE_STDLIB_H +#include +#endif +#include +#include "decimal.h" +#include "dist.h" +#include "mathops.h" + +/* + * Routine: set_precision(decimal_t *dest, int size, int precision) + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: None + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void set_precision(decimal_t* dest, int scale, int precision) { + dest->scale = scale; + dest->precision = precision; + dest->number = 0; + dest->flags = 0; + + return; +} + +/* + * Routine: mk_decimal(int size, int precision) + * Purpose: initialize a decimal_t + * Algorithm: + * Data Structures: + * + * Params: int size: total number of places in the decimal + * int precision: number of places in the fraction + * Returns: decimal_t * + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +decimal_t* mk_decimal(int s, int p) { + auto res = (decimal_t*)malloc(sizeof(struct DECIMAL_T)); + + if ((s < 0) || (p < 0)) + return (NULL); + + MALLOC_CHECK(res); + + res->flags = 0; + res->scale = s; + res->precision = p; + res->flags = + static_cast(static_cast(res->flags) | FL_INIT); + + return (res); +} + +/* + * Routine: itodec(int src, decimal_t *dest) + * Purpose: convert an integer to a decimal_t + * Algorithm: + * Data Structures: + * + * Params: source integer + * Returns: decimal_t * + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20000104 need to set errno on error + */ +int itodec(decimal_t* dest, int src) { + int scale = 1, bound = 1; + + while ((bound * 10) <= src) { + scale += 1; + bound *= 10; + } + + dest->precision = 0; + dest->scale = scale; + dest->number = src; + + return (0); +} + +/* + * Routine: ftodec(double f, decimal_t *dec) + * Purpose: Convert a double to a decimal_t + * Algorithm: + * Data Structures: + * + * Params: double f + * Returns: decimal_t * + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int ftodec(decimal_t* dest, double f) { + static char valbuf[20]; + + auto result = snprintf(valbuf, sizeof(valbuf), "%f", f); + if (result < 0) + perror("sprintf failed"); + + return (strtodec(dest, valbuf)); +} + +/* + * Routine: strtodec() + * Purpose: Convert an ascii string to a decimal_t structure + * Algorithm: + * Data Structures: + * + * Params: char *s + * Returns: decimal_t * + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int strtodec(decimal_t* dest, char* s) { + int i; + char* d_pt; + char valbuf[20]; + + if (strlen(s) < 20) { + strcpy(valbuf, s); + } + dest->flags = 0; + if ((d_pt = strchr(valbuf, '.')) == NULL) { + dest->scale = strlen(valbuf); + dest->number = atoi(valbuf); + dest->precision = 0; + } else { + *d_pt = '\0'; + d_pt += 1; + dest->scale = strlen(valbuf); + dest->number = atoi(valbuf); + dest->precision = strlen(d_pt); + for (i = 0; i < dest->precision; i++) + dest->number *= 10; + dest->number += atoi(d_pt); + } + + if (*s == '-' && dest->number > 0) + dest->number *= -1; + + return (0); +} + +/* + * Routine: dectostr(decimal_t *d, char *buf) + * Purpose: convert a decimal structure to a string + * Algorithm: + * Data Structures: + * + * Params: + * Returns: char *; NULL on success + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int dectostr(char* dest, decimal_t* d, DSDGenContext& dsdGenContext) { + ds_key_t number; + int i; + static char szFormat[80]; + + if (!dsdGenContext.dectostr_init) { + auto result = sprintf(szFormat, "%s.%s", HUGE_FORMAT, HUGE_FORMAT); + if (result < 0) + perror("sprintf failed"); + dsdGenContext.dectostr_init = 1; + } + + if (d == NULL || dest == NULL) + return (-1); + for (number = d->number, i = 0; i < d->precision; i++) + number /= 10; + + dest = (char*)malloc(160); + auto result = sprintf(dest, szFormat, number, d->number - number); + if (result < 0) + perror("sprintf failed"); + + return (0); +} + +/* + * Routine: dectof(float *dest, decimal_t *d) + * Purpose: convert a decimal structure to a double + * Algorithm: + * Data Structures: + * + * Params: + * Returns: char *; NULL on success + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int dectoflt(double* dest, decimal_t* d) { + if ((dest == NULL) || (d == NULL)) + return (-1); +#ifdef WIN32 +#pragma warning(disable : 4244) +#endif + *dest = d->number; +#ifdef WIN32 +#pragma warning(default : 4244) +#endif + while (--d->precision > 0) + *dest /= 10.0; + + return (0); +} + +/* + * Routine: decimal_t_op(int op, decimal_t *operand1, decimal_t *operand2) + * Purpose: execute arbitrary binary operations on decimal_t's + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int decimal_t_op(decimal_t* dest, int op, decimal_t* d1, decimal_t* d2) { + int res, np; + float f1, f2; + + if ((d1 == NULL) || (d2 == NULL)) + return (-1); + + dest->scale = (d1->scale > d2->scale) ? d1->scale : d2->scale; + if (d1->precision > d2->precision) { + dest->precision = d1->precision; + } else { + dest->precision = d2->precision; + } + + switch (op) { + case OP_PLUS: + dest->number = d1->number + d2->number; + break; + case OP_MINUS: + dest->number = d1->number - d2->number; + break; + case OP_MULT: + res = d1->precision + d2->precision; + dest->number = d1->number * d2->number; + while (res-- > dest->precision) + dest->number /= 10; + break; + case OP_DIV: + f1 = static_cast(d1->number); + np = d1->precision; + while (np < dest->precision) { + f1 *= 10.0; + np += 1; + } + np = 0; + while (np < dest->precision) { + f1 *= 10.0; + np += 1; + } + f2 = static_cast(d2->number); + np = d2->precision; + while (np < dest->precision) { + f2 *= 10.0; + np += 1; + } + + dest->number = static_cast(f1 / f2); + break; + default: { + auto result = printf("decimal_t_op does not support op %d\n", op); + if (result < 0) + perror("sprintf failed"); + exit(1); + break; + } + } + + return (0); +} + +#ifdef TEST +main() { + decimal_t* res; + int code; + + /* mk_decimal */ + res = mk_decimal(5, 2); + if (res == NULL) { + printf("mk_decimal returned NULL\n"); + exit(-1); + } + + /* itodec */ + itodec(res, 0); + code = dectoi(res); + if (code) { + printf("r_decimal:itodec(0, res) != 0 (%d)\n", code); + exit(-1); + } + + itodec(res, 999); + code = dectoi(res); + if (code != 999) { + printf("r_decimal:itodec(999, res) != 0 (%d)\n", code); + exit(-1); + } + + exit(0); +} +#endif /* TEST */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/dist.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/dist.cpp new file mode 100644 index 0000000000000..778d72497a0b9 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/dist.cpp @@ -0,0 +1,1142 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "config.h" +#include "porting.h" + +#include +#include +#include + +#define MAX_LINE_LEN 120 +#ifdef WIN32 +#define OPTION_START '/' +#else +#define OPTION_START '-' +#endif +#ifdef _WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#endif +#ifdef NCR +#include +#endif +#ifndef USE_STDLIB_H +#include +#endif +#include "config.h" +#include "date.h" +#include "dcomp.h" +#include "decimal.h" +#include "dist.h" +#include "error_msg.h" +#include "genrand.h" +#include "r_params.h" +#include "tpcds_idx.hpp" +#ifdef TEST +option_t options[] = { + {"DISTRIBUTIONS", + OPT_STR, + 2, + "read distributions from file ", + NULL, + "tester_dist.idx"}, + NULL}; + +char params[2]; +struct { + char* name; +} tdefs[] = {NULL}; +#endif + +/* NOTE: these need to be in sync with a_dist.h */ +#define D_NAME_LEN 20 +#define FL_LOADED 0x01 +static int load_dist(d_idx_t* d); + +#include +#include "config.h" +#include "porting.h" +#include "r_params.h" + +/* + * Routine: release(char *param_name, char *msg) + * Purpose: display version information + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int printReleaseInfo( + const char* param_name, + const char* msg, + DSDGenContext& dsdGenContext) { + auto result = fprintf( + stderr, + "%s Population Generator (Version %d.%d.%d%s)\n", + get_str("PROG", dsdGenContext), + VERSION, + RELEASE, + MODIFICATION, + PATCH); + if (result < 0) + perror("sprintf failed"); + result = fprintf(stderr, "Copyright %s %s\n", COPYRIGHT, C_DATES); + if (result < 0) + perror("sprintf failed"); + + exit(0); +} + +/* + * Routine: usage(char *param_name, char *msg) + * Purpose: display a usage message, with an optional error message + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int usage( + const char* param_name, + const char* msg, + DSDGenContext& dsdGenContext) { + init_params(dsdGenContext); + + auto result = fprintf( + stderr, + "%s Population Generator (Version %d.%d.%d%s)\n", + get_str("PROG", dsdGenContext), + VERSION, + RELEASE, + MODIFICATION, + PATCH); + if (result < 0) + perror("sprintf failed"); + result = fprintf(stderr, "Copyright %s %s\n", COPYRIGHT, C_DATES); + if (result < 0) + perror("sprintf failed"); + + if (msg != NULL) + printf("\nERROR: %s\n\n", msg); + + printf("\n\nUSAGE: %s [options]\n", get_str("PROG", dsdGenContext)); + printf( + "\nNote: When defined in a parameter file (using -p), parmeters " + "should\n"); + printf("use the form below. Each option can also be set from the command\n"); + printf("line, using a form of '%cparam [optional argument]'\n", OPTION_START); + printf("Unique anchored substrings of options are also recognized, and \n"); + printf( + "case is ignored, so '%csc' is equivalent to '%cSCALE'\n\n", + OPTION_START, + OPTION_START); + printf("General Options\n===============\n"); + print_options(dsdGenContext.options, 0, dsdGenContext); + printf("\n"); + printf("Advanced Options\n===============\n"); + print_options(dsdGenContext.options, 1, dsdGenContext); + printf("\n"); + exit((msg == NULL) ? 0 : 1); +} + +/* + * Routine: read_file(char *param_name, char *fname) + * Purpose: process a parameter file + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int read_file( + const char* param_name, + const char* optarg, + DSDGenContext& dsdGenContext) { + FILE* fp = nullptr; + char* cp = nullptr; + char line[MAX_LINE_LEN]; + char name[100]; + int index = 0; + + init_params(dsdGenContext); + + if ((fp = fopen(optarg, "r")) == NULL) + return (-1); + while (fgets(line, MAX_LINE_LEN, fp) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + if ((cp = strchr(line, '-')) != NULL) + if (*(cp + 1) == '-') + *cp = '\0'; + if ((cp = strtok(line, " \t=\n")) != NULL) { + strcpy(name, cp); + index = fnd_param(name, dsdGenContext); + if (index == -1) + continue; /* JMS: errors are silently ignored */ + cp += strlen(cp) + 1; + while (*cp && strchr(" \t =", *cp)) + cp++; + + /* command line options over-ride those in a file */ + if (static_cast(dsdGenContext.options[index].flags) & + OPT_SET) + continue; + + if (*cp) { + switch (static_cast(dsdGenContext.options[index].flags) & + TYPE_MASK) { + case OPT_INT: + if ((cp = strtok(cp, " \t\n")) != NULL) + set_option(name, cp); + break; + case OPT_STR: + case OPT_FLG: + set_option(name, cp); + break; + } + } + } + } + + fclose(fp); + + return (0); +} + +/* + * Routine: set_scale() + * Purpose: link SCALE and SCALE_INDEX + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int SetScaleIndex( + const char* szName, + const char* szValue, + DSDGenContext& dsdGenContext) { + char szScale[2]; + int nScale; + + if ((nScale = atoi(szValue)) == 0) + nScale = 1; + + nScale = 1 + static_cast(log10(nScale)); + szScale[0] = '0' + nScale; + szScale[1] = '\0'; + + set_int("_SCALE_INDEX", szScale, dsdGenContext); + + return (atoi(szValue)); +} + +/* + * Routine: print_options(struct OPTION_T *o, int file, int depth) + * Purpose: print a summary of options + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +static void print_options( + struct OPTION_T* o, + int bShowOptional, + DSDGenContext& dsdGenContext) { + int w_adjust = 0, bShow = 0, nCount = 0; + + for (int i = 0; dsdGenContext.options[i].name != NULL; i++) { + /* + * options come in two groups, general and "hidden". Decide which group + * to show in this pass, and ignore others + */ + bShow = 0; + if (bShowOptional && (static_cast(o[i].flags) & OPT_ADV)) + bShow = 1; + if (!bShowOptional && !(static_cast(o[i].flags) & OPT_ADV)) + bShow = 1; + + if (!bShow || (static_cast(o[i].flags) & OPT_HIDE)) + continue; + + nCount += 1; + printf("%s = ", o[i].name); + w_adjust = 15 - strlen(o[i].name); + if (static_cast(o[i].flags) & OPT_INT) + printf(" "); + else if (static_cast(o[i].flags) & OPT_STR) + printf(" "); + else if (static_cast(o[i].flags) & OPT_SUB) + printf(" "); + else if (static_cast(o[i].flags) & OPT_FLG) + printf(" [Y|N] "); + else + printf(" "); + printf("%*s-- %s", w_adjust, " ", o[i].usage); + if (static_cast(o[i].flags) & OPT_NOP) + printf(" NOT IMPLEMENTED"); + printf("\n"); + } + + if (nCount == 0) + printf("None defined.\n"); + + return; +} + +/* + * Routine: di_compare() + * Purpose: comparison routine for two d_idx_t entries; used by qsort + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int di_compare(const void* op1, const void* op2) { + d_idx_t *ie1 = (d_idx_t*)op1, *ie2 = (d_idx_t*)op2; + + return (strcasecmp(ie1->name, ie2->name)); +} + +int load_dists() { + /* open the dist file */ + auto read_ptr = tpcds_idx; + int32_t temp; + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + int entry_count = ntohl(temp); + read_ptr = tpcds_idx + tpcds_idx_len - (entry_count * IDX_SIZE); + for (int i = 0; i < entry_count; i++) { + d_idx_t entry; + memset(&entry, 0, sizeof(const d_idx_t)); + memcpy(entry.name, read_ptr, D_NAME_LEN); + read_ptr += D_NAME_LEN; + entry.name[D_NAME_LEN] = '\0'; + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + entry.index = ntohl(temp); + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + entry.offset = ntohl(temp); + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + entry.str_space = ntohl(temp); + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + entry.length = ntohl(temp); + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + entry.w_width = ntohl(temp); + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + entry.v_width = ntohl(temp); + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + entry.name_space = ntohl(temp); + load_dist(&entry); + auto lockedMap = idx_.wlock(); + lockedMap->emplace(std::string(entry.name), entry); + } + return (1); +} +/* + * Routine: find_dist(char *name, DSDGenContext& dsdGenContext) + * Purpose: translate from dist_t name to d_idx_t * + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +const d_idx_t* find_dist(const char* name) { + std::call_once(initFlag_, []() { load_dists(); }); + + std::string key(name); + auto lockedMap = idx_.rlock(); + if (lockedMap->find(key) != lockedMap->end()) { + return &(lockedMap->at(key)); + } + return nullptr; +} + +/* + * Routine: load_dist(int fd, dist_t *d, DSDGenContext& dsdGenContext) + * Purpose: load a particular distribution + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +static int load_dist(d_idx_t* di) { + int res = 0, i = 0, j = 0; + dist_t* d; + int32_t temp; + FILE* ifp; + + if (di->flags != FL_LOADED) /* make sure no one beat us to it */ + { + auto read_ptr = tpcds_idx; + read_ptr += di->offset; + di->dist = static_cast(malloc(sizeof(struct DIST_T))); + MALLOC_CHECK(di->dist); + d = di->dist; + + /* load the type information */ + d->type_vector = static_cast(malloc(sizeof(int32_t) * di->v_width)); + MALLOC_CHECK(d->type_vector); + for (i = 0; i < di->v_width; i++) { + if (read_ptr) + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + d->type_vector[i] = ntohl(temp); + } + + /* load the weights */ + d->weight_sets = static_cast(malloc(sizeof(int*) * di->w_width)); + d->maximums = static_cast(malloc(sizeof(int32_t) * di->w_width)); + MALLOC_CHECK(d->weight_sets); + MALLOC_CHECK(d->maximums); + for (i = 0; i < di->w_width; i++) { + *(d->weight_sets + i) = + static_cast(malloc(di->length * sizeof(int32_t))); + MALLOC_CHECK(*(d->weight_sets + i)); + d->maximums[i] = 0; + for (j = 0; j < di->length; j++) { + if (read_ptr) + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + *(*(d->weight_sets + i) + j) = ntohl(temp); + /* calculate the maximum weight and convert sets to cummulative + */ + d->maximums[i] += d->weight_sets[i][j]; + d->weight_sets[i][j] = d->maximums[i]; + } + } + + /* load the value offsets */ + d->value_sets = static_cast(malloc(sizeof(int*) * di->v_width)); + MALLOC_CHECK(d->value_sets); + for (i = 0; i < di->v_width; i++) { + *(d->value_sets + i) = + static_cast(malloc(di->length * sizeof(int32_t))); + MALLOC_CHECK(*(d->value_sets + i)); + for (j = 0; j < di->length; j++) { + if (read_ptr) + memcpy(&temp, read_ptr, sizeof(int32_t)); + read_ptr += sizeof(int32_t); + *(*(d->value_sets + i) + j) = ntohl(temp); + } + } + + /* load the column aliases, if they were defined */ + if (di->name_space) { + d->names = static_cast(malloc(di->name_space)); + MALLOC_CHECK(d->names); + if (d->names && read_ptr) + memcpy(d->names, read_ptr, di->name_space * sizeof(char)); + read_ptr += di->name_space * sizeof(char); + } + + /* and finally the values themselves */ + d->strings = static_cast(malloc(sizeof(char) * di->str_space)); + MALLOC_CHECK(d->strings); + if (d->strings && read_ptr) + memcpy(d->strings, read_ptr, di->str_space * sizeof(char)); + read_ptr += di->str_space * sizeof(char); + di->flags = FL_LOADED; + } + + return (res); +} + +/* + * Routine: void *dist_op() + * Purpose: select a value/weight from a distribution + * Algorithm: + * Data Structures: + * + * Params: char *d_name + * int vset: which set of values + * int wset: which set of weights + * Returns: appropriate data type cast as a void * + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20000317 Need to be sure this is portable to NT and others + */ +int dist_op( + void* dest, + int op, + const char* d_name, + int vset, + int wset, + int stream, + DSDGenContext& dsdGenContext) { + dist_t* dist = nullptr; + int level = 0, index = 0, dt = 0; + char* char_val = nullptr; + int i_res = 1; + const d_idx_t* d; + + if ((d = find_dist(d_name)) == nullptr) { + char msg[40 + strlen(d_name)]; + auto result = sprintf(msg, "Invalid distribution name '%s'", d_name); + if (result < 0) + perror("sprintf failed"); + INTERNAL(msg); + assert(d != nullptr); + } + + dist = d->dist; + + if (op == 0) { + genrand_integer( + &level, + DIST_UNIFORM, + 1, + dist->maximums[wset - 1], + 0, + stream, + dsdGenContext); + while (level > dist->weight_sets[wset - 1][index] && index < d->length) + index += 1; + dt = vset - 1; + if ((index >= d->length) || (dt > d->v_width)) + INTERNAL("Distribution overrun"); + char_val = dist->strings + dist->value_sets[dt][index]; + } else { + index = vset - 1; + dt = wset - 1; + if (index >= d->length || index < 0) { + auto result = + fprintf(stderr, "Runtime ERROR: Distribution over-run/under-run\n"); + if (result < 0) + perror("sprintf failed"); + result = fprintf( + stderr, + "Check distribution definitions and usage for %s.\n", + d->name); + if (result < 0) + perror("sprintf failed"); + result = fprintf(stderr, "index = %d, length=%d.\n", index, d->length); + if (result < 0) + perror("sprintf failed"); + exit(1); + } + char_val = dist->strings + dist->value_sets[dt][index]; + } + + switch (dist->type_vector[dt]) { + case TKN_VARCHAR: + if (dest) + *static_cast(dest) = static_cast(char_val); + break; + case TKN_INT: + i_res = atoi(char_val); + if (dest) + *static_cast(dest) = i_res; + break; + case TKN_DATE: + if (dest == NULL) { + dest = static_cast(malloc(sizeof(date_t))); + MALLOC_CHECK(dest); + } + strtodt(*static_cast(dest), char_val); + break; + case TKN_DECIMAL: + if (dest == NULL) { + dest = static_cast(malloc(sizeof(decimal_t))); + MALLOC_CHECK(dest); + } + strtodec(*static_cast(dest), char_val); + break; + } + + return ( + (dest == nullptr) + ? i_res + : index + 1); /* shift back to the 1-based indexing scheme */ +} + +/* + * Routine: int dist_weight + * Purpose: return the weight of a particular member of a distribution + * Algorithm: + * Data Structures: + * + * Params: distribution *d + * int index: which "row" + * int wset: which set of weights + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20000405 need to add error checking + */ +int dist_weight( + int* dest, + const char* d, + int index, + int wset, + DSDGenContext& /*dsdGenContext*/) { + dist_t* dist = nullptr; + int res = 0; + const d_idx_t* d_idx; + + if ((d_idx = find_dist(d)) == nullptr) { + char msg[40 + strlen(d)]; + sprintf(msg, "Invalid distribution name '%s'", d); + INTERNAL(msg); + } + + dist = d_idx->dist; + assert(index > 0); + assert(wset > 0); + res = dist->weight_sets[wset - 1][index - 1]; + /* reverse the accumulation of weights */ + if (index > 1) + res -= dist->weight_sets[wset - 1][index - 2]; + + if (dest == nullptr) + return (res); + + *dest = res; + + return (0); +} + +/* + * Routine: int DistNameIndex() + * Purpose: return the index of a column alias + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +int DistNameIndex( + const char* szDist, + int nNameType, + const char* szName, + DSDGenContext& /*dsdGenContext*/) { + const d_idx_t* d_idx = nullptr; + dist_t* dist = nullptr; + int res = 0; + char* cp = NULL; + + if ((d_idx = find_dist(szDist)) == NULL) + return (-1); + dist = d_idx->dist; + + if (dist->names == NULL) + return (-1); + + res = 0; + cp = dist->names; + do { + if (strcasecmp(szName, cp) == 0) + break; + cp += strlen(cp) + 1; + res += 1; + } while (res < (d_idx->v_width + d_idx->w_width)); + + if (res >= 0) { + if ((nNameType == VALUE_NAME) && (res < d_idx->v_width)) + return (res + 1); + if ((nNameType == WEIGHT_NAME) && (res > d_idx->v_width)) + return (res - d_idx->v_width + 1); + } + + return (-1); +} + +/* + * Routine: int distsize(char *name) + * Purpose: return the size of a distribution + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20000405 need to add error checking + */ +int distsize(const char* name, DSDGenContext& /*dsdGenContext*/) { + const d_idx_t* dist; + + dist = find_dist(name); + + if (dist == NULL) + return (-1); + + return (dist->length); +} + +/* + * Routine: int IntegrateDist(char *szDistName, int nPct, int nStartIndex, int + *nWeightSet) Purpose: return the index of the entry which, starting from + *nStartIndex, would create a range comprising nPct of the total contained in + *nWeightSet NOTE: the value can "wrap" -- that is, the returned value can be + *less than nStartIndex Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ + +int IntegrateDist( + const char* szDistName, + int nPct, + int nStartIndex, + int nWeightSet, + DSDGenContext& dsdGenContext) { + const d_idx_t* pDistIndex = nullptr; + int nGoal = 0, nSize = 0; + + if ((nPct <= 0) || (nPct >= 100)) + return (QERR_RANGE_ERROR); + + pDistIndex = find_dist(szDistName); + if (pDistIndex == NULL) + return (QERR_BAD_NAME); + + if (nStartIndex > pDistIndex->length) + return (QERR_RANGE_ERROR); + + nGoal = pDistIndex->dist->maximums[nWeightSet]; + nGoal = nGoal * nPct / 100; + nSize = distsize(szDistName, dsdGenContext); + + while (nGoal >= 0) { + nStartIndex++; + nGoal -= dist_weight( + nullptr, szDistName, nStartIndex % nSize, nWeightSet, dsdGenContext); + } + + return (nStartIndex); +} + +/* + * Routine: int dist_type(char *name, int nValueSet) + * Purpose: return the type of the n-th value set in a distribution + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +int dist_type(const char* name, int nValueSet, DSDGenContext& dsdGenContext) { + const d_idx_t* dist; + + dist = find_dist(name); + + if (dist == nullptr) + return (-1); + + if (nValueSet < 1 || nValueSet > dist->v_width) + return (-1); + + return (dist->dist->type_vector[nValueSet - 1]); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void dump_dist(const char* name, DSDGenContext& dsdGenContext) { + const d_idx_t* pIndex = nullptr; + int i, j; + char* pCharVal = nullptr; + int nVal = 0; + + pIndex = find_dist(name); + if (pIndex == nullptr) + ReportErrorNoLine(QERR_BAD_NAME, name, 1); + printf("create %s;\n", pIndex->name); + printf("set types = ("); + for (i = 0; i < pIndex->v_width; i++) { + if (i > 0) + printf(", "); + printf( + "%s", dist_type(name, i + 1, dsdGenContext) == 7 ? "int" : "varchar"); + } + printf(");\n"); + printf("set weights = %d;\n", pIndex->w_width); + for (i = 0; i < pIndex->length; i++) { + printf("add("); + for (j = 0; j < pIndex->v_width; j++) { + if (j) + printf(", "); + if (dist_type(name, j + 1, dsdGenContext) != 7) { + dist_member(&pCharVal, name, i + 1, j + 1, dsdGenContext); + printf("\"%s\"", pCharVal); + } else { + dist_member(&nVal, name, i + 1, j + 1, dsdGenContext); + printf("%d", nVal); + } + } + printf("; "); + for (j = 0; j < pIndex->w_width; j++) { + if (j) + printf(", "); + printf("%d", dist_weight(nullptr, name, i + 1, j + 1, dsdGenContext)); + } + printf(");\n"); + } + + return; +} + +/* + * Routine: dist_active(char *szName, int nWeightSet) + * Purpose: return number of entries with non-zero weght values + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int dist_active( + const char* szName, + int nWeightSet, + DSDGenContext& dsdGenContext) { + int nSize, nResult = 0, i = 0; + + nSize = distsize(szName, dsdGenContext); + for (i = 1; i <= nSize; i++) { + if (dist_weight(nullptr, szName, i, nWeightSet, dsdGenContext) != 0) + nResult += 1; + } + + return (nResult); +} + +/* + * Routine: DistSizeToShiftWidth(char *szDist) + * Purpose: Determine the number of bits required to select a member of the + * distribution Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int DistSizeToShiftWidth( + const char* szDist, + int nWeightSet, + DSDGenContext& dsdGenContext) { + int nBits = 1, nMax; + unsigned int nTotal = 2; + const d_idx_t* d; + + d = find_dist(szDist); + nMax = dist_max(d->dist, nWeightSet, dsdGenContext); + + while (nTotal < nMax) { + nBits += 1; + nTotal <<= 1; + } + + return (nBits); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int MatchDistWeight( + void* dest, + const char* szDist, + int nWeight, + int nWeightSet, + int ValueSet, + DSDGenContext& dsdGenContext) { + const d_idx_t* d = nullptr; + dist_t* dist = nullptr; + int index = 0, dt = 0, i_res = 0, nRetcode = 0; + char* char_val; + + if ((d = find_dist(szDist)) == nullptr) { + char msg[40 + strlen(szDist)]; + sprintf(msg, "Invalid distribution name '%s'", szDist); + INTERNAL(msg); + } + + dist = d->dist; + nWeight %= dist->maximums[nWeightSet - 1]; + + while (nWeight > dist->weight_sets[nWeightSet - 1][index] && + index < d->length) + index += 1; + dt = ValueSet - 1; + if (index >= d->length) + index = d->length - 1; + char_val = dist->strings + dist->value_sets[dt][index]; + + switch (dist->type_vector[dt]) { + case TKN_VARCHAR: + if (dest) + *static_cast(dest) = static_cast(char_val); + break; + case TKN_INT: + i_res = atoi(char_val); + if (dest) + *static_cast(dest) = i_res; + break; + case TKN_DATE: + if (dest == nullptr) { + dest = static_cast(malloc(sizeof(date_t))); + MALLOC_CHECK(dest); + } + strtodt(*static_cast(dest), char_val); + break; + case TKN_DECIMAL: + if (dest == nullptr) { + dest = static_cast(malloc(sizeof(decimal_t))); + MALLOC_CHECK(dest); + } + strtodec(*(decimal_t**)dest, char_val); + break; + } + + nRetcode = 1; + index = 1; + while (index < dist->maximums[nWeightSet - 1]) { + nRetcode += 1; + index *= 2; + } + + return (nRetcode); +} + +/* + * Routine: findDistValue(char *szValue, char *szDistName, int nValueSet) + * Purpose: Return the row number where the entry is found + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20031024 jms this routine needs to handle all data types, not just varchar + */ +int findDistValue( + const char* szValue, + const char* szDistName, + int ValueSet, + DSDGenContext& dsdGenContext) { + char szDistValue[128]; + int nRetValue = 1, nDistMax; + + nDistMax = distsize(szDistName, dsdGenContext); + + for (nRetValue = 1; nRetValue < nDistMax; nRetValue++) { + dist_member(&szDistValue, szDistName, nRetValue, ValueSet, dsdGenContext); + if (strcmp(szValue, szDistValue) == 0) + break; + } + + if (nRetValue <= nDistMax) + return (nRetValue); + return (-1); +} + +void DSDGenContext::Reset() { + init_rand_init = 0; + mk_address_init = 0; + setUpdateDateRange_init = 0; + mk_dbgen_version_init = 0; + getCatalogNumberFromPage_init = 0; + checkSeeds_init = 0; + dateScaling_init = 0; + mk_w_call_center_init = 0; + mk_w_catalog_page_init = 0; + mk_master_catalog_sales_init = 0; + dectostr_init = 0; + date_join_init = 0; + setSCDKeys_init = 0; + scd_join_init = 0; + matchSCDSK_init = 0; + skipDays_init = 0; + mk_w_catalog_returns_init = 0; + mk_detail_catalog_sales_init = 0; + mk_w_customer_init = 0; + mk_w_date_init = 0; + mk_w_inventory_init = 0; + mk_w_item_init = 0; + mk_w_promotion_init = 0; + mk_w_reason_init = 0; + mk_w_ship_mode_init = 0; + mk_w_store_returns_init = 0; + mk_master_store_sales_init = 0; + mk_w_store_init = 0; + mk_w_web_page_init = 0; + mk_w_web_returns_init = 0; + mk_master_init = 0; + mk_detail_init = 0; + mk_w_web_site_init = 0; + mk_cust_init = 0; + mk_order_init = 0; + mk_part_init = 0; + mk_supp_init = 0; + dbg_text_init = 0; + find_dist_init = 0; + cp_join_init = 0; + web_join_init = 0; + set_pricing_init = 0; + init_params_init = 0; + get_rowcount_init = 0; + mk_detail_web_sales_init = 0; + mk_master_web_sales_init = 0; +} + +#ifdef TEST +main() { + int i_res; + char* c_res; + decimal_t dec_res; + + init_params(); + + dist_member(&i_res, "test_dist", 1, 1); + if (i_res != 10) { + printf("dist_member(\"test_dist\", 1, 1): %d != 10\n", i_res); + exit(1); + } + dist_member(&i_res, "test_dist", 1, 2); + if (i_res != 60) { + printf("dist_member(\"test_dist\", 1, 2): %d != 60\n", i_res); + exit(1); + } + dist_member((void*)&c_res, "test_dist", 1, 3); + if (strcmp(c_res, "El Camino")) { + printf("dist_member(\"test_dist\", 1, 3): %s != El Camino\n", c_res); + exit(1); + } + dist_member((void*)&dec_res, "test_dist", 1, 4); + if (strcmp(dec_res.number, "1") || strcmp(dec_res.fraction, "23")) { + printf( + "dist_member(\"test_dist\", 1, 4): %s.%s != 1.23\n", + dec_res.number, + dec_res.fraction); + exit(1); + } + dist_weight(&i_res, "test_dist", 2, 2); + if (3 != i_res) { + printf("dist_weight(\"test_dist\", 2, 2): %d != 3\n", i_res); + exit(1); + } +} +#endif /* TEST */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/error_msg.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/error_msg.cpp new file mode 100644 index 0000000000000..eb1792eba1c70 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/error_msg.cpp @@ -0,0 +1,237 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "error_msg.h" +#include +#include +#include +#include "config.h" +#include "grammar_support.h" +#include "porting.h" +static int* LN; +static char* FN; + +err_msg_t Errors[MAX_ERROR + 2] = { + { + EFLG_NO_ARG, + "", + }, + {EFLG_STR_ARG, "File '%s' not found"}, + {EFLG_NO_ARG, "Line exceeds maximum leng.h"}, + {EFLG_STR_ARG, "Memory allocation failed %s"}, + {EFLG_STR_ARG, "Syntax Error: \n'%s'"}, + {EFLG_NO_ARG, "Invalid/Out-of-range Argument"}, + {EFLG_STR_ARG, "'%s' is not a unique name"}, + {EFLG_STR_ARG, "'%s' is not a valid name"}, + {EFLG_NO_ARG, "Command parse failed"}, + {EFLG_NO_ARG, "Invalid tag found"}, + {EFLG_STR_ARG, "Read failed on '%s'"}, + {EFLG_NO_ARG, "Too Many Templates!"}, + {EFLG_NO_ARG, "Each workload definition must be in its own file"}, + {EFLG_NO_ARG, + "Query Class name must be unique within a workload definition"}, + {EFLG_NO_ARG, "Query Template must be unique within a query class"}, + {EFLG_STR_ARG | EFLG_SYSTEM, "Open failed on '%s'"}, + {EFLG_STR_ARG, "%s not yet implemented"}, /* QERR_NOT_IMPLEMENTED */ + {EFLG_STR_ARG, "string trucated to '%s'"}, + {EFLG_NO_ARG, "Non-terminated string"}, + {EFLG_STR_ARG, "failed to write to '%s'"}, + {EFLG_NO_ARG, "No type vector defined for distribution"}, + {EFLG_NO_ARG, "No weight count defined for distribution"}, + {EFLG_NO_ARG, "No limits defined for pricing calculations"}, + {EFLG_STR_ARG, "Percentage is out of bounds in substitution '%s'"}, + {EFLG_STR_ARG, "Name is not a distribution or table name: '%s'"}, + {EFLG_NO_ARG, "Cannot evaluate expression"}, + {EFLG_STR_ARG, + "Substitution'%s' is used before being initialized"}, /* QERR_NO_INIT + */ + {EFLG_NO_ARG, + "RANGE()/LIST()/ULIST() not supported for NORMAL " + "distributions"}, + {EFLG_STR_ARG, "Bad Nesting; '%s' not found"}, + {EFLG_STR_ARG, "Include stack overflow when opening '%s'"}, + {EFLG_STR_ARG, "Bad function call: '%s'"}, + {EFLG_STR_ARG, "Bad Hierarchy Call: '%s'"}, + {EFLG_NO_ARG, "Must set types and weights before defining names"}, + {EFLG_NO_ARG, "More than 20 arguments in definition"}, + {EFLG_NO_ARG, "Argument type mismat.h"}, + {EFLG_NO_ARG, + "RANGE()/LIST()/ULIST() cannot be used in the " + "same expression"}, /* QERR_RANGE_LIST + */ + {EFLG_NO_ARG, "Selected scale factor is NOT valid for result publication"}, + {EFLG_STR_ARG, "Parameter setting failed for '%s'"}, + {EFLG_STR_ARG, "Table %s is being joined without an explicit rule"}, + {EFLG_STR_ARG, "Table %s is not yet fully defined"}, + {EFLG_STR_ARG, + "Table %s is a child; it is populated during the build of " + "its parent (e.g., catalog_sales builds catalog returns)"}, + {EFLG_NO_ARG, + "Command line arguments for dbgen_version exceed 200 " + "characters; truncated"}, + {EFLG_NO_ARG, + "A query template list must be supplied using the " + "INPUT option"}, /* QERR_NO_QUERYLIST + */ + {EFLG_NO_ARG, + "Invalid query number found in permutation!"}, /* QERR_QUERY_RANGE + */ + {EFLG_NO_ARG, + "RANGE/LIST/ULIST expressions not valid as " + "function parameters"}, /* QERR_MODIFIED_PARAM + */ + {EFLG_NO_ARG, + "RANGE/LIST/ULIST truncated to available " + "values"}, /* QERR_MODIFIED_PARAM + */ + {EFLG_NO_ARG, + "This scale factor is valid for QUALIFICATION " + "ONLY"}, /* QERR_QUALIFICATION_SCALE + */ + {EFLG_STR_ARG, + "Generating %s requires the '-update' option"}, /* QERR_TABLE_UPDATE + */ + {0, NULL}}; + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void ProcessErrorCode( + int nErrorCode, + char* szRoutineName, + char* szParam, + int nParam) { + switch (nErrorCode) { + case QERR_NO_FILE: + ReportError(QERR_NO_FILE, szParam, 1); + break; + case QERR_SYNTAX: + case QERR_RANGE_ERROR: + case QERR_NON_UNIQUE: + case QERR_BAD_NAME: + case QERR_DEFINE_OVERFLOW: + case QERR_INVALID_TAG: + case QERR_READ_FAILED: + case QERR_NO_MEMORY: + case QERR_LINE_TOO_LONG: + ReportError(nErrorCode, szRoutineName, 1); + break; + } + return; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int ReportError(int nError, const char* msg, int bExit) { + auto result = fprintf(stderr, "ERROR?!\n"); + if (result < 0) + perror("sprintf failed"); + return (nError); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int ReportErrorNoLine(int nError, const char* msg, int bExit) { + if (nError < MAX_ERROR) { + switch (static_cast(Errors[-nError].flags) & EFLG_ARG_MASK) { + case EFLG_NO_ARG: { + auto result = fprintf( + stderr, + "%s: %s\n", + (bExit) ? "ERROR" : "Warning", + Errors[-nError].prompt); + if (result < 0) + perror("sprintf failed"); + break; + } + case EFLG_STR_ARG: { + auto prompt = Errors[std::min( + static_cast(-nError), + static_cast(MAX_ERROR + 1))] + .prompt; + char e_msg[1024 + strlen(prompt) + strlen(msg)]; + auto result = sprintf(e_msg, prompt, msg); + if (result < 0) + perror("sprintf failed"); + result = + fprintf(stderr, "%s: %s\n", (bExit) ? "ERROR" : "Warning", e_msg); + if (result < 0) + perror("sprintf failed"); + break; + } + } + + if (static_cast(Errors[static_cast(-nError)].flags) & + EFLG_SYSTEM) + perror(msg); + } + + if (bExit) + exit(nError); + else + return (nError); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void SetErrorGlobals(char* szFileName, int* nLineNumber) { + FN = szFileName; + LN = nLineNumber; + + return; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/genrand.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/genrand.cpp new file mode 100644 index 0000000000000..585ad51e89c92 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/genrand.cpp @@ -0,0 +1,703 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include +#include +#include "config.h" +#include "porting.h" +#ifdef WIN32 +#include +#include +#endif +#include "config.h" +#include "date.h" +#include "decimal.h" +#include "dist.h" +#include "genrand.h" +#include "params.h" +#include "porting.h" +#include "r_params.h" + +#include "columns.h" +#include "streams.h" +#include "tables.h" + +static long Mult = 16807; /* the multiplier */ +static long nQ = 127773; /* the quotient MAXINT / Mult */ +static long nR = 2836; /* the remainder MAXINT % Mult */ +void DSNthElement(HUGE_TYPE N, int nStream, DSDGenContext& dsdGenContext); + +/* + * Routine: next_random(int stream, DSDGenContext& dsdGenContext) + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +long next_random(int stream, DSDGenContext& dsdGenContext) { + long s = dsdGenContext.Streams[stream].nSeed, div_res, mod_res; + + div_res = s / nQ; + mod_res = s - nQ * div_res; /* i.e., mod_res = s % nQ */ + s = Mult * mod_res - div_res * nR; + if (s < 0) + s += MAXINT; + dsdGenContext.Streams[stream].nSeed = s; + dsdGenContext.Streams[stream].nUsed += 1; +#ifdef JMS + dsdGenContext.Streams[stream].nTotal += 1; +#endif + return (s); +} + +/* + * Routine: next_random_float(int stream) + * Purpose: return random in [0..1] + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +double next_random_float(int stream, DSDGenContext& dsdGenContext) { + long res; + + res = next_random(stream, dsdGenContext); + + return (static_cast(res) / static_cast(MAXINT)); +} + +/* + * Routine: skip_random(int stream, int skip_count, DSDGenContext& + * dsdGenContext) Purpose: Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void skip_random(int nStream, ds_key_t N, DSDGenContext& dsdGenContext) { + ds_key_t Z; + ds_key_t M; + +#ifdef UNDEF + fprintf(stderr, "skipping stream %d to %d\n", nStream, N); + Streams[nStream].nTotal = N; +#endif + M = Mult; + Z = static_cast(dsdGenContext.Streams[nStream].nInitialSeed); + while (N > 0) { + if (N % 2 != 0) /* testing for oddness, this seems portable */ + Z = (M * Z) % MAXINT; + N = N / 2; /* integer division, truncates */ + M = (M * M) % MAXINT; + } + dsdGenContext.Streams[nStream].nSeed = static_cast(Z); + + return; +} + +/* + * Routine: genrand_integer(int dist, int min, int max, int mean, dsdGenContext) + * Purpose: generate a random integer given the distribution and limits + * Algorithm: + * Data Structures: + * + * Params: + * Returns: int + * Called By: + * Calls: + * Assumptions: + * Side Effects: + */ +int genrand_integer( + int* dest, + int dist, + int min, + int max, + int mean, + int stream, + DSDGenContext& dsdGenContext) { + int res = 0, i; + double fres = 0; + + switch (dist) { + case DIST_UNIFORM: + res = next_random(stream, dsdGenContext); + res %= max - min + 1; + res += min; + break; + case DIST_EXPONENTIAL: + for (i = 0; i < 12; i++) + fres += + static_cast(next_random(stream, dsdGenContext) / MAXINT) - + 0.5; + res = min + static_cast((max - min + 1) * fres); + break; + default: + INTERNAL("Undefined distribution"); + break; + } + + if (dest == nullptr) + return (res); + + *dest = res; + + return (0); +} + +/* + * Routine: genrand_key(ket_t *dest, int dist, ds_key_t min, ds_key_t max, + * ds_key_t mean, int stream, DSDGenContext& dsdGenContext) Purpose: generate a + * random integer given the distribution and limits Algorithm: Data Structures: + * + * Params: + * Returns: ds_key_t + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: Need to rework to rely on RNG routines that will work for 64 bit return + * values + */ +ds_key_t genrand_key( + ds_key_t* dest, + int dist, + ds_key_t min, + ds_key_t max, + ds_key_t mean, + int stream, + DSDGenContext& dsdGenContext) { + int res = 0, i; + double fres = 0; + + switch (dist) { + case DIST_UNIFORM: + res = next_random(stream, dsdGenContext); + res %= static_cast(max - min + 1); + res += static_cast(min); + break; + case DIST_EXPONENTIAL: + for (i = 0; i < 12; i++) + fres += + static_cast(next_random(stream, dsdGenContext) / MAXINT) - + 0.5; + res = static_cast(min) + static_cast((max - min + 1) * fres); + break; + default: + INTERNAL("Undefined distribution"); + break; + } + + if (dest == nullptr) + return (static_cast(res)); + + *dest = static_cast(res); + + return (static_cast(0)); +} + +/* + * Routine: + * genrand_decimal(int dist, decimal_t *min, decimal_t *max, decimal_t + **mean), dsdGenContext Purpose: create a random decimal_t Algorithm: Data + *Structures: + * + * Params: min/max are char * to allow easy passing of precision + * Returns: decimal_t *; NULL on failure + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int genrand_decimal( + decimal_t* dest, + int dist, + decimal_t* min, + decimal_t* max, + decimal_t* mean, + int stream, + DSDGenContext& dsdGenContext) { + int i; + decimal_t res; + double fres = 0.0; + + if (min->precision < max->precision) + dest->precision = min->precision; + else + dest->precision = max->precision; + + switch (dist) { + case DIST_UNIFORM: + res.number = next_random(stream, dsdGenContext); + res.number %= max->number - min->number + 1; + res.number += min->number; + break; + case DIST_EXPONENTIAL: + for (i = 0; i < 12; i++) { + fres /= 2.0; + fres += static_cast( + static_cast(next_random(stream, dsdGenContext)) / + static_cast(MAXINT)) - + 0.5; + } + res.number = mean->number + + static_cast((max->number - min->number + 1) * fres); + break; + default: + INTERNAL("Undefined distribution"); + break; + } + + dest->number = res.number; + i = 0; + while (res.number > 10) { + res.number /= 10; + i += 1; + } + dest->scale = i; + + return (0); +} + +/* Routine: RNGReset(int tbl) + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int RNGReset(int tbl, DSDGenContext& dsdGenContext) { + int i; + + for (i = 0; dsdGenContext.Streams[i].nColumn != -1; i++) + if (dsdGenContext.Streams[i].nTable == tbl) + dsdGenContext.Streams[i].nSeed = dsdGenContext.Streams[i].nInitialSeed; + + return (0); +} + +/* WARNING! This routine assumes the existence of 64-bit */ + +/* integers. The notation used here- "HUGE" is *not* ANSI standard. */ + +/* Hopefully, you have this extension as well. If not, use whatever */ + +/* nonstandard trick you need to in order to get 64 bit integers. */ + +/* The book says that this will work if MAXINT for the type you choose */ + +/* is at least 2**46 - 1, so 64 bits is more than you *really* need */ + +static HUGE_TYPE Multiplier = 16807; /* or whatever nonstandard */ +static HUGE_TYPE Modulus = 2147483647; /* trick you use to get 64 bit int */ + +/* Advances value of Seed after N applications of the random number generator + with multiplier Mult and given Modulus. + NthElement(Seed[],count); + + Theory: We are using a generator of the form + X_n = [Mult * X_(n-1)] mod Modulus. It turns out that + X_n = [(Mult ** n) X_0] mod Modulus. + This can be computed using a divide-and-conquer technique, see + the code below. + + In words, this means that if you want the value of the Seed after n + applications of the generator, you multiply the initial value of the + Seed by the "super multiplier" which is the basic multiplier raised + to the nth power, and then take mod Modulus. +*/ + +/* Nth Element of sequence starting with StartSeed */ +void DSNthElementNthElement( + HUGE_TYPE N, + int nStream, + DSDGenContext& dsdGenContext) { + HUGE_TYPE Z; + HUGE_TYPE Mult; + + Mult = Multiplier; + Z = static_cast(dsdGenContext.Streams[nStream].nInitialSeed); + while (N > 0) { + if (N % 2 != 0) /* testing for oddness, this seems portable */ + { +#ifdef JMS + dsdGenContext.Streams[nStream].nTotal += 1; +#endif + Z = (Mult * Z) % Modulus; + } + N = N / 2; /* integer division, truncates */ + Mult = (Mult * Mult) % Modulus; +#ifdef JMS + dsdGenContext.Streams[nStream].nTotal += 2; +#endif + } + dsdGenContext.Streams[nStream].nSeed = static_cast(Z); + + return; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int dump_seeds_ds(int tbl, DSDGenContext& dsdGenContext) { + int i; + + for (i = 0; dsdGenContext.Streams[i].nColumn != -1; i++) + if (dsdGenContext.Streams[i].nTable == tbl) { + auto result = printf( + "%04d\t%09d\t%09ld\n", + i, + dsdGenContext.Streams[i].nUsed, + dsdGenContext.Streams[i].nSeed); + if (result < 0) + perror("sprintf failed"); + } + return (0); +} + +/* + * Routine: gen_charset(char *set, int min, int max) + * Purpose: generate random characters from set for a random length [min..max] + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int gen_charset( + char* dest, + char* set, + int min, + int max, + int stream, + DSDGenContext& dsdGenContext) { + int len, i, temp; + + if (set == NULL) { + dest = NULL; + return (-1); + } + + genrand_integer(&len, DIST_UNIFORM, min, max, 0, stream, dsdGenContext); + + for (i = 0; i < max; i++) { + genrand_integer( + &temp, DIST_UNIFORM, 0, strlen(set) - 1, 0, stream, dsdGenContext); + if (i < len) + dest[i] = *(set + temp); + } + dest[len] = '\0'; + + return (0); +} + +/* + * Routine: genrand_date(int dist, date_t *min, date_t *max, DSDGenContext& + * dsdGenContext) Purpose: generate random date within [min..max] Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int genrand_date( + date_t* dest, + int dist, + date_t* min, + date_t* max, + date_t* mean, + int stream, + DSDGenContext& dsdGenContext) { + int range, imean = 0, temp, idt, nYear, nTotalWeight = 0, nDayCount; + + idt = dttoj(min); + range = dttoj(max); + range -= idt; + nDayCount = min->day; + nYear = min->year; + + switch (dist) { + case DIST_SALES: + case DIST_RETURNS: + /* walk from min to max to "integrate" the distribution */ + while (range -= 1) { + nTotalWeight += dist_weight( + NULL, "calendar", nDayCount, dist + is_leap(nYear), dsdGenContext); + if (nDayCount == 365 + is_leap(nYear)) { + nYear += 1; + nDayCount = 1; + } else + nDayCount += 1; + } + /* pick a value in the resulting range */ + temp = genrand_integer( + NULL, DIST_UNIFORM, 1, nTotalWeight, 0, stream, dsdGenContext); + /* and walk it again to translate that back to a date */ + nDayCount = min->day; + idt = min->julian; + nYear = min->year; + while (temp >= 0) { + temp -= dist_weight( + NULL, "calendar", nDayCount, dist + is_leap(nYear), dsdGenContext); + nDayCount += 1; + idt += 1; + if (nDayCount > 365 + is_leap(nYear)) { + nYear += 1; + nDayCount = 1; + } + } + break; + case DIST_EXPONENTIAL: + imean = dttoj(mean); + imean -= idt; + case DIST_UNIFORM: + genrand_integer(&temp, dist, 0, range, imean, stream, dsdGenContext); + idt += temp; + break; + default: + break; + } + + jtodt(dest, idt); + + return (0); +} + +/************** + ************** + ** + ** static routines + ** + ************** + **************/ + +/* + * Routine: init_rand(DSDGenContext& dsdGenContext) + * Purpose: Initialize the RNG used throughout the code + * Algorithm: To allow two columns to use the same stream of numbers (for + *joins), pre-sort the streams list by Duplicate and then assign values. Order + *by column after initialization Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +// FIXME: allow re-init +void init_rand(DSDGenContext& dsdGenContext) { + long long i, skip, nSeed; // changed to long long from int + + if (!dsdGenContext.init_rand_init) { + if (is_set("RNGSEED", dsdGenContext)) + nSeed = get_int("RNGSEED", dsdGenContext); + else + nSeed = RNG_SEED; + skip = MAXINT / MAX_COLUMN; + for (i = 0; i < MAX_COLUMN; i++) { + // simulate the overflow as if it were an int + if (i != 0 && (INT_MAX - nSeed) / i < skip) { + long long val = nSeed + skip * i; + val %= MAXINT; + val -= MAXINT; + val -= 2; + dsdGenContext.Streams[i].nInitialSeed = val; + dsdGenContext.Streams[i].nSeed = val; + } else { + dsdGenContext.Streams[i].nInitialSeed = nSeed + skip * i; + dsdGenContext.Streams[i].nSeed = nSeed + skip * i; + } + dsdGenContext.Streams[i].nUsed = 0; + } + dsdGenContext.init_rand_init = 1; + } + return; +} + +void resetSeeds(int nTable, DSDGenContext& dsdGenContext) { + int i; + + for (i = 0; i < MAX_COLUMN; i++) + if (dsdGenContext.Streams[i].nTable == nTable) + dsdGenContext.Streams[i].nSeed = dsdGenContext.Streams[i].nInitialSeed; + return; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void genrand_email( + char* pEmail, + char* pFirst, + char* pLast, + int nColumn, + DSDGenContext& dsdGenContext) { + char* pDomain = nullptr; + char szCompany[50]; + int nCompanyLength; + + pick_distribution(&pDomain, "top_domains", 1, 1, nColumn, dsdGenContext); + genrand_integer( + &nCompanyLength, DIST_UNIFORM, 10, 20, 0, nColumn, dsdGenContext); + gen_charset(&szCompany[0], ALPHANUM, 1, 20, nColumn, dsdGenContext); + szCompany[nCompanyLength] = '\0'; + + if ((strlen(pFirst) + strlen(pLast) + strlen(szCompany) + strlen(pDomain) + + 3) < (RS_C_EMAIL + 1)) { + auto result = + sprintf(pEmail, "%s.%s@%s.%s", pFirst, pLast, szCompany, pDomain); + if (result < 0) + perror("sprintf failed"); + } + + return; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void genrand_ipaddr(char* pDest, int nColumn, DSDGenContext& dsdGenContext) { + int arQuads[4], i; + + for (i = 0; i < 4; i++) + genrand_integer( + &arQuads[i], DIST_UNIFORM, 1, 255, 0, nColumn, dsdGenContext); + auto result = sprintf( + pDest, + "%03d.%03d.%03d.%03d", + arQuads[0], + arQuads[1], + arQuads[2], + arQuads[3]); + if (result < 0) + perror("sprintf failed"); + + return; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int genrand_url(char* pDest, int nColumn) { + strcpy(pDest, "http://www.foo.com"); + + return (0); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int setSeed(int nStream, int nValue, DSDGenContext& dsdGenContext) { + int nRetValue; + + nRetValue = dsdGenContext.Streams[nStream].nSeed; + dsdGenContext.Streams[nStream].nSeed = nValue; + + return (nRetValue); +} + +#ifdef TEST +main() { + printf("r_genrand:No test routine has been defined for this module\n"); + + exit(0); +} +#endif /* TEST */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/join.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/join.cpp new file mode 100644 index 0000000000000..1a3b1fcf00f39 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/join.cpp @@ -0,0 +1,455 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "dist.h" +#include "error_msg.h" +#include "genrand.h" +#include "porting.h" +#include "r_params.h" +#include "scaling.h" +#include "scd.h" +#include "sparse.h" +#include "tables.h" +#include "tdefs.h" +#include "tpcds.idx.h" +#include "w_web_sales.h" + +ds_key_t web_join(int col, ds_key_t join_key, DSDGenContext& dsdGenContext); + +/* + * Routine: date_join(int from_tbl, int join_count) + * Purpose: account for the different date-adjusted patterns in the data set + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: Relies on existing RNG code, which isn't really 64bit; will probably + * requre a rework of the genrand_xx routines + */ +static ds_key_t date_join( + int from_tbl, + int from_col, + ds_key_t join_count, + int nYear, + DSDGenContext& dsdGenContext) { + int nDay, nTemp, nMin = -1, nMax = -1, nResult; + int jToday; + date_t TempDate; + + strtodt(&TempDate, TODAYS_DATE); + jToday = dttoj(&TempDate); + + switch (from_tbl) { + case STORE_SALES: + case CATALOG_SALES: + case WEB_SALES: + pick_distribution( + &nDay, + "calendar", + 1, + calendar_sales + is_leap(nYear), + from_col, + dsdGenContext); + break; + + /* + * returns are keyed to the sale date, with the lag between sale and return + * selected within a known range, based on sales channel + */ + case STORE_RETURNS: + nMin = SS_MIN_SHIP_DELAY; + nMax = SS_MAX_SHIP_DELAY; + case CATALOG_RETURNS: + if (nMin == -1) { + nMin = CS_MIN_SHIP_DELAY; + nMax = CS_MAX_SHIP_DELAY; + } + case WEB_RETURNS: + if (nMin == -1) { + nMin = WS_MIN_SHIP_DELAY; + nMax = WS_MAX_SHIP_DELAY; + } + genrand_integer( + &nTemp, DIST_UNIFORM, nMin * 2, nMax * 2, 0, from_col, dsdGenContext); + return (join_count + nTemp); + break; + case WEB_SITE: + case WEB_PAGE: + return (web_join(from_col, join_count, dsdGenContext)); + default: + pick_distribution( + &nDay, "calendar", 1, 1 + is_leap(nYear), from_col, dsdGenContext); + break; + } + + TempDate.year = nYear; + TempDate.month = 1; + TempDate.day = 1; + + nResult = dttoj(&TempDate) + nDay; + + return (static_cast(nResult > jToday) ? -1 : nResult); +} + +/* + * Routine: time_join(int from_tbl, int join_count) + * Purpose: create joins that are time-skewed + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: Relies on existing RNG code, which isn't really 64bit; will probably + * requre a rework of the genrand_xx routines + */ +ds_key_t time_join( + int to_tbl, + int to_col, + ds_key_t join_count, + DSDGenContext& dsdGenContext) { + int hour, secs; + + switch (to_tbl) { + case STORE_SALES: + case STORE_RETURNS: + pick_distribution(&hour, "hours", 1, 2, to_col, dsdGenContext); + break; + case CATALOG_SALES: + case WEB_SALES: + case CATALOG_RETURNS: + case WEB_RETURNS: + pick_distribution(&hour, "hours", 1, 3, to_col, dsdGenContext); + break; + default: + pick_distribution(&hour, "hours", 1, 1, to_col, dsdGenContext); + break; + } + genrand_integer(&secs, DIST_UNIFORM, 0, 3599, 0, to_col, dsdGenContext); + + return (static_cast(hour * 3600 + secs)); +} + +/* + * Routine: cp_join(int from_tbl, int join_count) + * Purpose: create joins to catalog_page + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +static ds_key_t +cp_join(int tbl, int col, ds_key_t jDate, DSDGenContext& dsdGenContext) { + ds_key_t res; + static int nPagePerCatalog; + int nType, nCount, nOffset, nPage; + static date_t dTemp; + char* szTemp = nullptr; + + if (!dsdGenContext.cp_join_init) { + nPagePerCatalog = + (static_cast(get_rowcount(CATALOG_PAGE, dsdGenContext)) / + CP_CATALOGS_PER_YEAR) / + (YEAR_MAXIMUM - YEAR_MINIMUM + 2); + strtodt(&dTemp, DATA_START_DATE); + dsdGenContext.cp_join_init = 1; + } + + nType = + pick_distribution(&szTemp, "catalog_page_type", 1, 2, col, dsdGenContext); + genrand_integer( + &nPage, DIST_UNIFORM, 1, nPagePerCatalog, 0, col, dsdGenContext); + nOffset = static_cast(jDate) - dTemp.julian - 1; + nCount = (nOffset / 365) * CP_CATALOGS_PER_YEAR; + nOffset %= 365; + + switch (nType) { + case 1: /* bi-annual */ + if (nOffset > 183) + nCount += 1; + break; + case 2: /* quarterly */ + nCount += (nOffset / 91); + break; + case 3: /* monthly */ + nCount += (nOffset / 31); + break; + } + + res = CP_SK(nCount, nPagePerCatalog, nPage); + + return (res); +} +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t getCatalogNumberFromPage( + ds_key_t kPageNumber, + DSDGenContext& dsdGenContext) { + static int nPagePerCatalog; + + if (!dsdGenContext.getCatalogNumberFromPage_init) { + nPagePerCatalog = + (static_cast(get_rowcount(CATALOG_PAGE, dsdGenContext)) / + CP_CATALOGS_PER_YEAR) / + (YEAR_MAXIMUM - YEAR_MINIMUM + 2); + dsdGenContext.getCatalogNumberFromPage_init = 1; + } + + return (kPageNumber / nPagePerCatalog); +} + +/* + * Routine: web_join(int col, ds_key_t join_key, DSDGenContext& dsdGenContext) + * Purpose: create joins to web_site/web_page. These need to be handled + *together, since the date of transaction must fit within the lifetime of a + *particular page, which must fit within the lifetime of a particular site Data + *Structures: + * + * Params: + * join_key is one of two things: + * 1. the xxx_sk for a particular row in the dimension for which we + *need appropriate dates + * 2. a julian date for which we need to pick a valid xxx_sk value + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t web_join(int col, ds_key_t join_key, DSDGenContext& dsdGenContext) { + ds_key_t res = -1, kSite; + static int nConcurrentSites, nSiteDuration, nOffset; + static date_t dSiteOpen, /* open/close dates for current web site */ + dSiteClose; + int nTemp; + tdef* pWS = getSimpleTdefsByNumber(WEB_SITE, dsdGenContext); + tdef* pWP = getSimpleTdefsByNumber(WEB_PAGE, dsdGenContext); + + if (!dsdGenContext.web_join_init) { + strtodt(&dSiteClose, WEB_END_DATE); + nSiteDuration = dSiteClose.julian; + nConcurrentSites = + static_cast(get_rowcount(CONCURRENT_WEB_SITES, dsdGenContext)); + strtodt(&dSiteOpen, WEB_START_DATE); + nSiteDuration -= dSiteOpen.julian; + nSiteDuration *= nConcurrentSites; + nOffset = (dSiteClose.julian - dSiteOpen.julian) / (2 * nSiteDuration); + dsdGenContext.web_join_init = 1; + } + + switch (col) { + /************** + * join_key is the xxx_sk value for a dimension + */ + case WEB_OPEN_DATE: + strtodt(&dSiteOpen, DATE_MINIMUM); + res = dSiteOpen.julian - + ((join_key * WEB_DATE_STAGGER) % nSiteDuration / 2); + if (WEB_IS_REPLACED(join_key)) /* this site is completely replaced */ + { + if (WEB_IS_REPLACEMENT(join_key)) /* this is the second site */ + { + /* the open date of the second site needs to align on a revision + * boundary */ + res += nOffset * nSiteDuration; + } + } + break; + case WEB_CLOSE_DATE: + strtodt(&dSiteOpen, DATE_MINIMUM); + res = dSiteOpen.julian - + ((join_key * WEB_DATE_STAGGER) % nSiteDuration / 2); + res += pWS->nParam * nSiteDuration; + if (WEB_IS_REPLACED(join_key)) /* this site is completely replaced */ + { + if (!WEB_IS_REPLACEMENT(join_key)) /* this is the first site */ + { + /* the close date of the first site needs to align on a revision + * boundary */ + res -= pWS->nParam * nSiteDuration / 2; + } + } + break; + case WEB_REC_START_DATE_ID: + strtodt(&dSiteOpen, DATE_MINIMUM); + res = dSiteOpen.julian - + (((join_key - 1) * WEB_DATE_STAGGER) % nSiteDuration / 2); + res += (join_key % pWS->nParam) * nSiteDuration; + break; + case WEB_REC_END_DATE_ID: + strtodt(&dSiteOpen, DATE_MINIMUM); + res = dSiteOpen.julian - + ((join_key * WEB_DATE_STAGGER) % nSiteDuration / 2); + res += ((join_key + 1) % pWS->nParam) * nSiteDuration * 5 - 1; + break; + case WP_REC_START_DATE_ID: + strtodt(&dSiteOpen, DATE_MINIMUM); + res = dSiteOpen.julian - + (((join_key - 1) * WEB_DATE_STAGGER) % nSiteDuration / 2); + res += (join_key % pWP->nParam) * nSiteDuration * 5; + break; + case WP_REC_END_DATE_ID: + strtodt(&dSiteOpen, DATE_MINIMUM); + res = dSiteOpen.julian - + ((join_key * WEB_DATE_STAGGER) % nSiteDuration / 2); + res += ((join_key + 1) % pWP->nParam) * nSiteDuration - 1; + break; + case WP_CREATION_DATE_SK: + /* page creation has to happen outside of the page window, to assure a + * constant number of pages, so it occurs in the gap between site + * creation and the site's actual activity. For sites that are replaced + * in the time span of the data set, this will depend on whether they + * are the first version or the second + */ + strtodt(&dSiteOpen, DATE_MINIMUM); + kSite = join_key / WEB_PAGES_PER_SITE + 1; + res = dSiteOpen.julian - + ((static_cast(kSite) * WEB_DATE_STAGGER) % nSiteDuration / 2); + if ((static_cast(kSite) % pWP->nParam) == + 0) /* this is a site that gets replaced */ + { + genrand_integer( + &nTemp, + DIST_UNIFORM, + static_cast(res), + dSiteOpen.julian, + 0, + col, + dsdGenContext); + res = nTemp; + } + break; + /***************** + * join key from here on is a date for which a valid site/page must be + * found the sk for a web page is a compound value: + * and each component is a combination of the unique site or page and + * the active revision to it + */ + case WR_WEB_PAGE_SK: + case WS_WEB_PAGE_SK: + res = genrand_integer( + NULL, DIST_UNIFORM, 1, WEB_PAGES_PER_SITE, 0, col, dsdGenContext); + break; + } + + return (res); +} + +/* + * Routine: mk_join(int from_tbl, int to_tbl, int join_count) + * Purpose: return a primary key for to_tbl, creating a join between from_tbl + *and to_tbl Algorithm: all joins are currently uniformly distributed. The + *calling convention allows for each join in the schema to be distributed + *differently Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: Relies on existing RNG code, which isn't really 64bit; will probably + *requre a rework of the genrand_xx routines + */ +ds_key_t mk_join( + int from_col, + int to_tbl, + ds_key_t join_count, + DSDGenContext& dsdGenContext) { + ds_key_t res; + int nYear, nFromTable = 0, nTableIndex = to_tbl; + tdef* pTdef; + + nFromTable = getTableFromColumn(from_col, dsdGenContext); + + /* + * if the table being joined to employs sparse keys, the join gets handled + * in sparse.c + */ + pTdef = getSimpleTdefsByNumber(to_tbl, dsdGenContext); + if (pTdef->flags & FL_SPARSE) { + if (pTdef->arSparseKeys == NULL) + initSparseKeys(to_tbl, dsdGenContext); + } + + switch (to_tbl) { + /* some tables require special handling */ + case CATALOG_PAGE: + return (cp_join(nFromTable, from_col, join_count, dsdGenContext)); + case DATET: + genrand_integer( + &nYear, + DIST_UNIFORM, + YEAR_MINIMUM, + YEAR_MAXIMUM, + 0, + from_col, + dsdGenContext); + return ( + date_join(nFromTable, from_col, join_count, nYear, dsdGenContext)); + case TIME: + return (time_join(nFromTable, from_col, join_count, dsdGenContext)); + /* the rest of the tables use standard, uniform joins */ + default: + /* + * all TYPE2 tables (i.e., history keeping dimensions) need a special + * join algorithm + */ + if (pTdef->flags & FL_TYPE_2) + return (scd_join(nTableIndex, from_col, join_count, dsdGenContext)); + + if (pTdef->flags & FL_SPARSE) + return (randomSparseKey(nTableIndex, from_col, dsdGenContext)); + + genrand_key( + &res, + DIST_UNIFORM, + static_cast(1), + get_rowcount(nTableIndex, dsdGenContext), + static_cast(0), + from_col, + dsdGenContext); + break; + } + + return (static_cast(res)); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/list.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/list.cpp new file mode 100644 index 0000000000000..f6d69e8d2a4c0 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/list.cpp @@ -0,0 +1,272 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "list.h" +#include +#include +#include +#include "config.h" +#include "error_msg.h" +#include "porting.h" + +list_t* makeList(int nFlags, int (*SortFunc)(const void* d1, const void* d2)) { + auto pRes = static_cast(malloc(sizeof(list_t))); + MALLOC_CHECK(pRes); + if (pRes == nullptr) + ReportError(QERR_NO_MEMORY, "client list", 1); + memset(pRes, 0, sizeof(list_t)); + pRes->nFlags = nFlags; + pRes->pSortFunc = SortFunc; + + return (pRes); +} + +list_t* addList(list_t* pList, void* pData) { + node_t* pInsertPoint; + unsigned int bMoveForward = + (static_cast(pList->nFlags) & L_FL_HEAD); + + auto pNode = static_cast(malloc(sizeof(node_t))); + MALLOC_CHECK(pNode); + if (!pNode) + ReportErrorNoLine(QERR_NO_MEMORY, "client node", 1); + memset(pNode, 0, sizeof(node_t)); + pNode->pData = pData; + + if (pList->nMembers == 0) /* first node */ + { + pList->head = pNode; + pList->tail = pNode; + pList->nMembers = 1; + return (pList); + } + + if (static_cast(pList->nFlags) & L_FL_SORT) { + if (pList->pSortFunc(pData, pList->head->pData) <= 0) { + /* new node become list head */ + pNode->pNext = pList->head; + pList->head->pPrev = pNode; + pList->head = pNode; + pList->nMembers += 1; + return (pList); + } + pInsertPoint = pList->head; + + /* find the correct point to insert new node */ + while (pInsertPoint) { + if (pList->pSortFunc(pInsertPoint->pData, pData) < 0) + break; + pInsertPoint = (bMoveForward) ? pInsertPoint->pNext : pInsertPoint->pPrev; + } + if (pInsertPoint) /* mid-list insert */ + { + pNode->pNext = pInsertPoint->pNext; + pNode->pPrev = pInsertPoint; + pInsertPoint->pNext = pNode; + } else { + if (bMoveForward) { + /* new node becomes list tail */ + pNode->pPrev = pList->tail; + pList->tail->pNext = pNode; + pList->tail = pNode; + } else { + /* new node become list head */ + pNode->pNext = pList->head; + pList->head->pPrev = pNode; + pList->head = pNode; + } + } + + pList->nMembers += 1; + + return (pList); + } + + if (static_cast(pList->nFlags) & L_FL_HEAD) { + pNode->pNext = pList->head; + pList->head->pPrev = pNode; + pList->head = pNode; + pList->nMembers += 1; + } else { + pNode->pPrev = pList->tail; + pList->tail->pNext = pNode; + pList->tail = pNode; + pList->nMembers += 1; + } + + return (pList); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void* removeItem(list_t* pList, int bHead) { + void* pResult; + + if (pList->nMembers == 0) + return (NULL); + + if (!bHead) { + pResult = pList->tail->pData; + pList->tail = pList->tail->pPrev; + pList->tail->pNext = NULL; + } else { + pResult = pList->head->pData; + pList->head = pList->head->pNext; + pList->head->pPrev = NULL; + } + + pList->nMembers -= 1; + + return (pResult); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void* getHead(list_t* pList) { + assert(pList); + + if (!pList->head) + return (NULL); + + pList->pCurrent = pList->head; + + return (pList->pCurrent->pData); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void* getTail(list_t* pList) { + assert(pList); + + if (!pList->tail) + return (NULL); + + pList->pCurrent = pList->tail; + + return (pList->pCurrent->pData); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void* getNext(list_t* pList) { + assert(pList); + + if (!pList->pCurrent->pNext) + return (NULL); + + pList->pCurrent = pList->pCurrent->pNext; + + return (pList->pCurrent->pData); +} + +/* + * Routine: + * Purpose: findList(list_t *pList, void *pData) + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void* findList(list_t* pList, void* pData) { + void* pNode; + struct LIST_NODE_T* pOldCurrent = pList->pCurrent; + + for (pNode = getHead(pList); pNode; pNode = getNext(pList)) + if (pList->pSortFunc(pNode, pData) == 0) { + pList->pCurrent = pOldCurrent; + return (pNode); + } + + pList->pCurrent = pOldCurrent; + return (NULL); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void* getItem(list_t* pList, int nIndex) { + void* pResult; + struct LIST_NODE_T* pOldCurrent = pList->pCurrent; + + if (nIndex > length(pList)) + return (NULL); + + for (pResult = getHead(pList); --nIndex; pResult = getNext(pList)) + ; + + pList->pCurrent = pOldCurrent; + return (pResult); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/load.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/load.cpp new file mode 100644 index 0000000000000..8390d6d763ab7 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/load.cpp @@ -0,0 +1,87 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "config.h" +#include "porting.h" +#include "tables.h" + +#ifdef SQLSERVER +// ODBC headers +#include +#include +#include +SQLHENV henv; +#endif + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int create_table(int nTable) { + return (0); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void load_init(void) + +{ +#ifdef SQLSERVER + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); + SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); +#endif + + return; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void load_close(void) { +#ifdef SQLSERVER + SQLFreeHandle(SQL_HANDLE_ENV, henv); +#endif + + return; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/misc.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/misc.cpp new file mode 100644 index 0000000000000..8ec2c59635ad7 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/misc.cpp @@ -0,0 +1,103 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "porting.h" +#ifndef USE_STDLIB_H +#include +#endif +#include +#ifdef AIX +#include +#endif /* AIX */ +#include +#include +#include "date.h" +#include "decimal.h" +#include "dist.h" +#include "genrand.h" +#include "misc.h" +#include "r_params.h" +#include "tdefs.h" + +static char* alpha_num = + "0123456789abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ,"; + +char* getenv(const char* name); +int print_separator(int sep); + +extern long Seed[]; + +#ifdef WIN32 +#define PATH_SEP '\\' +#else +#define PATH_SEP '/' +#endif + +int file_num = -1; + +/* + * + * Various routines that handle distributions, value selections and + * seed value management for the DSS benchmark. Current functions: + * env_config -- set config vars with optional environment override + * a_rnd(min, max) -- random alphanumeric within length range + */ + +/* + * env_config: look for a environmental variable setting and return its + * value; otherwise return the default supplied + */ +char* env_config(char* var, char* dflt) { + static char* evar; + + if ((evar = getenv(var)) != NULL) + return (evar); + else + return (dflt); +} + +/* + * generate a random string with length randomly selected in [min, max] + * and using the characters in alphanum (currently includes a space + * and comma) + */ +int a_rnd( + int min, + int max, + int column, + char* dest, + DSDGenContext& dsdGenContext) { + int i, len, char_int; + + genrand_integer(&len, DIST_UNIFORM, min, max, 0, column, dsdGenContext); + for (i = 0; i < len; i++) { + if (i % 5 == 0) + genrand_integer( + &char_int, + DIST_UNIFORM, + 0, + static_cast(1) << 30, + 0, + column, + dsdGenContext); + *(dest + i) = alpha_num[static_cast(char_int) & 077]; + char_int = static_cast(static_cast(char_int) >> 6); + } + *(dest + len) = '\0'; + return (len); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/nulls.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/nulls.cpp new file mode 100644 index 0000000000000..e1390de0610b8 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/nulls.cpp @@ -0,0 +1,86 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "nulls.h" +#include "config.h" +#include "genrand.h" +#include "porting.h" +#include "tdefs.h" + +/* + * Routine: nullCheck(int nColumn, DSDGenContext& dsdGenContext) + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int nullCheck(int nColumn, DSDGenContext& dsdGenContext) { + int nLastTable = 0; + tdef* pTdef; + ds_key_t kBitMask = 1; + + nLastTable = getTableFromColumn(nColumn, dsdGenContext); + pTdef = getSimpleTdefsByNumber(nLastTable, dsdGenContext); + + kBitMask = + (static_cast(kBitMask) + << static_cast(nColumn - pTdef->nFirstColumn)); + + return ((pTdef->kNullBitMap & kBitMask) != 0); +} + +/* +* Routine: nullSet(int *pDest, int nStream, DSDGenContext& dsdGenContext) +* Purpose: set the kNullBitMap for a particular table +* Algorithm: +* 1. if random[1,100] >= table's NULL pct, clear map and return +* 2. set map + +* Data Structures: +* +* Params: +* Returns: +* Called By: +* Calls: +* Assumptions: +* Side Effects: uses 2 RNG calls +* TODO: None +*/ +void nullSet(ds_key_t* pDest, int nStream, DSDGenContext& dsdGenContext) { + int nThreshold; + ds_key_t kBitMap; + int nLastTable = 0; + tdef* pTdef; + + nLastTable = getTableFromColumn(nStream, dsdGenContext); + pTdef = getSimpleTdefsByNumber(nLastTable, dsdGenContext); + + /* burn the RNG calls */ + genrand_integer( + &nThreshold, DIST_UNIFORM, 0, 9999, 0, nStream, dsdGenContext); + genrand_key(&kBitMap, DIST_UNIFORM, 1, MAXINT, 0, nStream, dsdGenContext); + + /* set the bitmap based on threshold and NOT NULL definitions */ + *pDest = 0; + if (nThreshold < pTdef->nNullPct) { + *pDest = kBitMap; + *pDest &= ~pTdef->kNotNullBitMap; + } + + return; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/parallel.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/parallel.cpp new file mode 100644 index 0000000000000..f51df2e40f8f4 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/parallel.cpp @@ -0,0 +1,197 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include +#include "config.h" +#include "genrand.h" +#include "porting.h" +#include "r_params.h" +#include "scaling.h" +#include "tdefs.h" + +/* + * Routine: split_work(int tnum, worker_t *w) + * Purpose: allocate work between processes and threads + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int split_work( + int tnum, + ds_key_t* pkFirstRow, + ds_key_t* pkRowCount, + DSDGenContext& dsdGenContext) { + ds_key_t kTotalRows, kRowsetSize, kExtraRows; + int nParallel, nChild; + + kTotalRows = get_rowcount(tnum, dsdGenContext); + nParallel = get_int("PARALLEL", dsdGenContext); + nChild = get_int("CHILD", dsdGenContext) + 1; + + /* + * 1. small tables aren't paralelized + * 2. nothing is parallelized unless a command line arg is supplied + */ + *pkFirstRow = 1; + *pkRowCount = kTotalRows; + + if (kTotalRows < 1000000) { + if (nChild > 1) /* small table; only build it once */ + { + *pkFirstRow = 1; + *pkRowCount = 0; + return (0); + } + return (1); + } + + if (!is_set("PARALLEL", dsdGenContext)) { + return (1); + } + + /* + * at this point, do the calculation to set the rowcount for this part of a + * parallel build + */ + kExtraRows = kTotalRows % nParallel; + kRowsetSize = (kTotalRows - kExtraRows) / nParallel; + + /* start the starting row id */ + *pkFirstRow += (nChild - 1) * kRowsetSize; + if (kExtraRows && (nChild - 1)) + *pkFirstRow += ((nChild - 1) < kExtraRows) ? (nChild - 1) : kExtraRows; + + /* set the rowcount for this child */ + *pkRowCount = kRowsetSize; + if (kExtraRows && (nChild <= kExtraRows)) + *pkRowCount += 1; + + return (1); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int checkSeeds(tdef* pTdef, DSDGenContext& dsdGenContext) { + int i, nReturnCode = 0; + static int bSetSeeds = 0; + + if (!dsdGenContext.checkSeeds_init) { + bSetSeeds = is_set("CHKSEEDS", dsdGenContext); + dsdGenContext.checkSeeds_init = 1; + } + + for (i = pTdef->nFirstColumn; i <= pTdef->nLastColumn; i++) { + if (bSetSeeds) { + if (dsdGenContext.Streams[i].nUsed > + dsdGenContext.Streams[i].nUsedPerRow) { + auto result = fprintf( + stderr, + "Seed overrun on column %d. Used: %d\n", + i, + dsdGenContext.Streams[i].nUsed); + if (result < 0) + perror("sprintf failed"); + dsdGenContext.Streams[i].nUsedPerRow = dsdGenContext.Streams[i].nUsed; + nReturnCode = 1; + } + } + dsdGenContext.Streams[i].nUsed = 0; /* reset for the next time */ + } + + return (nReturnCode); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int row_stop(int tbl, DSDGenContext& dsdGenContext) { + tdef* pTdef; + + pTdef = getSimpleTdefsByNumber(tbl, dsdGenContext); + checkSeeds(pTdef, dsdGenContext); + if (pTdef->flags & FL_PARENT) { + pTdef = getSimpleTdefsByNumber(pTdef->nParam, dsdGenContext); + checkSeeds(pTdef, dsdGenContext); + } + return (0); +} + +/* + * Routine: row_skip + * Purpose: skip over un-used rows in a table + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20020816 jms The second parameter should really be a ds_key_t to allow + * BIG skips + */ +int row_skip(int tbl, ds_key_t count, DSDGenContext& dsdGenContext) { + int i; + for (i = 0; dsdGenContext.Streams[i].nColumn != -1; i++) { + if (dsdGenContext.Streams[i].nTable == tbl) { + skip_random( + i, count * dsdGenContext.Streams[i].nUsedPerRow, dsdGenContext); + dsdGenContext.Streams[i].nUsed = 0; + dsdGenContext.Streams[i].nTotal = + count * dsdGenContext.Streams[i].nUsedPerRow; + } + if (dsdGenContext.Streams[i].nDuplicateOf && + (dsdGenContext.Streams[i].nDuplicateOf != i)) { + skip_random( + dsdGenContext.Streams[i].nDuplicateOf, + count * + dsdGenContext.Streams[dsdGenContext.Streams[i].nDuplicateOf] + .nUsedPerRow, + dsdGenContext); + dsdGenContext.Streams[dsdGenContext.Streams[i].nDuplicateOf].nUsed = 0; + dsdGenContext.Streams[dsdGenContext.Streams[i].nDuplicateOf].nTotal = + count * dsdGenContext.Streams[i].nUsedPerRow; + } + } + + return (0); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/permute.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/permute.cpp new file mode 100644 index 0000000000000..0ca880a434205 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/permute.cpp @@ -0,0 +1,103 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "config.h" +#include "porting.h" +#ifndef USE_STDLIB_H +#include +#endif +#include +#include "genrand.h" + +/* + * Routine: MakePermutation(int nSize) + * Purpose: Permute the integers in [1..nSize] + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int* makePermutation( + int* nNumberSet, + int nSize, + int nStream, + DSDGenContext& dsdGenContext) { + int i, nTemp, nIndex, *pInt; + + if (nSize <= 0) + return (NULL); + + if (!nNumberSet) { + nNumberSet = static_cast(malloc(nSize * sizeof(int))); + MALLOC_CHECK(nNumberSet); + pInt = nNumberSet; + for (i = 0; i < nSize; i++) + *pInt++ = i; + } + + for (i = 0; i < nSize; i++) { + nIndex = genrand_integer( + NULL, DIST_UNIFORM, 0, nSize - 1, 0, nStream, dsdGenContext); + nTemp = nNumberSet[i]; + nNumberSet[i] = nNumberSet[nIndex]; + nNumberSet[nIndex] = nTemp; + } + + return (nNumberSet); +} + +/* + * Routine: MakePermutation(int nSize) + * Purpose: Permute the integers in [1..nSize] + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t* makeKeyPermutation( + ds_key_t* nNumberSet, + ds_key_t nSize, + int nStream, + DSDGenContext& dsdGenContext) { + ds_key_t i, nTemp, nIndex, *pInt; + if (nSize <= 0) + return (NULL); + + if (!nNumberSet) { + nNumberSet = static_cast(malloc(nSize * sizeof(ds_key_t))); + MALLOC_CHECK(nNumberSet); + pInt = nNumberSet; + for (i = 0; i < nSize; i++) + *pInt++ = i; + } + + for (i = 0; i < nSize; i++) { + nIndex = genrand_key( + NULL, DIST_UNIFORM, 0, nSize - 1, 0, nStream, dsdGenContext); + nTemp = nNumberSet[i]; + nNumberSet[i] = nNumberSet[nIndex]; + nNumberSet[nIndex] = nTemp; + } + + return (nNumberSet); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/pricing.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/pricing.cpp new file mode 100644 index 0000000000000..37af73e46f7bb --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/pricing.cpp @@ -0,0 +1,459 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "pricing.h" +#include +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "decimal.h" +#include "dist.h" +#include "error_msg.h" +#include "genrand.h" +#include "porting.h" +#include "w_web_sales.h" + +#define MAX_LIMIT 12 +static ds_limits_t aPriceLimits[MAX_LIMIT] = { + {CS_PRICING, + CS_QUANTITY_MAX, + CS_MARKUP_MAX, + CS_DISCOUNT_MAX, + CS_WHOLESALE_MAX, + CS_COUPON_MAX}, + {SS_PRICING, + SS_QUANTITY_MAX, + SS_MARKUP_MAX, + SS_DISCOUNT_MAX, + SS_WHOLESALE_MAX, + SS_COUPON_MAX}, + {WS_PRICING, + WS_QUANTITY_MAX, + WS_MARKUP_MAX, + WS_DISCOUNT_MAX, + WS_WHOLESALE_MAX, + WS_COUPON_MAX}, + {CR_PRICING, + CS_QUANTITY_MAX, + CS_MARKUP_MAX, + CS_DISCOUNT_MAX, + CS_WHOLESALE_MAX, + CS_COUPON_MAX}, + {SR_PRICING, + SS_QUANTITY_MAX, + SS_MARKUP_MAX, + SS_DISCOUNT_MAX, + SS_WHOLESALE_MAX, + SS_COUPON_MAX}, + {WR_PRICING, + WS_QUANTITY_MAX, + WS_MARKUP_MAX, + WS_DISCOUNT_MAX, + WS_WHOLESALE_MAX, + WS_COUPON_MAX}, + {S_PLINE_PRICING, + WS_QUANTITY_MAX, + WS_MARKUP_MAX, + WS_DISCOUNT_MAX, + WS_WHOLESALE_MAX, + WS_COUPON_MAX}, + {S_CLIN_PRICING, + WS_QUANTITY_MAX, + WS_MARKUP_MAX, + WS_DISCOUNT_MAX, + WS_WHOLESALE_MAX, + WS_COUPON_MAX}, + {S_WLIN_PRICING, + WS_QUANTITY_MAX, + WS_MARKUP_MAX, + WS_DISCOUNT_MAX, + WS_WHOLESALE_MAX, + WS_COUPON_MAX}, + {S_SRET_PRICING, + WS_QUANTITY_MAX, + WS_MARKUP_MAX, + WS_DISCOUNT_MAX, + WS_WHOLESALE_MAX, + WS_COUPON_MAX}, + {S_CRET_PRICING, + WS_QUANTITY_MAX, + WS_MARKUP_MAX, + WS_DISCOUNT_MAX, + WS_WHOLESALE_MAX, + WS_COUPON_MAX}, + {S_WRET_PRICING, + WS_QUANTITY_MAX, + WS_MARKUP_MAX, + WS_DISCOUNT_MAX, + WS_WHOLESALE_MAX, + WS_COUPON_MAX} + +}; + +/* + * Routine: set_pricing(int nTabId, ds_pricing_t *pPricing) + * Purpose: handle the various pricing calculations for the fact tables + * Notes: + * the RNG usage is not kept in sync between sales pricing and returns + *pricing. If the calculations look wrong, it may be necessary to "waste" some + *RNG calls on one side or the other to bring things back in line Data + *Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void set_pricing( + int nTabId, + ds_pricing_t* pPricing, + DSDGenContext& dsdGenContext) { + int nLastId = -1, nQuantityMax = std::numeric_limits::max(), + nQuantityMin = 1; + decimal_t dQuantity, dMarkupMin, dDiscountMin, dWholesaleMin, dMarkupMax, + dDiscountMax, dWholesaleMax, dCouponMin, dCouponMax, dZero, dOneHalf, + d9pct, dOne, dTemp, dHundred; + decimal_t dMarkup, dCoupon, dShipping, dDiscount, dTemp2; + int i, nCashPct, nCreditPct, nCouponUsage; + + strtodec(&dMarkupMin, "0.00"); + strtodec(&dDiscountMin, "0.00"); + strtodec(&dWholesaleMin, "1.00"); + strtodec(&dCouponMin, "0.00"); + strtodec(&dZero, "0.00"); + strtodec(&dOneHalf, "0.50"); + strtodec(&d9pct, "0.09"); + strtodec(&dWholesaleMin, "1.00"); + strtodec(&dHundred, "100.00"); + strtodec(&dOne, "1.00"); + + if (nTabId != nLastId) { + nLastId = -1; + for (i = 0; i < MAX_LIMIT; i++) { + if (nTabId == aPriceLimits[i].nId) + nLastId = i; + } + if (nLastId == -1) + INTERNAL("No pricing limits defined"); + nQuantityMax = atoi(aPriceLimits[nLastId].szQuantity); + strtodec(&dDiscountMax, aPriceLimits[nLastId].szDiscount); + strtodec(&dMarkupMax, aPriceLimits[nLastId].szMarkUp); + strtodec(&dWholesaleMax, aPriceLimits[nLastId].szWholesale); + strtodec(&dCouponMax, aPriceLimits[nLastId].szCoupon); + } + + switch (nTabId) { + case SS_PRICING: + case CS_PRICING: + case WS_PRICING: + case S_PLINE_PRICING: + case S_CLIN_PRICING: + case S_WLIN_PRICING: + genrand_integer( + &pPricing->quantity, + DIST_UNIFORM, + nQuantityMin, + nQuantityMax, + 0, + nTabId, + dsdGenContext); + itodec(&dQuantity, pPricing->quantity); + genrand_decimal( + &pPricing->wholesale_cost, + DIST_UNIFORM, + &dWholesaleMin, + &dWholesaleMax, + NULL, + nTabId, + dsdGenContext); + + /* ext_wholesale_cost = wholesale_cost * quantity */ + decimal_t_op( + &pPricing->ext_wholesale_cost, + OP_MULT, + &dQuantity, + &pPricing->wholesale_cost); + + /* list_price = wholesale_cost * (1 + markup) */ + genrand_decimal( + &dMarkup, + DIST_UNIFORM, + &dMarkupMin, + &dMarkupMax, + NULL, + nTabId, + dsdGenContext); + decimal_t_op(&dMarkup, OP_PLUS, &dMarkup, &dOne); + decimal_t_op( + &pPricing->list_price, OP_MULT, &pPricing->wholesale_cost, &dMarkup); + + /* sales_price = list_price * (1 - discount)*/ + genrand_decimal( + &dDiscount, + DIST_UNIFORM, + &dDiscountMin, + &dDiscountMax, + NULL, + nTabId, + dsdGenContext); + NegateDecimal(&dDiscount); + decimal_t_op(&pPricing->ext_discount_amt, OP_PLUS, &dDiscount, &dOne); + decimal_t_op( + &pPricing->sales_price, + OP_MULT, + &pPricing->list_price, + &pPricing->ext_discount_amt); + + /* ext_list_price = list_price * quantity */ + decimal_t_op( + &pPricing->ext_list_price, + OP_MULT, + &pPricing->list_price, + &dQuantity); + + /* ext_sales_price = sales_price * quantity */ + decimal_t_op( + &pPricing->ext_sales_price, + OP_MULT, + &pPricing->sales_price, + &dQuantity); + + /* ext_discount_amt = ext_list_price - ext_sales_price */ + decimal_t_op( + &pPricing->ext_discount_amt, + OP_MINUS, + &pPricing->ext_list_price, + &pPricing->ext_sales_price); + + /* coupon_amt = ext_sales_price * coupon */ + genrand_decimal( + &dCoupon, DIST_UNIFORM, &dZero, &dOne, NULL, nTabId, dsdGenContext); + genrand_integer( + &nCouponUsage, DIST_UNIFORM, 1, 100, 0, nTabId, dsdGenContext); + if (nCouponUsage <= 20) /* 20% of sales employ a coupon */ + decimal_t_op( + &pPricing->coupon_amt, + OP_MULT, + &pPricing->ext_sales_price, + &dCoupon); + else + memcpy(&pPricing->coupon_amt, &dZero, sizeof(decimal_t)); + + /* net_paid = ext_sales_price - coupon_amt */ + decimal_t_op( + &pPricing->net_paid, + OP_MINUS, + &pPricing->ext_sales_price, + &pPricing->coupon_amt); + + /* shipping_cost = list_price * shipping */ + genrand_decimal( + &dShipping, + DIST_UNIFORM, + &dZero, + &dOneHalf, + NULL, + nTabId, + dsdGenContext); + decimal_t_op( + &pPricing->ship_cost, OP_MULT, &pPricing->list_price, &dShipping); + + /* ext_shipping_cost = shipping_cost * quantity */ + decimal_t_op( + &pPricing->ext_ship_cost, OP_MULT, &pPricing->ship_cost, &dQuantity); + + /* net_paid_inc_ship = net_paid + ext_shipping_cost */ + decimal_t_op( + &pPricing->net_paid_inc_ship, + OP_PLUS, + &pPricing->net_paid, + &pPricing->ext_ship_cost); + + /* ext_tax = tax * net_paid */ + genrand_decimal( + &pPricing->tax_pct, + DIST_UNIFORM, + &dZero, + &d9pct, + NULL, + nTabId, + dsdGenContext); + decimal_t_op( + &pPricing->ext_tax, OP_MULT, &pPricing->net_paid, &pPricing->tax_pct); + + /* net_paid_inc_tax = net_paid + ext_tax */ + decimal_t_op( + &pPricing->net_paid_inc_tax, + OP_PLUS, + &pPricing->net_paid, + &pPricing->ext_tax); + + /* net_paid_inc_ship_tax = net_paid_inc_tax + ext_shipping_cost */ + decimal_t_op( + &pPricing->net_paid_inc_ship_tax, + OP_PLUS, + &pPricing->net_paid_inc_ship, + &pPricing->ext_tax); + + /* net_profit = net_paid - ext_wholesale_cost */ + decimal_t_op( + &pPricing->net_profit, + OP_MINUS, + &pPricing->net_paid, + &pPricing->ext_wholesale_cost); + break; + case CR_PRICING: + case SR_PRICING: + case WR_PRICING: + /* quantity is determined before we are called */ + /* ext_wholesale_cost = wholesale_cost * quantity */ + itodec(&dQuantity, pPricing->quantity); + decimal_t_op( + &pPricing->ext_wholesale_cost, + OP_MULT, + &dQuantity, + &pPricing->wholesale_cost); + + /* ext_list_price = list_price * quantity */ + decimal_t_op( + &pPricing->ext_list_price, + OP_MULT, + &pPricing->list_price, + &dQuantity); + + /* ext_sales_price = sales_price * quantity */ + decimal_t_op( + &pPricing->ext_sales_price, + OP_MULT, + &pPricing->sales_price, + &dQuantity); + + /* net_paid = ext_list_price (couppons don't effect returns) */ + memcpy( + &pPricing->net_paid, &pPricing->ext_sales_price, sizeof(decimal_t)); + + /* shipping_cost = list_price * shipping */ + genrand_decimal( + &dShipping, + DIST_UNIFORM, + &dZero, + &dOneHalf, + NULL, + nTabId, + dsdGenContext); + decimal_t_op( + &pPricing->ship_cost, OP_MULT, &pPricing->list_price, &dShipping); + + /* ext_shipping_cost = shipping_cost * quantity */ + decimal_t_op( + &pPricing->ext_ship_cost, OP_MULT, &pPricing->ship_cost, &dQuantity); + + /* net_paid_inc_ship = net_paid + ext_shipping_cost */ + decimal_t_op( + &pPricing->net_paid_inc_ship, + OP_PLUS, + &pPricing->net_paid, + &pPricing->ext_ship_cost); + + /* ext_tax = tax * net_paid */ + decimal_t_op( + &pPricing->ext_tax, OP_MULT, &pPricing->net_paid, &pPricing->tax_pct); + + /* net_paid_inc_tax = net_paid + ext_tax */ + decimal_t_op( + &pPricing->net_paid_inc_tax, + OP_PLUS, + &pPricing->net_paid, + &pPricing->ext_tax); + + /* net_paid_inc_ship_tax = net_paid_inc_tax + ext_shipping_cost */ + decimal_t_op( + &pPricing->net_paid_inc_ship_tax, + OP_PLUS, + &pPricing->net_paid_inc_ship, + &pPricing->ext_tax); + + /* net_profit = net_paid - ext_wholesale_cost */ + decimal_t_op( + &pPricing->net_profit, + OP_MINUS, + &pPricing->net_paid, + &pPricing->ext_wholesale_cost); + + /* see to it that the returned amounts add up to the total returned */ + /* allocate some of return to cash */ + genrand_integer( + &nCashPct, DIST_UNIFORM, 0, 100, 0, nTabId, dsdGenContext); + itodec(&dTemp, nCashPct); + decimal_t_op(&pPricing->refunded_cash, OP_DIV, &dTemp, &dHundred); + decimal_t_op( + &pPricing->refunded_cash, + OP_MULT, + &pPricing->refunded_cash, + &pPricing->net_paid); + + /* allocate some to reversed charges */ + genrand_integer( + &nCreditPct, DIST_UNIFORM, 1, 100, 0, nTabId, dsdGenContext); + itodec(&dTemp2, nCreditPct); + decimal_t_op(&dTemp, OP_DIV, &dTemp2, &dHundred); + decimal_t_op( + &dTemp2, OP_MINUS, &pPricing->net_paid, &pPricing->refunded_cash); + decimal_t_op(&pPricing->reversed_charge, OP_MULT, &dTemp2, &dTemp); + + /* the rest is store credit */ + decimal_t_op( + &pPricing->store_credit, + OP_MINUS, + &pPricing->net_paid, + &pPricing->reversed_charge); + decimal_t_op( + &pPricing->store_credit, + OP_MINUS, + &pPricing->store_credit, + &pPricing->refunded_cash); + + /* pick a fee for the return */ + genrand_decimal( + &pPricing->fee, + DIST_UNIFORM, + &dOneHalf, + &dHundred, + &dZero, + nTabId, + dsdGenContext); + + /* and calculate the net effect */ + decimal_t_op( + &pPricing->net_loss, + OP_MINUS, + &pPricing->net_paid_inc_ship_tax, + &pPricing->store_credit); + decimal_t_op( + &pPricing->net_loss, + OP_MINUS, + &pPricing->net_loss, + &pPricing->refunded_cash); + decimal_t_op( + &pPricing->net_loss, + OP_MINUS, + &pPricing->net_loss, + &pPricing->reversed_charge); + decimal_t_op( + &pPricing->net_loss, OP_PLUS, &pPricing->net_loss, &pPricing->fee); + break; + } + + return; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/r_params.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/r_params.cpp new file mode 100644 index 0000000000000..4647569f675fc --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/r_params.cpp @@ -0,0 +1,707 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +/* + * parameter handling functions + */ +#include "r_params.h" +#include +#include +#include +#include +#include +#include "config.h" +#include "dist.h" +#include "porting.h" +#include "tdefs.h" + +#define PARAM_MAX_LEN 80 +#define MAX_LINE_LEN 120 +#ifdef WIN32 +#define OPTION_START '/' +#else +#define OPTION_START '-' +#endif + +#ifndef TEST +extern option_t options[]; +extern char* params[]; +#else +option_t options[] = { + {"PROG", OPT_STR | OPT_HIDE, 0, NULL, NULL, "tester"}, + {"PARAMS", OPT_STR, 1, "read parameters from file ", read_file, ""}, + {"DISTRIBUTIONS", + OPT_STR, + 2, + "read distributions from file ", + NULL, + "tester_dist.idx"}, + {"OUTDIR", OPT_STR, 3, "generate files in directory ", NULL, "./"}, + {"VERBOSE", OPT_FLG, 4, "enable verbose output", NULL, "N"}, + {"HELP", OPT_FLG, 5, "display this message", usage, "N"}, + {"scale", OPT_INT, 6, "set scale to ", NULL, "1"}, + NULL}; +char* params[9]; +#endif + +int read_file(const char* param_name, const char* option); +int fnd_param(const char* name, DSDGenContext& dsdGenContext); +void print_params(DSDGenContext& dsdGenContext); + +/* + * Routine: load_params() + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20010621 JMS shared memory not yet implemented + */ +void load_params() { + /* + int i=0; + while (options[i].name != NULL) + { + load_param(i, GetSharedMemoryParam(options[i].index)); + i++; + } + SetSharedMemoryStat(STAT_ROWCOUNT, get_int("STEP"), 0); + */ + return; +} + +/* + * Routine: set_flag(int f) + * Purpose: set a toggle parameter + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void set_flg(const char* flag, DSDGenContext& dsdGenContext) { + int nParam; + + init_params(dsdGenContext); + nParam = fnd_param(flag, dsdGenContext); + if (nParam >= 0) + strcpy(dsdGenContext.params[dsdGenContext.options[nParam].index], "Y"); + + return; +} + +/* + * Routine: clr_flg(f) + * Purpose: clear a toggle parameter + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void clr_flg(const char* flag, DSDGenContext& dsdGenContext) { + int nParam; + + init_params(dsdGenContext); + nParam = fnd_param(flag, dsdGenContext); + if (nParam >= 0) + strcpy(dsdGenContext.params[dsdGenContext.options[nParam].index], "N"); + return; +} + +/* + * Routine: is_set(int f) + * Purpose: return the state of a toggle parameter, or whether or not a string + * or int parameter has been set Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int is_set(const char* flag, DSDGenContext& dsdGenContext) { + int nParam, bIsSet = 0; + + init_params(dsdGenContext); + nParam = fnd_param(flag, dsdGenContext); + if (nParam >= 0) { + if ((static_cast(dsdGenContext.options[nParam].flags) & + TYPE_MASK) == OPT_FLG) + bIsSet = + (dsdGenContext.params[dsdGenContext.options[nParam].index][0] == 'Y') + ? 1 + : 0; + else + bIsSet = (static_cast(dsdGenContext.options[nParam].flags) & + OPT_SET) || + (strlen(dsdGenContext.options[nParam].dflt) > 0); + } + + return (bIsSet); /* better a false negative than a false positive ? */ +} + +/* + * Routine: set_int(int var, char *value) + * Purpose: set an integer parameter + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void set_int(const char* var, const char* val, DSDGenContext& dsdGenContext) { + int nParam; + + init_params(dsdGenContext); + nParam = fnd_param(var, dsdGenContext); + if (nParam >= 0) { + strcpy(dsdGenContext.params[dsdGenContext.options[nParam].index], val); + dsdGenContext.options[nParam].flags = static_cast( + static_cast(dsdGenContext.options[nParam].flags) | OPT_SET); + } + return; +} + +/* + * Routine: get_int(char *var) + * Purpose: return the value of an integer parameter + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int get_int(const char* var, DSDGenContext& dsdGenContext) { + int nParam; + + init_params(dsdGenContext); + nParam = fnd_param(var, dsdGenContext); + if (nParam >= 0) + return (atoi(dsdGenContext.params[dsdGenContext.options[nParam].index])); + else + return (0); +} + +double get_dbl(const char* var, DSDGenContext& dsdGenContext) { + int nParam; + + init_params(dsdGenContext); + nParam = fnd_param(var, dsdGenContext); + if (nParam >= 0) + return (atof(dsdGenContext.params[dsdGenContext.options[nParam].index])); + else + return (0); +} + +/* + * Routine: set_str(int var, char *value) + * Purpose: set a character parameter + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void set_str(const char* var, const char* val, DSDGenContext& dsdGenContext) { + int nParam; + + init_params(dsdGenContext); + nParam = fnd_param(var, dsdGenContext); + if (nParam >= 0) { + strcpy(dsdGenContext.params[dsdGenContext.options[nParam].index], val); + dsdGenContext.options[nParam].flags = static_cast( + static_cast(dsdGenContext.options[nParam].flags) | OPT_SET); + } + + return; +} + +/* + * Routine: get_str(char * var) + * Purpose: return the value of a character parameter + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +char* get_str(const char* var, DSDGenContext& dsdGenContext) { + int nParam; + + init_params(dsdGenContext); + nParam = fnd_param(var, dsdGenContext); + if (nParam >= 0) + return (dsdGenContext.params[dsdGenContext.options[nParam].index]); + else + return (NULL); +} + +/* + * Routine: init_params(DSDGenContext& dsdGenContext) + * Purpose: initialize a parameter set, setting default values + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int init_params(DSDGenContext& dsdGenContext) { + int i; + + if (dsdGenContext.init_params_init) + return (0); + + for (i = 0; dsdGenContext.options[i].name != NULL; i++) { + dsdGenContext.params[dsdGenContext.options[i].index] = + static_cast(malloc(PARAM_MAX_LEN * sizeof(char))); + MALLOC_CHECK(dsdGenContext.params[dsdGenContext.options[i].index]); + strncpy( + dsdGenContext.params[dsdGenContext.options[i].index], + dsdGenContext.options[i].dflt, + 80); + if (*dsdGenContext.options[i].dflt) + dsdGenContext.options[i].flags = static_cast( + static_cast(dsdGenContext.options[i].flags) | OPT_DFLT); + } + + dsdGenContext.init_params_init = 1; + + return (0); +} + +/* + * Routine: save_file(char *path) + * Purpose: print a summary of options + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int save_file(const char* path, DSDGenContext& dsdGenContext) { + int i, w_adjust; + FILE* ofp; + time_t timestamp; + + init_params(dsdGenContext); + time(×tamp); + + if ((ofp = fopen(path, "w")) == NULL) + return (-1); + + auto result = fprintf( + ofp, + "--\n-- %s Benchmark Parameter File\n-- Created: %s", + get_str("PROG", dsdGenContext), + ctime(×tamp)); + if (result < 0) + perror("sprintf failed"); + result = fprintf( + ofp, + "--\n-- Each entry is of the form: ' = -- " + "optional comment'\n"); + if (result < 0) + perror("sprintf failed"); + result = fprintf( + ofp, "-- Refer to benchmark documentation for more details\n--\n"); + if (result < 0) + perror("sprintf failed"); + + for (i = 0; dsdGenContext.options[i].name != NULL; i++) { + if (static_cast(dsdGenContext.options[i].flags) & + OPT_HIDE) /* hidden option */ + continue; + if (strlen(dsdGenContext.params[dsdGenContext.options[i].index]) == 0) + continue; + + result = fprintf(ofp, "%s = ", dsdGenContext.options[i].name); + if (result < 0) + perror("sprintf failed"); + w_adjust = strlen(dsdGenContext.options[i].name) + 3; + if (static_cast(dsdGenContext.options[i].flags) & OPT_STR) { + result = fprintf( + ofp, "\"%s\"", dsdGenContext.params[dsdGenContext.options[i].index]); + if (result < 0) + perror("sprintf failed"); + w_adjust += 2; + } else { + result = fprintf( + ofp, "%s", dsdGenContext.params[dsdGenContext.options[i].index]); + if (result < 0) + perror("sprintf failed"); + } + w_adjust += + strlen(dsdGenContext.params[dsdGenContext.options[i].index]) + 3; + w_adjust = 60 - w_adjust; + result = + fprintf(ofp, "%*s-- %s", w_adjust, " ", dsdGenContext.options[i].usage); + if (result < 0) + perror("sprintf failed"); + if (static_cast(dsdGenContext.options[i].flags) & OPT_NOP) { + result = fprintf(ofp, " NOT IMPLEMENTED"); + if (result < 0) + perror("sprintf failed"); + } + result = fprintf(ofp, "\n"); + if (result < 0) + perror("sprintf failed"); + } + + fclose(ofp); + + return (0); +} + +/* + * Routine: set_option(int var, char *value) + * Purpose: set a particular parameter; main entry point for the module + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int set_option(const char* name, const char* param) { + printf("ERROR: set_option not supported"); + assert(0); + exit(1); +} + +/* + * Routine: process_options(int count, char **vector) + * Purpose: process a set of command line options + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20000309 need to return integer to allow processing of left-over args + */ +int process_options( + int count, + const char** vector, + DSDGenContext& dsdGenContext) { + int option_num = 1, res = 1; + + init_params(dsdGenContext); + + while (option_num < count) { + if (*vector[option_num] == OPTION_START) { + if (option_num == (count - 1)) + res = set_option(vector[option_num] + 1, NULL); + else + res = set_option(vector[option_num] + 1, vector[option_num + 1]); + } + + if (res < 0) { + auto result = printf( + "ERROR: option '%s' or its argument unknown.\n", + (vector[option_num] + 1)); + if (result < 0) + perror("sprintf failed"); + usage(NULL, NULL, dsdGenContext); + exit(1); + } else + option_num += res; + } + +#ifdef JMS + if (is_set("VERBOSE", dsdGenContext)) + print_params(dsdGenContext); +#endif + + return (option_num); +} + +/* + * Routine: print_params(DSDGenContext& dsdGenContext) + * Purpose: print a parameter summary to display current settings + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void print_params(DSDGenContext& dsdGenContext) { + int i; + + init_params(dsdGenContext); + + for (i = 0; dsdGenContext.options[i].name != NULL; i++) + if (dsdGenContext.options[i].name != NULL) { + auto result = printf("%s = ", dsdGenContext.options[i].name); + if (result < 0) + perror("sprintf failed"); + switch (static_cast(dsdGenContext.options[i].flags) & + TYPE_MASK) { + case OPT_INT: { + result = printf( + "%d\n", + get_int( + const_cast(dsdGenContext.options[i].name), + dsdGenContext)); + if (result < 0) + perror("sprintf failed"); + break; + } + case OPT_STR: { + result = printf( + "%s\n", + get_str( + const_cast(dsdGenContext.options[i].name), + dsdGenContext)); + if (result < 0) + perror("sprintf failed"); + break; + } + case OPT_FLG: { + result = printf( + "%c\n", + is_set( + const_cast(dsdGenContext.options[i].name), + dsdGenContext) + ? 'Y' + : 'N'); + if (result < 0) + perror("sprintf failed"); + break; + } + } + } + + return; +} + +/* + * Routine: fnd_param(char *name, int *type, char *value, DSDGenContext& + * dsdGenContext) Purpose: traverse the defined parameters, looking for a match + * Algorithm: + * Data Structures: + * + * Params: + * Returns: index of option + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int fnd_param(const char* name, DSDGenContext& dsdGenContext) { + int i, res = -1; + + for (i = 0; dsdGenContext.options[i].name != NULL; i++) { + if (strncasecmp(name, dsdGenContext.options[i].name, strlen(name)) == 0) { + if (res == -1) + res = i; + else + return (-1); + } + } + + return (res); +} + +/* + * Routine: GetParamName(int nParam) + * Purpose: Translate between a parameter index and its name + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +char* GetParamName(int nParam, DSDGenContext& dsdGenContext) { + init_params(dsdGenContext); + + return const_cast(dsdGenContext.options[nParam].name); +} + +/* + * Routine: GetParamValue(int nParam) + * Purpose: Retrieve a parameters string value based on an index + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +char* GetParamValue(int nParam, DSDGenContext& dsdGenContext) { + init_params(dsdGenContext); + + return (dsdGenContext.params[dsdGenContext.options[nParam].index]); +} + +/* + * Routine: load_param(char *szValue, int nParam) + * Purpose: Set a parameter based on an index + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int load_param(int nParam, const char* szValue, DSDGenContext& dsdGenContext) { + init_params(dsdGenContext); + + if (static_cast(dsdGenContext.options[nParam].flags) & + OPT_SET) /* already set from the command line */ + return (0); + else + strcpy(dsdGenContext.params[dsdGenContext.options[nParam].index], szValue); + + return (0); +} + +/* + * Routine: IsIntParam(char *szValue, int nParam) + * Purpose: Boolean test for integer parameter + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int IsIntParam(const char* szParam, DSDGenContext& dsdGenContext) { + int nParam; + + if ((nParam = fnd_param(szParam, dsdGenContext)) == -1) + return (nParam); + + return ( + (static_cast(dsdGenContext.options[nParam].flags) & OPT_INT) + ? 1 + : 0); +} + +/* + * Routine: IsStrParam(char *szValue, int nParam) + * Purpose: Boolean test for string parameter + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int IsStrParam(const char* szParam, DSDGenContext& dsdGenContext) { + int nParam; + + if ((nParam = fnd_param(szParam, dsdGenContext)) == -1) + return (nParam); + + return ( + (static_cast(dsdGenContext.options[nParam].flags) & OPT_STR) + ? 1 + : 0); +} + +#ifdef TEST + +main() { + init_params(); + set_int("SCALE", "7"); + set_flg("VERBOSE"); + set_str("DISTRIBUTIONS", "'some file name'"); + print_params(); + set_int("s", "8"); + clr_flg("VERBOSE"); + printf("DIST is %s\n", get_str("DISTRIBUTIONS")); + print_params(); + usage(NULL, NULL); +} +#endif /* TEST_PARAMS */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/scaling.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/scaling.cpp new file mode 100644 index 0000000000000..d13e7a5847519 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/scaling.cpp @@ -0,0 +1,785 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "scaling.h" +#include +#include +#include +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "dist.h" +#include "error_msg.h" +#include "genrand.h" +#include "parallel.h" +#include "porting.h" +#include "r_params.h" +#include "scd.h" +#include "tdef_functions.h" +#include "tdefs.h" +#include "tpcds.idx.h" +#include "w_inventory.h" + +void setUpdateScaling(int table, DSDGenContext& dsdGenContext); +int row_skip(int tbl, ds_key_t count, DSDGenContext& dsdGenContext); + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int getScaleSlot(int nTargetGB, DSDGenContext& dsdGenContext) { + int i; + + for (i = 0; nTargetGB > dsdGenContext.arScaleVolume[i]; i++) + ; + + return (i); +} + +/* + * Routine: LogScale(void) + * Purpose: use the command line volume target, in GB, to calculate the global + * rowcount multiplier Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: arRowcounts are set to the appropriate number of rows for the + * target scale factor + * TODO: None + */ +static ds_key_t +LogScale(int nTable, int nTargetGB, DSDGenContext& dsdGenContext) { + int nIndex = 1, nDelta, i; + float fOffset; + ds_key_t hgRowcount = 0; + + i = getScaleSlot(nTargetGB, dsdGenContext); + + nDelta = dist_weight(NULL, "rowcounts", nTable + 1, i + 1, dsdGenContext) - + dist_weight(NULL, "rowcounts", nTable + 1, i, dsdGenContext); + fOffset = + static_cast(nTargetGB - dsdGenContext.arScaleVolume[i - 1]) / + static_cast( + dsdGenContext.arScaleVolume[i] - dsdGenContext.arScaleVolume[i - 1]); + + hgRowcount = static_cast(fOffset * static_cast(nDelta)); + hgRowcount += + dist_weight(NULL, "rowcounts", nTable + 1, nIndex, dsdGenContext); + + return (hgRowcount); +} + +/* + * Routine: StaticScale(void) + * Purpose: use the command line volume target, in GB, to calculate the global + * rowcount multiplier Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: arRowcounts are set to the appropriate number of rows for the + * target scale factor + * TODO: None + */ +static ds_key_t +StaticScale(int nTable, int nTargetGB, DSDGenContext& dsdGenContext) { + return (dist_weight(NULL, "rowcounts", nTable + 1, 1, dsdGenContext)); +} + +/* + * Routine: LinearScale(void) + * Purpose: use the command line volume target, in GB, to calculate the global + *rowcount multiplier Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: scale factors defined in rowcounts distribution define + *1/10/100/1000/... GB with sufficient accuracy Side Effects: arRowcounts are + *set to the appropriate number of rows for the target scale factor + * TODO: None + */ +static ds_key_t +LinearScale(int nTable, int nTargetGB, DSDGenContext& dsdGenContext) { + int i; + ds_key_t hgRowcount = 0; + + for (i = 8; i >= 0; i--) /* work from large scales down)*/ + { + /* + * use the defined rowcounts to build up the target GB volume + */ + while (nTargetGB >= dsdGenContext.arScaleVolume[i]) { + hgRowcount += + dist_weight(NULL, "rowcounts", nTable + 1, i + 1, dsdGenContext); + nTargetGB -= dsdGenContext.arScaleVolume[i]; + } + } + + return (hgRowcount); +} +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t getIDCount(int nTable, DSDGenContext& dsdGenContext) { + ds_key_t kRowcount, kUniqueCount; + tdef* pTdef; + + kRowcount = get_rowcount(nTable, dsdGenContext); + if (nTable >= PSEUDO_TABLE_START) + return (kRowcount); + pTdef = getSimpleTdefsByNumber(nTable, dsdGenContext); + if (pTdef->flags & FL_TYPE_2) { + kUniqueCount = (kRowcount / 6) * 3; + switch (kRowcount % 6) { + case 1: + kUniqueCount += 1; + break; + case 2: + case 3: + kUniqueCount += 2; + break; + case 4: + case 5: + kUniqueCount += 3; + break; + } + return (kUniqueCount); + } else { + return (kRowcount); + } +} + +/* + * Routine: get_rowcount(int table) + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20040820 jms Need to address special case scaling in a more general + * fashion + */ +ds_key_t get_rowcount(int table, DSDGenContext& dsdGenContext) { + static double nScale; + int nTable, nMultiplier, i, nBadScale = 0, nRowcountOffset = 0; + tdef* pTdef; + + if (!dsdGenContext.get_rowcount_init) { + nScale = get_dbl("SCALE", dsdGenContext); + if (nScale > 100000) + ReportErrorNoLine(QERR_BAD_SCALE, NULL, 1); + + memset(dsdGenContext.arRowcount, 0, sizeof(long) * MAX_TABLE); + int iScale = nScale < 1 ? 1 : static_cast(nScale); + for (nTable = CALL_CENTER; nTable <= MAX_TABLE; nTable++) { + switch (iScale) { + case 100000: + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 9, + dsdGenContext); + break; + case 30000: + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 8, + dsdGenContext); + break; + case 10000: + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 7, + dsdGenContext); + break; + case 3000: + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 6, + dsdGenContext); + break; + case 1000: + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 5, + dsdGenContext); + break; + case 300: + nBadScale = QERR_BAD_SCALE; + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 4, + dsdGenContext); + break; + case 100: + nBadScale = QERR_BAD_SCALE; + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 3, + dsdGenContext); + break; + case 10: + nBadScale = QERR_BAD_SCALE; + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 2, + dsdGenContext); + break; + case 1: + nBadScale = QERR_QUALIFICATION_SCALE; + dsdGenContext.arRowcount[nTable].kBaseRowcount = dist_weight( + NULL, + "rowcounts", + nTable + nRowcountOffset + 1, + 1, + dsdGenContext); + break; + default: + nBadScale = QERR_BAD_SCALE; + int mem = + dist_member(NULL, "rowcounts", nTable + 1, 3, dsdGenContext); + switch (mem) { + case 2: + dsdGenContext.arRowcount[nTable].kBaseRowcount = + LinearScale(nTable + nRowcountOffset, nScale, dsdGenContext); + break; + case 1: + dsdGenContext.arRowcount[nTable].kBaseRowcount = + StaticScale(nTable + nRowcountOffset, nScale, dsdGenContext); + break; + case 3: + dsdGenContext.arRowcount[nTable].kBaseRowcount = + LogScale(nTable + nRowcountOffset, nScale, dsdGenContext); + break; + } /* switch(FL_SCALE_MASK) */ + break; + } /* switch(nScale) */ + + /* now adjust for the multiplier */ + nMultiplier = 1; + if (nTable < PSEUDO_TABLE_START) { + pTdef = getSimpleTdefsByNumber(nTable, dsdGenContext); + nMultiplier = (pTdef->flags & FL_TYPE_2) ? 2 : 1; + } + for (i = 1; + i <= dist_member(NULL, "rowcounts", nTable + 1, 2, dsdGenContext); + i++) { + nMultiplier *= 10; + } + if (dsdGenContext.arRowcount[nTable].kBaseRowcount >= 0) { + if (nScale < 1) { + int mem = + dist_member(NULL, "rowcounts", nTable + 1, 3, dsdGenContext); + if ((mem > 1)) { + dsdGenContext.arRowcount[nTable].kBaseRowcount = static_cast( + dsdGenContext.arRowcount[nTable].kBaseRowcount * nScale); + } + if (dsdGenContext.arRowcount[nTable].kBaseRowcount == 0) { + dsdGenContext.arRowcount[nTable].kBaseRowcount = 1; + } + } + } + dsdGenContext.arRowcount[nTable].kBaseRowcount *= nMultiplier; + } /* for each table */ + + // if (nBadScale && !is_set("QUIET")) + // ReportErrorNoLine(nBadScale, NULL, 0); + + dsdGenContext.get_rowcount_init = 1; + } + + if (table == INVENTORY) + return (sc_w_inventory(nScale, dsdGenContext)); + if (table == S_INVENTORY) + return ( + getIDCount(ITEM, dsdGenContext) * + get_rowcount(WAREHOUSE, dsdGenContext) * 6); + + return (dsdGenContext.arRowcount[table].kBaseRowcount); +} + +/* + * Routine: setUpdateDates + * Purpose: determine the dates for fact table updates + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void setUpdateDates(DSDGenContext& dsdGenContext) { + assert(0); + int nDay, nUpdate, i; + date_t dtTemp; + + nUpdate = get_int("UPDATE", dsdGenContext); + while (nUpdate--) { + /* pick two adjacent days in the low density zone */ + dsdGenContext.arUpdateDates[0] = + getSkewedJulianDate(calendar_low, 0, dsdGenContext); + jtodt(&dtTemp, dsdGenContext.arUpdateDates[0]); + dist_weight( + &nDay, + "calendar", + day_number(&dtTemp) + 1, + calendar_low, + dsdGenContext); + if (nDay) + dsdGenContext.arUpdateDates[1] = dsdGenContext.arUpdateDates[0] + 1; + else + dsdGenContext.arUpdateDates[1] = dsdGenContext.arUpdateDates[0] - 1; + + /* + * pick the related Thursdays for inventory + * 1. shift first date to the Thursday in the current update week + * 2. move forward/back to get into correct comparability zone + * 3. set next date to next/prior Thursday based on comparability zone + */ + jtodt(&dtTemp, dsdGenContext.arUpdateDates[0] + (4 - set_dow(&dtTemp))); + dist_weight( + &nDay, "calendar", day_number(&dtTemp), calendar_low, dsdGenContext); + dsdGenContext.arInventoryUpdateDates[0] = dtTemp.julian; + if (!nDay) { + jtodt(&dtTemp, dtTemp.julian - 7); + dsdGenContext.arInventoryUpdateDates[0] = dtTemp.julian; + dist_weight( + &nDay, "calendar", day_number(&dtTemp), calendar_low, dsdGenContext); + if (!nDay) + dsdGenContext.arInventoryUpdateDates[0] += 14; + } + + dsdGenContext.arInventoryUpdateDates[1] = + dsdGenContext.arInventoryUpdateDates[0] + 7; + jtodt(&dtTemp, dsdGenContext.arInventoryUpdateDates[1]); + dist_weight( + &nDay, + "calendar", + day_number(&dtTemp) + 1, + calendar_low, + dsdGenContext); + if (!nDay) + dsdGenContext.arInventoryUpdateDates[1] -= 14; + + /* repeat for medium calendar zone */ + dsdGenContext.arUpdateDates[2] = + getSkewedJulianDate(calendar_medium, 0, dsdGenContext); + jtodt(&dtTemp, dsdGenContext.arUpdateDates[2]); + dist_weight( + &nDay, + "calendar", + day_number(&dtTemp) + 1, + calendar_medium, + dsdGenContext); + if (nDay) + dsdGenContext.arUpdateDates[3] = dsdGenContext.arUpdateDates[2] + 1; + else + dsdGenContext.arUpdateDates[3] = dsdGenContext.arUpdateDates[2] - 1; + + jtodt(&dtTemp, dsdGenContext.arUpdateDates[2] + (4 - set_dow(&dtTemp))); + dist_weight( + &nDay, "calendar", day_number(&dtTemp), calendar_medium, dsdGenContext); + dsdGenContext.arInventoryUpdateDates[2] = dtTemp.julian; + if (!nDay) { + jtodt(&dtTemp, dtTemp.julian - 7); + dsdGenContext.arInventoryUpdateDates[2] = dtTemp.julian; + dist_weight( + &nDay, + "calendar", + day_number(&dtTemp), + calendar_medium, + dsdGenContext); + if (!nDay) + dsdGenContext.arInventoryUpdateDates[2] += 14; + } + + dsdGenContext.arInventoryUpdateDates[3] = + dsdGenContext.arInventoryUpdateDates[2] + 7; + jtodt(&dtTemp, dsdGenContext.arInventoryUpdateDates[3]); + dist_weight( + &nDay, "calendar", day_number(&dtTemp), calendar_medium, dsdGenContext); + if (!nDay) + dsdGenContext.arInventoryUpdateDates[3] -= 14; + + /* repeat for high calendar zone */ + dsdGenContext.arUpdateDates[4] = + getSkewedJulianDate(calendar_high, 0, dsdGenContext); + jtodt(&dtTemp, dsdGenContext.arUpdateDates[4]); + dist_weight( + &nDay, + "calendar", + day_number(&dtTemp) + 1, + calendar_high, + dsdGenContext); + if (nDay) + dsdGenContext.arUpdateDates[5] = dsdGenContext.arUpdateDates[4] + 1; + else + dsdGenContext.arUpdateDates[5] = dsdGenContext.arUpdateDates[4] - 1; + + jtodt(&dtTemp, dsdGenContext.arUpdateDates[4] + (4 - set_dow(&dtTemp))); + dist_weight( + &nDay, "calendar", day_number(&dtTemp), calendar_high, dsdGenContext); + dsdGenContext.arInventoryUpdateDates[4] = dtTemp.julian; + if (!nDay) { + jtodt(&dtTemp, dtTemp.julian - 7); + dsdGenContext.arInventoryUpdateDates[4] = dtTemp.julian; + dist_weight( + &nDay, "calendar", day_number(&dtTemp), calendar_high, dsdGenContext); + if (!nDay) + dsdGenContext.arInventoryUpdateDates[4] += 14; + } + + dsdGenContext.arInventoryUpdateDates[5] = + dsdGenContext.arInventoryUpdateDates[4] + 7; + jtodt(&dtTemp, dsdGenContext.arInventoryUpdateDates[5]); + dist_weight( + &nDay, "calendar", day_number(&dtTemp), calendar_high, dsdGenContext); + if (!nDay) + dsdGenContext.arInventoryUpdateDates[5] -= 14; + } + + // /* + // * output the update dates for this update set + // */ + // openDeleteFile(1); + // for (i = 0; i < 6; i += 2) + // print_delete(&arUpdateDates[i]); + // + // /* + // * inventory uses separate dates + // */ + // openDeleteFile(2); + // for (i = 0; i < 6; i += 2) + // print_delete(&arInventoryUpdateDates[i]); + // openDeleteFile(0); + + return; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int getUpdateDate( + int nTable, + ds_key_t kRowcount, + DSDGenContext& dsdGenContext) { + static int nIndex = 0, nLastTable = -1; + + if (nLastTable != nTable) { + nLastTable = nTable; + get_rowcount(nTable, dsdGenContext); + nIndex = 0; + } + + for (nIndex = 0; + kRowcount > dsdGenContext.arRowcount[nTable].kDayRowcount[nIndex]; + nIndex++) + if (nIndex == 5) + break; + + if (nTable == S_INVENTORY) { + return (dsdGenContext.arInventoryUpdateDates[nIndex]); + } else + return (dsdGenContext.arUpdateDates[nIndex]); +} + +/* + * Routine: getUpdateID(int nTable, ds_key_t *pDest) + * Purpose: select the primary key for an update set row + * Algorithm: + * Data Structures: + * + * Params: + * Returns: 1 if the row is new, 0 if it is reusing an existing ID + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: 20040326 jms getUpdateID() this MUST be updated for 64bit -- all usages + * use casts today + * TODO: 20060102 jms this will need to be looked at for parallelism at + * some point + */ +/* +int +getUpdateID(ds_key_t *pDest, int nTable, int nColumn) +{ + int bIsUpdate = 0, + nTemp; + + if (genrand_integer(NULL, DIST_UNIFORM, 0, 99, 0, nColumn, dsdGenContext) < +arRowcount[nTable].nUpdatePercentage) + { + bIsUpdate = 1; + genrand_integer(&nTemp, DIST_UNIFORM, 1, (int, +dsdGenContext)getIDCount(nTable), 0, nColumn); *pDest = (ds_key_t)nTemp; + } + else + { + *pDest = ++arRowcount[nTable].kNextInsertValue; + } + + return(bIsUpdate); +} +*/ + +/* + * Routine: getSkewedJulianDate(int nWeight, int nColumn, DSDGenContext& + * dsdGenContext) Purpose: return a julian date based on the given skew and + * column Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int getSkewedJulianDate( + int nWeight, + int nColumn, + DSDGenContext& dsdGenContext) { + int i; + date_t Date; + + pick_distribution(&i, "calendar", 1, nWeight, nColumn, dsdGenContext); + genrand_integer( + &Date.year, + DIST_UNIFORM, + YEAR_MINIMUM, + YEAR_MAXIMUM, + 0, + nColumn, + dsdGenContext); + dist_member(&Date.day, "calendar", i, 3, dsdGenContext); + dist_member(&Date.month, "calendar", i, 5, dsdGenContext); + return (dttoj(&Date)); +} + +/* + * Routine: dateScaling(int nTable, ds_key_t jDate) + * Purpose: determine the number of rows to build for a given date and fact + * table Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t dateScaling(int nTable, ds_key_t jDate, DSDGenContext& dsdGenContext) { + dist_t* pDist; + const d_idx_t* pDistIndex; + date_t Date; + int nDateWeight = 1, nCalendarTotal, nDayWeight; + ds_key_t kRowCount = -1; + tdef* pTdef = getSimpleTdefsByNumber(nTable, dsdGenContext); + pDistIndex = find_dist("calendar"); + pDist = pDistIndex->dist; + if (!pDist) + ReportError(QERR_NO_MEMORY, "dateScaling()", 1); + + jtodt(&Date, static_cast(jDate)); + + switch (nTable) { + case STORE_SALES: + case CATALOG_SALES: + case WEB_SALES: + kRowCount = get_rowcount(nTable, dsdGenContext); + nDateWeight = calendar_sales; + break; + case S_CATALOG_ORDER: + kRowCount = get_rowcount(CATALOG_SALES, dsdGenContext); + nDateWeight = calendar_sales; + break; + case S_PURCHASE: + kRowCount = get_rowcount(STORE_SALES, dsdGenContext); + nDateWeight = calendar_sales; + break; + case S_WEB_ORDER: + kRowCount = get_rowcount(WEB_SALES, dsdGenContext); + nDateWeight = calendar_sales; + break; + case S_INVENTORY: + case INVENTORY: + nDateWeight = calendar_uniform; + kRowCount = get_rowcount(WAREHOUSE, dsdGenContext) * + getIDCount(ITEM, dsdGenContext); + break; + default: + ReportErrorNoLine(QERR_TABLE_NOP, pTdef->name, 1); + break; + } + + if (nTable != + INVENTORY) /* inventory rowcount is uniform thorughout the year */ + { + if (is_leap(Date.year)) + nDateWeight += 1; + + nCalendarTotal = dist_max(pDist, nDateWeight, dsdGenContext); + nCalendarTotal *= 5; /* assumes date range is 5 years */ + + dist_weight( + &nDayWeight, "calendar", day_number(&Date), nDateWeight, dsdGenContext); + kRowCount *= nDayWeight; + kRowCount += nCalendarTotal / 2; + kRowCount /= nCalendarTotal; + } + + return (kRowCount); +} + +/* + * Routine: getUpdateBase(int nTable) + * Purpose: return the offset to the first order in this update set for a given + * table Algorithm: Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t getUpdateBase(int nTable, DSDGenContext& dsdGenContext) { + return (dsdGenContext.arRowcount[nTable - S_BRAND].kNextInsertValue); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void setUpdateScaling(int nTable, DSDGenContext& dsdGenContext) { + tdef* pTdef; + int i, nBaseTable; + ds_key_t kNewRowcount = 0; + + pTdef = getSimpleTdefsByNumber(nTable, dsdGenContext); + if (!(pTdef->flags & FL_SOURCE_DDL) || !(pTdef->flags & FL_DATE_BASED) || + (pTdef->flags & FL_NOP)) + return; + + switch (nTable) { + case S_PURCHASE: + nBaseTable = STORE_SALES; + break; + case S_CATALOG_ORDER: + nBaseTable = CATALOG_SALES; + break; + case S_WEB_ORDER: + nBaseTable = WEB_SALES; + break; + case S_INVENTORY: + nBaseTable = INVENTORY; + break; + default: { + auto result = + fprintf(stderr, "ERROR: Invalid table in setUpdateScaling\n"); + if (result < 0) + perror("sprintf failed"); + exit(1); + break; + } + } + + dsdGenContext.arRowcount[nTable].kNextInsertValue = + dsdGenContext.arRowcount[nTable].kBaseRowcount; + + for (i = 0; i < 6; i++) { + kNewRowcount += + dateScaling(nBaseTable, dsdGenContext.arUpdateDates[i], dsdGenContext); + dsdGenContext.arRowcount[nTable].kDayRowcount[i] = kNewRowcount; + } + + dsdGenContext.arRowcount[nTable].kBaseRowcount = kNewRowcount; + dsdGenContext.arRowcount[nTable].kNextInsertValue += + kNewRowcount * (get_int("update", dsdGenContext) - 1); + + return; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/scd.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/scd.cpp new file mode 100644 index 0000000000000..5a1e88e8269fc --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/scd.cpp @@ -0,0 +1,382 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "scd.h" +#include +#include "build_support.h" +#include "config.h" +#include "constants.h" +#include "dist.h" +#include "genrand.h" +#include "parallel.h" +#include "params.h" +#include "permute.h" +#include "porting.h" +#include "scaling.h" +#include "tables.h" +#include "tdef_functions.h" +#include "tdefs.h" + +/* an array of the most recent business key for each table */ +char arBKeys[MAX_TABLE][17]; + +/* + * Routine: setSCDKey + * Purpose: handle the versioning and date stamps for slowly changing dimensions + * Algorithm: + * Data Structures: + * + * Params: 1 if there is a new id; 0 otherwise + * Returns: + * Called By: + * Calls: + * Assumptions: Table indexs (surrogate keys) are 1-based. This assures that the + *arBKeys[] entry for each table is initialized. Otherwise, parallel generation + *would be more difficult. Side Effects: + * TODO: None + */ +int setSCDKeys( + int nColumnID, + ds_key_t kIndex, + char* szBKey, + ds_key_t* pkBeginDateKey, + ds_key_t* pkEndDateKey, + DSDGenContext& dsdGenContext) { + int bNewBKey = 0, nModulo; + ds_key_t jMinimumDataDate, jMaximumDataDate, jH1DataDate, jT1DataDate, + jT2DataDate; + date_t dtTemp; + int nTableID; + + strtodt(&dtTemp, DATA_START_DATE); + jMinimumDataDate = dtTemp.julian; + strtodt(&dtTemp, DATA_END_DATE); + jMaximumDataDate = dtTemp.julian; + jH1DataDate = jMinimumDataDate + (jMaximumDataDate - jMinimumDataDate) / 2; + jT2DataDate = (jMaximumDataDate - jMinimumDataDate) / 3; + jT1DataDate = jMinimumDataDate + jT2DataDate; + jT2DataDate += jT1DataDate; + + nTableID = getTableFromColumn(nColumnID, dsdGenContext); + nModulo = (int)(kIndex % 6); + switch (nModulo) { + case 1: /* 1 revision */ + mk_bkey(arBKeys[nTableID], kIndex, nColumnID); + bNewBKey = 1; + *pkBeginDateKey = jMinimumDataDate - nTableID * 6; + *pkEndDateKey = -1; + break; + case 2: /* 1 of 2 revisions */ + mk_bkey(arBKeys[nTableID], kIndex, nColumnID); + bNewBKey = 1; + *pkBeginDateKey = jMinimumDataDate - nTableID * 6; + *pkEndDateKey = jH1DataDate - nTableID * 6; + break; + case 3: /* 2 of 2 revisions */ + mk_bkey(arBKeys[nTableID], kIndex - 1, nColumnID); + *pkBeginDateKey = jH1DataDate - nTableID * 6 + 1; + *pkEndDateKey = -1; + break; + case 4: /* 1 of 3 revisions */ + mk_bkey(arBKeys[nTableID], kIndex, nColumnID); + bNewBKey = 1; + *pkBeginDateKey = jMinimumDataDate - nTableID * 6; + *pkEndDateKey = jT1DataDate - nTableID * 6; + break; + case 5: /* 2 of 3 revisions */ + mk_bkey(arBKeys[nTableID], kIndex - 1, nColumnID); + *pkBeginDateKey = jT1DataDate - nTableID * 6 + 1; + *pkEndDateKey = jT2DataDate - nTableID * 6; + break; + case 0: /* 3 of 3 revisions */ + mk_bkey(arBKeys[nTableID], kIndex - 2, nColumnID); + *pkBeginDateKey = jT2DataDate - nTableID * 6 + 1; + *pkEndDateKey = -1; + break; + } + + /* can't have a revision in the future, per bug 114 */ + if (*pkEndDateKey > jMaximumDataDate) + *pkEndDateKey = -1; + + strcpy(szBKey, arBKeys[nTableID]); + + return (bNewBKey); +} + +/* + * Routine: scd_join(int tbl, int col, ds_key_t jDate) + * Purpose: create joins to slowly changing dimensions + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t +scd_join(int tbl, int col, ds_key_t jDate, DSDGenContext& dsdGenContext) { + ds_key_t res, kRowcount; + static int jMinimumDataDate, jMaximumDataDate, jH1DataDate, jT1DataDate, + jT2DataDate; + date_t dtTemp; + + if (!dsdGenContext.scd_join_init) { + strtodt(&dtTemp, DATA_START_DATE); + jMinimumDataDate = dtTemp.julian; + strtodt(&dtTemp, DATA_END_DATE); + jMaximumDataDate = dtTemp.julian; + jH1DataDate = jMinimumDataDate + (jMaximumDataDate - jMinimumDataDate) / 2; + jT2DataDate = (jMaximumDataDate - jMinimumDataDate) / 3; + jT1DataDate = jMinimumDataDate + jT2DataDate; + jT2DataDate += jT1DataDate; + dsdGenContext.scd_join_init = 1; + } + + kRowcount = getIDCount(tbl, dsdGenContext); + genrand_key( + &res, + DIST_UNIFORM, + 1, + kRowcount, + 0, + col, + dsdGenContext); /* pick the id */ + res = matchSCDSK( + res, + jDate, + tbl, + dsdGenContext); /* map to the date-sensitive surrogate key */ + + /* can't have a revision in the future, per bug 114 */ + if (jDate > jMaximumDataDate) + res = -1; + + return ((res > get_rowcount(tbl, dsdGenContext)) ? -1 : res); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t matchSCDSK( + ds_key_t kUnique, + ds_key_t jDate, + int nTable, + DSDGenContext& dsdGenContext) { + ds_key_t kReturn = -1; + int jMinimumDataDate, jMaximumDataDate; + int jH1DataDate, jT1DataDate, jT2DataDate; + date_t dtTemp; + + strtodt(&dtTemp, DATA_START_DATE); + jMinimumDataDate = dtTemp.julian; + strtodt(&dtTemp, DATA_END_DATE); + jMaximumDataDate = dtTemp.julian; + jH1DataDate = jMinimumDataDate + (jMaximumDataDate - jMinimumDataDate) / 2; + jT2DataDate = (jMaximumDataDate - jMinimumDataDate) / 3; + jT1DataDate = jMinimumDataDate + jT2DataDate; + jT2DataDate += jT1DataDate; + + switch (kUnique % 3) /* number of revisions for the ID */ + { + case 1: /* only one occurrence of this ID */ + kReturn = (kUnique / 3) * 6; + kReturn += 1; + break; + case 2: /* two revisions of this ID */ + kReturn = (kUnique / 3) * 6; + kReturn += 2; + if (jDate > jH1DataDate) + kReturn += 1; + break; + case 0: /* three revisions of this ID */ + kReturn = (kUnique / 3) * 6; + kReturn += -2; + if (jDate > jT1DataDate) + kReturn += 1; + if (jDate > jT2DataDate) + kReturn += 1; + break; + } + + if (kReturn > get_rowcount(nTable, dsdGenContext)) + kReturn = get_rowcount(nTable, dsdGenContext); + + return (kReturn); +} + +/* + * Routine: + * Purpose: map from a unique ID to a random SK + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t getSKFromID(ds_key_t kID, int nColumn, DSDGenContext& dsdGenContext) { + ds_key_t kTemp = -1; + + switch (kID % 3) { + case 1: /* single revision */ + kTemp = kID / 3; + kTemp *= 6; + kTemp += 1; + break; + case 2: /* two revisions */ + kTemp = kID / 3; + kTemp *= 6; + kTemp += + genrand_integer(NULL, DIST_UNIFORM, 2, 3, 0, nColumn, dsdGenContext); + break; + case 0: /* three revisions */ + kTemp = kID / 3; + kTemp -= 1; + kTemp *= 6; + kTemp += + genrand_integer(NULL, DIST_UNIFORM, 4, 6, 0, nColumn, dsdGenContext); + break; + } + + return (kTemp); +} + +/* + * Routine: getFirstSK + * Purpose: map from id to an SK that can be mapped back to an id by printID() + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t getFirstSK(ds_key_t kID) { + ds_key_t kTemp = -1; + + switch (kID % 3) { + case 1: /* single revision */ + kTemp = kID / 3; + kTemp *= 6; + kTemp += 1; + break; + case 2: /* two revisions */ + kTemp = kID / 3; + kTemp *= 6; + kTemp += 2; + break; + case 0: /* three revisions */ + kTemp = kID / 3; + kTemp -= 1; + kTemp *= 6; + kTemp += 4; + break; + } + + return (kTemp); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +void changeSCD( + int nDataType, + void* pNewData, + void* pOldData, + int* nFlags, + int bFirst) { + /** + * if nFlags is odd, then this value will be retained + */ + if ((*nFlags != ((*nFlags / 2) * 2)) && (bFirst == 0)) { + /* + * the method to retain the old value depends on the data type + */ + switch (nDataType) { + case SCD_INT: + *static_cast(pNewData) = *static_cast(pOldData); + break; + case SCD_PTR: + pNewData = pOldData; + break; + case SCD_KEY: + *static_cast(pNewData) = *static_cast(pOldData); + break; + case SCD_CHAR: + strcpy(static_cast(pNewData), static_cast(pOldData)); + break; + case SCD_DEC: + if (pNewData && pOldData) + memcpy(pNewData, pOldData, sizeof(decimal_t)); + break; + } + } else { + /* + * the method to set the old value depends on the data type + */ + switch (nDataType) { + case SCD_INT: + *static_cast(pOldData) = *static_cast(pNewData); + break; + case SCD_PTR: + pOldData = pNewData; + break; + case SCD_KEY: + *static_cast(pOldData) = *static_cast(pNewData); + break; + case SCD_CHAR: + strcpy(static_cast(pOldData), static_cast(pNewData)); + break; + case SCD_DEC: + if (pOldData && pNewData) + memcpy(pOldData, pNewData, sizeof(decimal_t)); + break; + } + } + + *nFlags /= 2; + + return; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/skip_days.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/skip_days.cpp new file mode 100644 index 0000000000000..75a9414ae02d3 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/skip_days.cpp @@ -0,0 +1,49 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "skip_days.h" +#include "constants.h" +#include "date.h" +#include "dist.h" +#include "parallel.h" +#include "scaling.h" + +ds_key_t +skipDays(int nTable, ds_key_t* pRemainder, DSDGenContext& dsdGenContext) { + date_t BaseDate; + ds_key_t jDate; + ds_key_t kRowCount, kFirstRow, kDayCount, index = 1; + + if (!dsdGenContext.skipDays_init) { + *pRemainder = 0; + dsdGenContext.skipDays_init = 1; + } + strtodt(&BaseDate, DATA_START_DATE); + + // set initial conditions + jDate = BaseDate.julian; + *pRemainder = dateScaling(nTable, jDate, dsdGenContext) + index; + + // now check to see if we need to move to the + // the next piece of a parallel build + // move forward one day at a time + split_work(nTable, &kFirstRow, &kRowCount, dsdGenContext); + while (index < kFirstRow) { + kDayCount = dateScaling(nTable, jDate, dsdGenContext); + index += kDayCount; + jDate += 1; + *pRemainder = index; + } + if (index > kFirstRow) { + jDate -= 1; + } + return (jDate); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/sparse.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/sparse.cpp new file mode 100644 index 0000000000000..0175be4723409 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/sparse.cpp @@ -0,0 +1,97 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "sparse.h" +#include "config.h" +#include "error_msg.h" +#include "genrand.h" +#include "porting.h" +#include "scaling.h" +#include "tdefs.h" + +/* + * Routine: initSparseKeys() + * Purpose: set up the set of valid key values for a sparse table. + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: The total population will fit in 32b + * Side Effects: + * TODO: None + */ +int initSparseKeys(int nTable, DSDGenContext& dsdGenContext) { + ds_key_t kRowcount, kOldSeed; + int k; + tdef* pTdef; + + kRowcount = get_rowcount(nTable, dsdGenContext); + pTdef = getTdefsByNumber(nTable, dsdGenContext); + + pTdef->arSparseKeys = static_cast( + malloc(static_cast(kRowcount) * sizeof(ds_key_t))); + MALLOC_CHECK(pTdef->arSparseKeys); + if (pTdef->arSparseKeys == NULL) + ReportError(QERR_NO_MEMORY, "initSparseKeys()", 1); + memset( + pTdef->arSparseKeys, 0, static_cast(kRowcount) * sizeof(ds_key_t)); + + kOldSeed = setSeed(0, nTable, dsdGenContext); + for (k = 0; k < kRowcount; k++) + genrand_key( + &pTdef->arSparseKeys[k], + DIST_UNIFORM, + 1, + pTdef->nParam, + 0, + 0, + dsdGenContext); + setSeed(0, static_cast(kOldSeed), dsdGenContext); + + return (0); +} + +/* + * Routine: randomSparseKey() + * Purpose: randomly select one of the valid key values for a sparse table + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t +randomSparseKey(int nTable, int nColumn, DSDGenContext& dsdGenContext) { + int nKeyIndex; + ds_key_t kRowcount; + tdef* pTdef; + + pTdef = getTdefsByNumber(nTable, dsdGenContext); + kRowcount = get_rowcount(nTable, dsdGenContext); + genrand_integer( + &nKeyIndex, + DIST_UNIFORM, + 1, + static_cast(kRowcount), + 0, + nColumn, + dsdGenContext); + + return (pTdef->arSparseKeys[nKeyIndex]); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/tdef_functions.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/tdef_functions.cpp new file mode 100644 index 0000000000000..5d9026172a37a --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/tdef_functions.cpp @@ -0,0 +1,69 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "tdef_functions.h" +#include "dbgen_version.h" +#include "w_call_center.h" +#include "w_catalog_page.h" +#include "w_catalog_returns.h" +#include "w_catalog_sales.h" +#include "w_customer.h" +#include "w_customer_address.h" +#include "w_customer_demographics.h" +#include "w_datetbl.h" +#include "w_household_demographics.h" +#include "w_income_band.h" +#include "w_inventory.h" +#include "w_item.h" +#include "w_promotion.h" +#include "w_reason.h" +#include "w_ship_mode.h" +#include "w_store.h" +#include "w_store_returns.h" +#include "w_store_sales.h" +#include "w_timetbl.h" +#include "w_warehouse.h" +#include "w_web_page.h" +#include "w_web_returns.h" +#include "w_web_sales.h" +#include "w_web_site.h" + +table_func_t w_tdef_funcs[] = { + {"call_center", mk_w_call_center, {NULL, NULL}, NULL}, + {"catalog_page", mk_w_catalog_page, {NULL, NULL}, NULL}, + {"catalog_returns", NULL, {NULL, NULL}, NULL}, + {"catalog_sales", mk_w_catalog_sales, {NULL, NULL}, NULL}, + {"customer", mk_w_customer, {NULL, NULL}, NULL}, + {"customer_address", mk_w_customer_address, {NULL, NULL}, NULL}, + {"customer_demographics", mk_w_customer_demographics, {NULL, NULL}, NULL}, + {"date", mk_w_date, {NULL, NULL}, NULL}, + {"household_demographics", mk_w_household_demographics, {NULL, NULL}, NULL}, + {"income_band", mk_w_income_band, {NULL, NULL}, NULL}, + {"inventory", mk_w_inventory, {NULL, NULL}, NULL}, + {"item", mk_w_item, {NULL, NULL}, NULL}, + {"promotion", mk_w_promotion, {NULL, NULL}, NULL}, + {"reason", mk_w_reason, {NULL, NULL}, NULL}, + {"ship_mode", mk_w_ship_mode, {NULL, NULL}, NULL}, + {"store", mk_w_store, {NULL, NULL}, NULL}, + {"store_returns", mk_w_store_returns, {NULL, NULL}, NULL}, + {"store_sales", mk_w_store_sales, {NULL, NULL}, NULL}, + {"time", mk_w_time, {NULL, NULL}, NULL}, + {"warehouse", mk_w_warehouse, {NULL, NULL}, NULL}, + {"web_page", mk_w_web_page, {NULL, NULL}, NULL}, + {"web_returns", mk_w_web_returns, {NULL, NULL}, NULL}, + {"web_sales", mk_w_web_sales, {NULL, NULL}, NULL}, + {"web_site", mk_w_web_site, {NULL, NULL}, NULL}, + {"dbgen_version", mk_dbgen_version, {NULL, NULL}, NULL}, + {NULL}}; + +table_func_t* getTdefFunctionsByNumber(int nTable) { + return (&w_tdef_funcs[nTable]); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/tdefs.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/tdefs.cpp new file mode 100644 index 0000000000000..169637c1bc0e8 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/tdefs.cpp @@ -0,0 +1,185 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "tdefs.h" +#include +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "porting.h" +#include "r_params.h" +#include "scaling.h" +#include "tables.h" +#include "tdef_functions.h" + +/* + * Routine: get_rowcount(int table) + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t GetRowcountByName(char* szName, DSDGenContext& dsdGenContext) { + int nTable = -1; + + nTable = GetTableNumber(szName, dsdGenContext); + if (nTable >= 0) + return (get_rowcount(nTable - 1, dsdGenContext)); + + nTable = distsize(szName, dsdGenContext); + return (nTable); +} + +/* + * Routine: GetTableNumber(char *szName, DSDGenContext& dsdGenContext) + * Purpose: Return size of table, pseudo table or distribution + * Algorithm: Need to use rowcount distribution, since argument could be a + * pseudo table Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int GetTableNumber(char* szName, DSDGenContext& dsdGenContext) { + int i; + + for (i = 1; i <= distsize("rowcounts", dsdGenContext); i++) { + char* szTable = new char[100]; + dist_member(szTable, "rowcounts", i, 1, dsdGenContext); + if (strcasecmp(szTable, szName) == 0) + return (i - 1); + } + + return (-1); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +/* +tdef * +getTdefsByNumber(int nTable) +{ + if (is_set("UPDATE")) + { + if (s_tdefs[nTable].flags & FL_PASSTHRU) + { + switch(nTable + S_BRAND) + { + case S_CATALOG_PAGE: nTable = CATALOG_PAGE; break; + case S_CUSTOMER_ADDRESS: nTable = CUSTOMER_ADDRESS; break; + case S_PROMOTION: nTable = PROMOTION; break; + } + return(&w_tdefs[nTable]); + } + else + return(&s_tdefs[nTable]); + } + else + return(&w_tdefs[nTable]); +} +*/ +tdef* getSimpleTdefsByNumber(int nTable, DSDGenContext& dsdGenContext) { + if (nTable >= S_BRAND) + return (&dsdGenContext.s_tdefs[nTable - S_BRAND]); + return (&dsdGenContext.w_tdefs[nTable]); +} + +tdef* getTdefsByNumber(int nTable, DSDGenContext& dsdGenContext) { + if (is_set("UPDATE", dsdGenContext) && is_set("VALIDATE", dsdGenContext)) { + if (static_cast(dsdGenContext.s_tdefs[nTable].flags) & + FL_PASSTHRU) { + switch (nTable + S_BRAND) { + case S_CATALOG_PAGE: + nTable = CATALOG_PAGE; + break; + case S_CUSTOMER_ADDRESS: + nTable = CUSTOMER_ADDRESS; + break; + case S_PROMOTION: + nTable = PROMOTION; + break; + } + return (&dsdGenContext.w_tdefs[nTable]); + } else + return (&dsdGenContext.s_tdefs[nTable]); + } + + return (getSimpleTdefsByNumber(nTable, dsdGenContext)); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +const char* getTableNameByID(int i, DSDGenContext& dsdGenContext) { + tdef* pT = getSimpleTdefsByNumber(i, dsdGenContext); + + return (pT->name); +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int getTableFromColumn(int nColumn, DSDGenContext& dsdGenContext) { + int i; + tdef* pT; + + for (i = 0; i <= MAX_TABLE; i++) { + pT = getSimpleTdefsByNumber(i, dsdGenContext); + if ((nColumn >= pT->nFirstColumn) && (nColumn <= pT->nLastColumn)) + return (i); + } + return (-1); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/text.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/text.cpp new file mode 100644 index 0000000000000..0305f83b25c35 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/text.cpp @@ -0,0 +1,185 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include +#include +#include +#include "config.h" +#include "date.h" +#include "decimal.h" +#include "dist.h" +#include "genrand.h" +#include "porting.h" + +/* + * Routine: mk_sentence() + * Purpose: create a sample sentence + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +#define SPACE_INCREMENT 100 + +char* mk_sentence(int stream, DSDGenContext& dsdGenContext) { + char* verbiage = nullptr; + int used_space = 0; /* current length of the sentence being built */ + int allocated_space = 0; + int word_len = 0; + char *syntax = nullptr, *cp = nullptr, *word = nullptr, temp[2]; + + temp[1] = '\0'; + pick_distribution(&syntax, "sentences", 1, 1, stream, dsdGenContext); + + for (cp = syntax; *cp; cp++) { + switch (*cp) { + case 'N': /* pick a noun */ + pick_distribution(&word, "nouns", 1, 1, stream, dsdGenContext); + break; + case 'V': /* pick a verb */ + pick_distribution(&word, "verbs", 1, 1, stream, dsdGenContext); + break; + case 'J': /* pick a adjective */ + pick_distribution(&word, "adjectives", 1, 1, stream, dsdGenContext); + break; + case 'D': /* pick a adverb */ + pick_distribution(&word, "adverbs", 1, 1, stream, dsdGenContext); + break; + case 'X': /* pick a auxiliary verb */ + pick_distribution(&word, "auxiliaries", 1, 1, stream, dsdGenContext); + break; + case 'P': /* pick a preposition */ + pick_distribution(&word, "prepositions", 1, 1, stream, dsdGenContext); + break; + case 'A': /* pick an article */ + pick_distribution(&word, "articles", 1, 1, stream, dsdGenContext); + break; + case 'T': /* pick an terminator */ + pick_distribution(&word, "terminators", 1, 1, stream, dsdGenContext); + break; + default: + temp[0] = *cp; + break; + } + + if (word == nullptr) + word_len = 1; + else + word_len = strlen(word); + + if (used_space + word_len >= allocated_space) { + verbiage = static_cast( + realloc(verbiage, allocated_space + SPACE_INCREMENT)); + MALLOC_CHECK(verbiage); + allocated_space += SPACE_INCREMENT; + } + + if (word == nullptr) + strcpy(&verbiage[used_space], temp); + else + strcpy(&verbiage[used_space], word); + used_space += word_len; + word = nullptr; + } + + return (verbiage); +} + +/* + * Routine: gen_text() + * Purpose: entry point for this module. Generate a truncated sentence in a + * given length range + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +char* gen_text( + char* dest, + int min, + int max, + int stream, + DSDGenContext& dsdGenContext) { + int target_len = 0, generated_length = 0, capitalize = 1; + char* s = nullptr; + + genrand_integer( + &target_len, DIST_UNIFORM, min, max, 0, stream, dsdGenContext); + if (dest) + *dest = '\0'; + else { + dest = static_cast(malloc((max + 1) * sizeof(char))); + MALLOC_CHECK(dest); + } + + while (target_len > 0) { + s = mk_sentence(stream, dsdGenContext); + if (capitalize) + *s = toupper(*s); + generated_length = strlen(s); + capitalize = (s[generated_length - 1] == '.'); + if (target_len <= generated_length) + s[target_len] = '\0'; + strcat(dest, s); + target_len -= generated_length; + if (target_len > 0) { + strcat(dest, " "); + target_len -= 1; + } + } + + return (dest); +} + +#ifdef TEST +#define DECLARER +#include "r_driver.h" +#include "r_params.h" + +typedef struct { + char* name; +} tdef; +/* tdef tdefs[] = {NULL}; */ + +option_t options[] = { + + {"DISTRIBUTIONS", OPT_STR, 0, NULL, NULL, "tester_dist.idx"}, + NULL}; + +char* params[2]; + +main() { + char test_dest[201]; + int i; + + init_params(); + + for (i = 0; i < 100; i++) { + gen_text(test_dest, 100, 200, 1); + printf("%s\n", test_dest); + test_dest[0] = '\0'; + } + + return (0); +} +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_call_center.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_call_center.cpp new file mode 100644 index 0000000000000..564a1dae9614f --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_call_center.cpp @@ -0,0 +1,347 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_call_center.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "date.h" +#include "decimal.h" +#include "dist.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "parallel.h" +#include "porting.h" +#include "r_params.h" +#include "scaling.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" + +#include +#include +#include + +static struct CALL_CENTER_TBL g_call_center_OldValues; + +/* + * Routine: mk_w_call_center() + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20020830 jms Need to populate open and close dates + */ + +int mk_w_call_center( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int32_t jDateStart, nDaysPerRevision; + int32_t nSuffix, bFirstRecord = 0, nFieldChangeFlags, jDateEnd, nDateRange; + char *cp = nullptr, *sName1 = nullptr, *sName2 = nullptr; + decimal_t dMinTaxPercentage, dMaxTaxPercentage; + tdef* pTdef = getSimpleTdefsByNumber(CALL_CENTER, dsdGenContext); + + /* begin locals declarations */ + date_t dTemp; + double nScale; + struct CALL_CENTER_TBL *r, *rOldValues = &g_call_center_OldValues; + + r = &dsdGenContext.g_w_call_center; + + strtodt(&dTemp, DATA_START_DATE); + jDateStart = dttoj(&dTemp) - WEB_SITE; + strtodt(&dTemp, DATA_END_DATE); + jDateEnd = dttoj(&dTemp); + nDateRange = jDateEnd - jDateStart + 1; + nDaysPerRevision = nDateRange / pTdef->nParam + 1; + nScale = get_dbl("SCALE", dsdGenContext); + + r->cc_division_id = -1; + r->cc_closed_date_id = -1; + strcpy(r->cc_division_name, "No Name"); + + strtodec(&dMinTaxPercentage, MIN_CC_TAX_PERCENTAGE); + strtodec(&dMaxTaxPercentage, MAX_CC_TAX_PERCENTAGE); + + nullSet(&pTdef->kNullBitMap, CC_NULLS, dsdGenContext); + r->cc_call_center_sk = index; + + /* if we have generated the required history for this business key and + * generate a new one then reset associate fields (e.g., rec_start_date + * minimums) + */ + if (setSCDKeys( + CC_CALL_CENTER_ID, + index, + r->cc_call_center_id, + &r->cc_rec_start_date_id, + &r->cc_rec_end_date_id, + dsdGenContext)) { + r->cc_open_date_id = + jDateStart - + genrand_integer( + NULL, DIST_UNIFORM, -365, 0, 0, CC_OPEN_DATE_ID, dsdGenContext); + + /* + * some fields are not changed, even when a new version of the row is + * written + */ + nSuffix = static_cast(index / distsize("call_centers", dsdGenContext)); + dist_member( + &cp, + "call_centers", + static_cast((index % distsize("call_centers", dsdGenContext)) + 1), + 1, + dsdGenContext); + if (nSuffix > 0) { + snprintf(r->cc_name, RS_CC_NAME + 1, "%s_%d", cp, nSuffix); + } else + strcpy(r->cc_name, cp); + + mk_address(&r->cc_address, CC_ADDRESS, dsdGenContext); + bFirstRecord = 1; + } + + /* + * this is where we select the random number that controls if a field + * changes from one record to the next. + */ + nFieldChangeFlags = next_random(CC_SCD, dsdGenContext); + + /* the rest of the record in a history-keeping dimension can either be a new + * data value or not; use a random number and its bit pattern to determine + * which fields to replace and which to retain + */ + pick_distribution( + &r->cc_class, "call_center_class", 1, 1, CC_CLASS, dsdGenContext); + changeSCD( + SCD_PTR, + &r->cc_class, + &rOldValues->cc_class, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->cc_employees, + DIST_UNIFORM, + 1, + nScale >= 1 ? static_cast(CC_EMPLOYEE_MAX * nScale * nScale) + : static_cast(CC_EMPLOYEE_MAX), + 0, + CC_EMPLOYEES, + dsdGenContext); + changeSCD( + SCD_INT, + &r->cc_employees, + &rOldValues->cc_employees, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->cc_sq_ft, DIST_UNIFORM, 100, 700, 0, CC_SQ_FT, dsdGenContext); + r->cc_sq_ft *= r->cc_employees; + changeSCD( + SCD_INT, + &r->cc_sq_ft, + &rOldValues->cc_sq_ft, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution( + &r->cc_hours, "call_center_hours", 1, 1, CC_HOURS, dsdGenContext); + changeSCD( + SCD_PTR, + &r->cc_hours, + &rOldValues->cc_hours, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution(&sName1, "first_names", 1, 1, CC_MANAGER, dsdGenContext); + pick_distribution(&sName2, "last_names", 1, 1, CC_MANAGER, dsdGenContext); + snprintf(&r->cc_manager[0], RS_CC_MANAGER + 1, "%s %s", sName1, sName2); + changeSCD( + SCD_CHAR, + &r->cc_manager, + &rOldValues->cc_manager, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->cc_market_id, DIST_UNIFORM, 1, 6, 0, CC_MARKET_ID, dsdGenContext); + changeSCD( + SCD_INT, + &r->cc_market_id, + &rOldValues->cc_market_id, + &nFieldChangeFlags, + bFirstRecord); + + gen_text( + r->cc_market_class, + 20, + RS_CC_MARKET_CLASS, + CC_MARKET_CLASS, + dsdGenContext); + changeSCD( + SCD_CHAR, + &r->cc_market_class, + &rOldValues->cc_market_class, + &nFieldChangeFlags, + bFirstRecord); + + gen_text( + r->cc_market_desc, 20, RS_CC_MARKET_DESC, CC_MARKET_DESC, dsdGenContext); + changeSCD( + SCD_CHAR, + &r->cc_market_desc, + &rOldValues->cc_market_desc, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution( + &sName1, "first_names", 1, 1, CC_MARKET_MANAGER, dsdGenContext); + pick_distribution( + &sName2, "last_names", 1, 1, CC_MARKET_MANAGER, dsdGenContext); + snprintf( + &r->cc_market_manager[0], + RS_CC_MARKET_MANAGER + 1, + "%s %s", + sName1, + sName2); + changeSCD( + SCD_CHAR, + &r->cc_market_manager, + &rOldValues->cc_market_manager, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->cc_company, DIST_UNIFORM, 1, 6, 0, CC_COMPANY, dsdGenContext); + changeSCD( + SCD_INT, + &r->cc_company, + &rOldValues->cc_company, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->cc_division_id, DIST_UNIFORM, 1, 6, 0, CC_COMPANY, dsdGenContext); + changeSCD( + SCD_INT, + &r->cc_division_id, + &rOldValues->cc_division_id, + &nFieldChangeFlags, + bFirstRecord); + + mk_word( + r->cc_division_name, + "syllables", + r->cc_division_id, + RS_CC_DIVISION_NAME, + CC_DIVISION_NAME, + dsdGenContext); + changeSCD( + SCD_CHAR, + &r->cc_division_name, + &rOldValues->cc_division_name, + &nFieldChangeFlags, + bFirstRecord); + + mk_companyname( + r->cc_company_name, CC_COMPANY_NAME, r->cc_company, dsdGenContext); + changeSCD( + SCD_CHAR, + &r->cc_company_name, + &rOldValues->cc_company_name, + &nFieldChangeFlags, + bFirstRecord); + + genrand_decimal( + &r->cc_tax_percentage, + DIST_UNIFORM, + &dMinTaxPercentage, + &dMaxTaxPercentage, + NULL, + CC_TAX_PERCENTAGE, + dsdGenContext); + changeSCD( + SCD_DEC, + &r->cc_tax_percentage, + &rOldValues->cc_tax_percentage, + &nFieldChangeFlags, + bFirstRecord); + + // append the newly created row + char szTemp[128]; + + void* info = append_info_get(info_arr, CALL_CENTER); + + append_row_start(info); + append_key(CC_CALL_CENTER_SK, info, r->cc_call_center_sk); + append_varchar(CC_CALL_CENTER_ID, info, r->cc_call_center_id); + append_date(CC_REC_START_DATE_ID, info, r->cc_rec_start_date_id); + append_date(CC_REC_END_DATE_ID, info, r->cc_rec_end_date_id); + append_integer(CC_CLOSED_DATE_ID, info, r->cc_closed_date_id); + append_integer(CC_OPEN_DATE_ID, info, r->cc_open_date_id); + append_varchar(CC_NAME, info, r->cc_name); + append_varchar(CC_CLASS, info, &r->cc_class[0]); + append_integer(CC_EMPLOYEES, info, r->cc_employees); + append_integer(CC_SQ_FT, info, r->cc_sq_ft); + append_varchar(CC_HOURS, info, r->cc_hours); + append_varchar(CC_MANAGER, info, &r->cc_manager[0]); + append_integer(CC_MARKET_ID, info, r->cc_market_id); + append_varchar(CC_MARKET_CLASS, info, &r->cc_market_class[0]); + append_varchar(CC_MARKET_DESC, info, &r->cc_market_desc[0]); + append_varchar(CC_MARKET_MANAGER, info, &r->cc_market_manager[0]); + append_integer(CC_DIVISION, info, r->cc_division_id); + append_varchar(CC_DIVISION_NAME, info, &r->cc_division_name[0]); + append_integer(CC_COMPANY, info, r->cc_company); + append_varchar(CC_COMPANY_NAME, info, &r->cc_company_name[0]); + append_varchar(CC_ADDRESS, info, std::to_string(r->cc_address.street_num)); + + if (r->cc_address.street_name2) { + snprintf( + szTemp, + sizeof(szTemp), + "%s %s", + r->cc_address.street_name1, + r->cc_address.street_name2); + append_varchar(CC_ADDRESS, info, szTemp); + } else { + append_varchar(CC_ADDRESS, info, r->cc_address.street_name1); + } + + append_varchar(CC_ADDRESS, info, r->cc_address.street_type); + append_varchar(CC_ADDRESS, info, &r->cc_address.suite_num[0]); + append_varchar(CC_ADDRESS, info, r->cc_address.city); + append_varchar(CC_ADDRESS, info, r->cc_address.county); + append_varchar(CC_ADDRESS, info, r->cc_address.state); + snprintf(szTemp, sizeof(szTemp), "%05d", r->cc_address.zip); + append_varchar(CC_ADDRESS, info, szTemp); + append_varchar(CC_ADDRESS, info, &r->cc_address.country[0]); + append_integer_decimal(CC_GMT_OFFSET, info, r->cc_address.gmt_offset); + append_decimal(CC_TAX_PERCENTAGE, info, &r->cc_tax_percentage); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_page.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_page.cpp new file mode 100644 index 0000000000000..2063e8b453d90 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_page.cpp @@ -0,0 +1,124 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_catalog_page.h" + +#include "append_info.h" +#include "build_support.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "porting.h" +#include "scaling.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * Routine: mk_catalog_page() + * Purpose: populate the catalog_page table + * Algorithm: + * catalogs are issued either monthly, quarterly or bi-annually (cp_type) + * there is 1 of each type circulating at all times + * Data tdefsures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20020903 jms cp_department needs to be randomized + * 20020903 jms cp_description needs to be randomized + */ +int mk_w_catalog_page( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + date_t* dStartDate; + int nCatalogPageMax; + int nDuration, nOffset, nType; + struct CATALOG_PAGE_TBL* r; + int nCatalogInterval; + tdef* pTdef = getSimpleTdefsByNumber(CATALOG_PAGE, dsdGenContext); + + r = &dsdGenContext.g_w_catalog_page; + + nCatalogPageMax = + (static_cast( + get_rowcount(CATALOG_PAGE, dsdGenContext) / CP_CATALOGS_PER_YEAR)) / + (YEAR_MAXIMUM - YEAR_MINIMUM + 2); + dStartDate = strtodate(DATA_START_DATE); + strcpy(r->cp_department, "DEPARTMENT"); + + nullSet(&pTdef->kNullBitMap, CP_NULLS, dsdGenContext); + r->cp_catalog_page_sk = index; + mk_bkey(&r->cp_catalog_page_id[0], index, CP_CATALOG_PAGE_ID); + r->cp_catalog_number = static_cast((index - 1) / nCatalogPageMax + 1); + r->cp_catalog_page_number = + static_cast((index - 1) % nCatalogPageMax + 1); + switch (nCatalogInterval = + ((r->cp_catalog_number - 1) % CP_CATALOGS_PER_YEAR)) { + case 0: /* bi-annual */ + case 1: + nType = 1; + nDuration = 182; + nOffset = nCatalogInterval * nDuration; + break; + case 2: + case 3: /* Q2 */ + case 4: /* Q3 */ + case 5: /* Q4 */ + nDuration = 91; + nOffset = (nCatalogInterval - 2) * nDuration; + nType = 2; + break; + default: + nDuration = 30; + nOffset = (nCatalogInterval - 6) * nDuration; + nType = 3; /* monthly */ + } + r->cp_start_date_id = dStartDate->julian + nOffset; + r->cp_start_date_id += + ((r->cp_catalog_number - 1) / CP_CATALOGS_PER_YEAR) * 365; + r->cp_end_date_id = r->cp_start_date_id + nDuration - 1; + dist_member(&r->cp_type, "catalog_page_type", nType, 1, dsdGenContext); + gen_text( + &r->cp_description[0], + RS_CP_DESCRIPTION / 2, + RS_CP_DESCRIPTION - 1, + CP_DESCRIPTION, + dsdGenContext); + + void* info = append_info_get(info_arr, CATALOG_PAGE); + + append_row_start(info); + + append_key(CP_CATALOG_PAGE_SK, info, r->cp_catalog_page_sk); + append_varchar(CP_CATALOG_PAGE_ID, info, r->cp_catalog_page_id); + append_integer(CP_START_DATE_ID, info, r->cp_start_date_id); + append_integer(CP_END_DATE_ID, info, r->cp_end_date_id); + append_varchar(CP_DEPARTMENT, info, &r->cp_department[0]); + append_integer(CP_CATALOG_NUMBER, info, r->cp_catalog_number); + append_integer(CP_CATALOG_PAGE_NUMBER, info, r->cp_catalog_page_number); + append_varchar(CP_DESCRIPTION, info, &r->cp_description[0]); + append_varchar(CP_TYPE, info, r->cp_type); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_returns.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_returns.cpp new file mode 100644 index 0000000000000..ac785dc89e92d --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_returns.cpp @@ -0,0 +1,144 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_catalog_returns.h" +#include +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "genrand.h" +#include "nulls.h" +#include "parallel.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" +#include "w_catalog_sales.h" + +/* + * Routine: mk_catalog_returns() + * Purpose: populate a return fact *sync'd with a sales fact* + * Algorithm: Since the returns need to be in line with a prior sale, they need + * to use the output of the mk_catalog_sales() routine, and then add + *return-related information Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20020902 jms Need to link call center to date/time of return + * 20031023 jms removed ability for stand alone generation + */ +int mk_w_catalog_returns( + void* row, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int res = 0; + + decimal_t dHundred; + int nTemp; + struct W_CATALOG_RETURNS_TBL* r; + struct W_CATALOG_SALES_TBL* sale = &dsdGenContext.g_w_catalog_sales; + static int bStandAlone = 0; + tdef* pTdef = getSimpleTdefsByNumber(CATALOG_RETURNS, dsdGenContext); + + if (row == NULL) + r = &dsdGenContext.g_w_catalog_returns; + else + r = static_cast(row); + strtodec(&dHundred, "100.00"); + + /* if we were not called from the parent table's mk_xxx routine, then + * move to a parent row that needs to be returned, and generate it + */ + nullSet(&pTdef->kNullBitMap, CR_NULLS, dsdGenContext); + if (bStandAlone) { + genrand_integer( + &nTemp, DIST_UNIFORM, 0, 99, 0, CR_IS_RETURNED, dsdGenContext); + if (nTemp >= CR_RETURN_PCT) { + row_skip(CATALOG_SALES, 1, dsdGenContext); + return (1); + } + mk_w_catalog_sales(&dsdGenContext.g_w_catalog_sales, index, dsdGenContext); + } + + /* + * Some of the information in the return is taken from the original sale + * which has been regenerated + */ + r->cr_item_sk = sale->cs_sold_item_sk; + r->cr_catalog_page_sk = sale->cs_catalog_page_sk; + r->cr_order_number = sale->cs_order_number; + memcpy(&r->cr_pricing, &sale->cs_pricing, sizeof(ds_pricing_t)); + r->cr_refunded_customer_sk = sale->cs_bill_customer_sk; + r->cr_refunded_cdemo_sk = sale->cs_bill_cdemo_sk; + r->cr_refunded_hdemo_sk = sale->cs_bill_hdemo_sk; + r->cr_refunded_addr_sk = sale->cs_bill_addr_sk; + r->cr_call_center_sk = sale->cs_call_center_sk; + + /* + * some of the fields are conditionally taken from the sale + */ + r->cr_returning_customer_sk = + mk_join(CR_RETURNING_CUSTOMER_SK, CUSTOMER, 2, dsdGenContext); + r->cr_returning_cdemo_sk = + mk_join(CR_RETURNING_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 2, dsdGenContext); + r->cr_returning_hdemo_sk = + mk_join(CR_RETURNING_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 2, dsdGenContext); + r->cr_returning_addr_sk = + mk_join(CR_RETURNING_ADDR_SK, CUSTOMER_ADDRESS, 2, dsdGenContext); + if (genrand_integer( + NULL, + DIST_UNIFORM, + 0, + 99, + 0, + CR_RETURNING_CUSTOMER_SK, + dsdGenContext) < CS_GIFT_PCT) { + r->cr_returning_customer_sk = sale->cs_ship_customer_sk; + r->cr_returning_cdemo_sk = sale->cs_ship_cdemo_sk; + /* cr_returning_hdemo_sk removed, since it doesn't exist on the sales + * record */ + r->cr_returning_addr_sk = sale->cs_ship_addr_sk; + } + + /** + * the rest of the columns are generated for this specific return + */ + /* the items cannot be returned until they are shipped; offset is handled in + * mk_join, based on sales date */ + r->cr_returned_date_sk = + mk_join(CR_RETURNED_DATE_SK, DATET, sale->cs_ship_date_sk, dsdGenContext); + + /* the call center determines the time of the return */ + r->cr_returned_time_sk = mk_join(CR_RETURNED_TIME_SK, TIME, 1, dsdGenContext); + + r->cr_ship_mode_sk = mk_join(CR_SHIP_MODE_SK, SHIP_MODE, 1, dsdGenContext); + r->cr_warehouse_sk = mk_join(CR_WAREHOUSE_SK, WAREHOUSE, 1, dsdGenContext); + r->cr_reason_sk = mk_join(CR_REASON_SK, REASON, 1, dsdGenContext); + if (sale->cs_pricing.quantity != -1) + genrand_integer( + &r->cr_pricing.quantity, + DIST_UNIFORM, + 1, + sale->cs_pricing.quantity, + 0, + CR_PRICING, + dsdGenContext); + else + r->cr_pricing.quantity = -1; + set_pricing(CR_PRICING, &r->cr_pricing, dsdGenContext); + + return (res); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_sales.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_sales.cpp new file mode 100644 index 0000000000000..2a0bbd75f0965 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_catalog_sales.cpp @@ -0,0 +1,376 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_catalog_sales.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "genrand.h" +#include "nulls.h" +#include "parallel.h" +#include "params.h" +#include "permute.h" +#include "porting.h" +#include "scaling.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" +#include "w_catalog_returns.h" + +#include + +ds_key_t +skipDays(int nTable, ds_key_t* pRemainder, DSDGenContext& dsdGenContext); + +/* + * the validation process requires generating a single lineitem + * so the main mk_xxx routine has been split into a master record portion + * and a detail/lineitem portion. + */ +W_CATALOG_SALES_TBL* mk_catalog_sales_master( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + decimal_t dZero, dHundred, dOne, dOneHalf; + int nGiftPct; + struct W_CATALOG_SALES_TBL* r; + r = &dsdGenContext.g_w_catalog_sales; + + if (!dsdGenContext.mk_master_catalog_sales_init) { + dsdGenContext.jDate = + skipDays(CATALOG_SALES, &dsdGenContext.kNewDateIndex, dsdGenContext); + dsdGenContext.pCatalogSalesItemPermutation = makePermutation( + NULL, + (dsdGenContext.nCatalogSalesItemCount = + static_cast(getIDCount(ITEM, dsdGenContext))), + CS_PERMUTE, + dsdGenContext); + + dsdGenContext.mk_master_catalog_sales_init = 1; + } + + strtodec(&dZero, "0.00"); + strtodec(&dHundred, "100.00"); + strtodec(&dOne, "1.00"); + strtodec(&dOneHalf, "0.50"); + + while (index > dsdGenContext.kNewDateIndex) /* need to move to a new date */ + { + dsdGenContext.jDate += 1; + dsdGenContext.kNewDateIndex += + dateScaling(CATALOG_SALES, dsdGenContext.jDate, dsdGenContext); + } + + /*** + * some attributes remain the same for each lineitem in an order; others are + * different for each lineitem. + * + * Parallel generation causes another problem, since the values that get + * seeded may come from a prior row. If we are seeding at the start of a + * parallel chunk, hunt backwards in the RNG stream to find the most recent + * values that were used to set the values of the orderline-invariant + * columns + */ + + r->cs_sold_date_sk = dsdGenContext.jDate; + r->cs_sold_time_sk = + mk_join(CS_SOLD_TIME_SK, TIME, r->cs_call_center_sk, dsdGenContext); + r->cs_call_center_sk = (r->cs_sold_date_sk == -1) + ? -1 + : mk_join( + CS_CALL_CENTER_SK, CALL_CENTER, r->cs_sold_date_sk, dsdGenContext); + + r->cs_bill_customer_sk = + mk_join(CS_BILL_CUSTOMER_SK, CUSTOMER, 1, dsdGenContext); + r->cs_bill_cdemo_sk = + mk_join(CS_BILL_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 1, dsdGenContext); + r->cs_bill_hdemo_sk = + mk_join(CS_BILL_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 1, dsdGenContext); + r->cs_bill_addr_sk = + mk_join(CS_BILL_ADDR_SK, CUSTOMER_ADDRESS, 1, dsdGenContext); + + /* most orders are for the ordering customers, some are not */ + genrand_integer( + &nGiftPct, DIST_UNIFORM, 0, 99, 0, CS_SHIP_CUSTOMER_SK, dsdGenContext); + if (nGiftPct <= CS_GIFT_PCT) { + r->cs_ship_customer_sk = + mk_join(CS_SHIP_CUSTOMER_SK, CUSTOMER, 2, dsdGenContext); + r->cs_ship_cdemo_sk = + mk_join(CS_SHIP_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 2, dsdGenContext); + r->cs_ship_hdemo_sk = + mk_join(CS_SHIP_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 2, dsdGenContext); + r->cs_ship_addr_sk = + mk_join(CS_SHIP_ADDR_SK, CUSTOMER_ADDRESS, 2, dsdGenContext); + } else { + r->cs_ship_customer_sk = r->cs_bill_customer_sk; + r->cs_ship_cdemo_sk = r->cs_bill_cdemo_sk; + r->cs_ship_hdemo_sk = r->cs_bill_hdemo_sk; + r->cs_ship_addr_sk = r->cs_bill_addr_sk; + } + + r->cs_order_number = index; + genrand_integer( + &dsdGenContext.nTicketItemBase, + DIST_UNIFORM, + 1, + dsdGenContext.nCatalogSalesItemCount, + 0, + CS_SOLD_ITEM_SK, + dsdGenContext); + + return r; +} + +static void mk_detail( + void* info_arr, + int bPrint, + struct W_CATALOG_SALES_TBL* r, + DSDGenContext& dsdGenContext) { + int nShipLag, nTemp; + ds_key_t kItem; + tdef* pTdef = getSimpleTdefsByNumber(CATALOG_SALES, dsdGenContext); + + r = &dsdGenContext.g_w_catalog_sales; + + nullSet(&pTdef->kNullBitMap, CS_NULLS, dsdGenContext); + + /* orders are shipped some number of days after they are ordered */ + genrand_integer( + &nShipLag, + DIST_UNIFORM, + CS_MIN_SHIP_DELAY, + CS_MAX_SHIP_DELAY, + 0, + CS_SHIP_DATE_SK, + dsdGenContext); + r->cs_ship_date_sk = + (r->cs_sold_date_sk == -1) ? -1 : r->cs_sold_date_sk + nShipLag; + + /* + * items need to be unique within an order + * use a sequence within the permutation + * NB: Permutations are 1-based + */ + if (++dsdGenContext.nTicketItemBase > dsdGenContext.nCatalogSalesItemCount) + dsdGenContext.nTicketItemBase = 1; + kItem = getPermutationEntry( + dsdGenContext.pCatalogSalesItemPermutation, + dsdGenContext.nTicketItemBase); + r->cs_sold_item_sk = + matchSCDSK(kItem, r->cs_sold_date_sk, ITEM, dsdGenContext); + + /* catalog page needs to be from a catlog active at the time of the sale */ + r->cs_catalog_page_sk = (r->cs_sold_date_sk == -1) ? -1 + : mk_join( + CS_CATALOG_PAGE_SK, + CATALOG_PAGE, + r->cs_sold_date_sk, + dsdGenContext); + + r->cs_ship_mode_sk = mk_join(CS_SHIP_MODE_SK, SHIP_MODE, 1, dsdGenContext); + r->cs_warehouse_sk = mk_join(CS_WAREHOUSE_SK, WAREHOUSE, 1, dsdGenContext); + r->cs_promo_sk = mk_join(CS_PROMO_SK, PROMOTION, 1, dsdGenContext); + set_pricing(CS_PRICING, &r->cs_pricing, dsdGenContext); + + /** + * having gone to the trouble to make the sale, now let's see if it gets + * returned + */ + genrand_integer( + &nTemp, DIST_UNIFORM, 0, 99, 0, CR_IS_RETURNED, dsdGenContext); + if (nTemp < CR_RETURN_PCT) { + struct W_CATALOG_RETURNS_TBL w_catalog_returns; + struct W_CATALOG_RETURNS_TBL* rr = &dsdGenContext.g_w_catalog_returns; + mk_w_catalog_returns(rr, 1, dsdGenContext); + + void* info = append_info_get(info_arr, CATALOG_RETURNS); + append_row_start(info); + + append_key(CR_RETURNED_DATE_SK, info, rr->cr_returned_date_sk); + append_key(CR_RETURNED_TIME_SK, info, rr->cr_returned_time_sk); + append_key(CR_ITEM_SK, info, rr->cr_item_sk); + append_key(CR_REFUNDED_CUSTOMER_SK, info, rr->cr_refunded_customer_sk); + append_key(CR_REFUNDED_CDEMO_SK, info, rr->cr_refunded_cdemo_sk); + append_key(CR_REFUNDED_HDEMO_SK, info, rr->cr_refunded_hdemo_sk); + append_key(CR_REFUNDED_ADDR_SK, info, rr->cr_refunded_addr_sk); + append_key(CR_RETURNING_CUSTOMER_SK, info, rr->cr_returning_customer_sk); + append_key(CR_RETURNING_CDEMO_SK, info, rr->cr_returning_cdemo_sk); + append_key(CR_RETURNING_HDEMO_SK, info, rr->cr_returning_hdemo_sk); + append_key(CR_RETURNING_ADDR_SK, info, rr->cr_returning_addr_sk); + append_key(CR_CALL_CENTER_SK, info, rr->cr_call_center_sk); + append_key(CR_CATALOG_PAGE_SK, info, rr->cr_catalog_page_sk); + append_key(CR_SHIP_MODE_SK, info, rr->cr_ship_mode_sk); + append_key(CR_WAREHOUSE_SK, info, rr->cr_warehouse_sk); + append_key(CR_REASON_SK, info, rr->cr_reason_sk); + append_key(CR_ORDER_NUMBER, info, rr->cr_order_number); + append_integer(CR_PRICING_QUANTITY, info, rr->cr_pricing.quantity); + append_decimal(CR_PRICING_NET_PAID, info, &rr->cr_pricing.net_paid); + append_decimal(CR_PRICING_EXT_TAX, info, &rr->cr_pricing.ext_tax); + append_decimal( + CR_PRICING_NET_PAID_INC_TAX, info, &rr->cr_pricing.net_paid_inc_tax); + append_decimal(CR_PRICING_FEE, info, &rr->cr_pricing.fee); + append_decimal( + CR_PRICING_EXT_SHIP_COST, info, &rr->cr_pricing.ext_ship_cost); + append_decimal( + CR_PRICING_REFUNDED_CASH, info, &rr->cr_pricing.refunded_cash); + append_decimal( + CR_PRICING_REVERSED_CHARGE, info, &rr->cr_pricing.reversed_charge); + append_decimal(CR_PRICING_STORE_CREDIT, info, &rr->cr_pricing.store_credit); + append_decimal(CR_PRICING_NET_LOSS, info, &rr->cr_pricing.net_loss); + + append_row_end(info); + } + + void* info = append_info_get(info_arr, CATALOG_SALES); + append_row_start(info); + + append_key(CS_SOLD_DATE_SK, info, r->cs_sold_date_sk); + append_key(CS_SOLD_TIME_SK, info, r->cs_sold_time_sk); + append_key(CS_SHIP_DATE_SK, info, r->cs_ship_date_sk); + append_key(CS_BILL_CUSTOMER_SK, info, r->cs_bill_customer_sk); + append_key(CS_BILL_CDEMO_SK, info, r->cs_bill_cdemo_sk); + append_key(CS_BILL_HDEMO_SK, info, r->cs_bill_hdemo_sk); + append_key(CS_BILL_ADDR_SK, info, r->cs_bill_addr_sk); + append_key(CS_SHIP_CUSTOMER_SK, info, r->cs_ship_customer_sk); + append_key(CS_SHIP_CDEMO_SK, info, r->cs_ship_cdemo_sk); + append_key(CS_SHIP_HDEMO_SK, info, r->cs_ship_hdemo_sk); + append_key(CS_SHIP_ADDR_SK, info, r->cs_ship_addr_sk); + append_key(CS_CALL_CENTER_SK, info, r->cs_call_center_sk); + append_key(CS_CATALOG_PAGE_SK, info, r->cs_catalog_page_sk); + append_key(CS_SHIP_MODE_SK, info, r->cs_ship_mode_sk); + append_key(CS_WAREHOUSE_SK, info, r->cs_warehouse_sk); + append_key(CS_SOLD_ITEM_SK, info, r->cs_sold_item_sk); + append_key(CS_PROMO_SK, info, r->cs_promo_sk); + append_key(CS_ORDER_NUMBER, info, r->cs_order_number); + append_integer(CS_PRICING_QUANTITY, info, r->cs_pricing.quantity); + append_decimal( + CS_PRICING_WHOLESALE_COST, info, &r->cs_pricing.wholesale_cost); + append_decimal(CS_PRICING_LIST_PRICE, info, &r->cs_pricing.list_price); + append_decimal(CS_PRICING_SALES_PRICE, info, &r->cs_pricing.sales_price); + append_decimal( + CS_PRICING_EXT_DISCOUNT_AMOUNT, info, &r->cs_pricing.ext_discount_amt); + append_decimal( + CS_PRICING_EXT_SALES_PRICE, info, &r->cs_pricing.ext_sales_price); + append_decimal( + CS_PRICING_EXT_WHOLESALE_COST, info, &r->cs_pricing.ext_wholesale_cost); + append_decimal( + CS_PRICING_EXT_LIST_PRICE, info, &r->cs_pricing.ext_list_price); + append_decimal(CS_PRICING_EXT_TAX, info, &r->cs_pricing.ext_tax); + append_decimal(CS_PRICING_COUPON_AMT, info, &r->cs_pricing.coupon_amt); + append_decimal(CS_PRICING_EXT_SHIP_COST, info, &r->cs_pricing.ext_ship_cost); + append_decimal(CS_PRICING_NET_PAID, info, &r->cs_pricing.net_paid); + append_decimal( + CS_PRICING_NET_PAID_INC_TAX, info, &r->cs_pricing.net_paid_inc_tax); + append_decimal( + CS_PRICING_NET_PAID_INC_SHIP, info, &r->cs_pricing.net_paid_inc_ship); + append_decimal( + CS_PRICING_NET_PAID_INC_SHIP_TAX, + info, + &r->cs_pricing.net_paid_inc_ship_tax); + append_decimal(CS_PRICING_NET_PROFIT, info, &r->cs_pricing.net_profit); + + append_row_end(info); + + return; +} + +/* + * Routine: mk_catalog_sales() + * Purpose: build rows for the catalog sales table + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20020902 jms Need to link order date/time to call center record + * 20020902 jms Should promos be tied to item id? + */ +int mk_w_catalog_sales( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int nLineitems, i; + + row_skip(CATALOG_RETURNS, (index - 1), dsdGenContext); + struct W_CATALOG_SALES_TBL* r; + r = mk_catalog_sales_master(info_arr, index, dsdGenContext); + + /* + * now we select the number of lineitems in this order, and loop through + * them, printing as we go + */ + genrand_integer( + &nLineitems, DIST_UNIFORM, 4, 14, 0, CS_ORDER_NUMBER, dsdGenContext); + for (i = 1; i <= nLineitems; i++) { + mk_detail(info_arr, 1, r, dsdGenContext); + } + + /** + * and finally return 1 since we have already printed the rows. + */ + return 0; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int vld_w_catalog_sales( + int nTable, + ds_key_t kRow, + int* Permutation, + DSDGenContext& dsdGenContext) { + int nLineitem, nMaxLineitem, i; + + row_skip(nTable, kRow - 1, dsdGenContext); + row_skip(CATALOG_RETURNS, (kRow - 1), dsdGenContext); + dsdGenContext.jDate = + skipDays(CATALOG_SALES, &dsdGenContext.kNewDateIndex, dsdGenContext); + + struct W_CATALOG_SALES_TBL* r; + r = mk_catalog_sales_master(NULL, kRow, dsdGenContext); + genrand_integer( + &nMaxLineitem, DIST_UNIFORM, 4, 14, 9, CS_ORDER_NUMBER, dsdGenContext); + genrand_integer( + &nLineitem, + DIST_UNIFORM, + 1, + nMaxLineitem, + 0, + CS_PRICING_QUANTITY, + dsdGenContext); + for (i = 1; i < nLineitem; i++) { + mk_detail(NULL, 0, r, dsdGenContext); + } + mk_detail(NULL, 1, r, dsdGenContext); + + return (0); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer.cpp new file mode 100644 index 0000000000000..b9cd8682d7106 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer.cpp @@ -0,0 +1,164 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_customer.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "genrand.h" +#include "nulls.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include +#include "parallel.h" +/* extern tdef w_tdefs[]; */ + +/* + * Routine: mk_customer + * Purpose: populate the customer dimension + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +int mk_w_customer( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int nTemp; + + int nBaseDate; + /* begin locals declarations */ + int nNameIndex, nGender; + struct W_CUSTOMER_TBL* r; + date_t dtTemp; + date_t dtBirthMin, dtBirthMax, dtToday, dt1YearAgo, dt10YearsAgo; + tdef* pT = getSimpleTdefsByNumber(CUSTOMER, dsdGenContext); + r = &dsdGenContext.g_w_customer; + + date_t min_date; + strtodt(&min_date, DATE_MINIMUM); + nBaseDate = dttoj(&min_date); + + strtodt(&dtBirthMax, "1992-12-31"); + strtodt(&dtBirthMin, "1924-01-01"); + strtodt(&dtToday, TODAYS_DATE); + jtodt(&dt1YearAgo, dtToday.julian - 365); + jtodt(&dt10YearsAgo, dtToday.julian - 3650); + + nullSet(&pT->kNullBitMap, C_NULLS, dsdGenContext); + r->c_customer_sk = index; + mk_bkey(&r->c_customer_id[0], index, C_CUSTOMER_ID); + genrand_integer( + &nTemp, DIST_UNIFORM, 1, 100, 0, C_PREFERRED_CUST_FLAG, dsdGenContext); + r->c_preferred_cust_flag = (nTemp < C_PREFERRED_PCT) ? 1 : 0; + + /* demographic keys are a composite of values. rebuild them a la + * bitmap_to_dist */ + r->c_current_hdemo_sk = + mk_join(C_CURRENT_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 1, dsdGenContext); + + r->c_current_cdemo_sk = + mk_join(C_CURRENT_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 1, dsdGenContext); + + r->c_current_addr_sk = mk_join( + C_CURRENT_ADDR_SK, CUSTOMER_ADDRESS, r->c_customer_sk, dsdGenContext); + nNameIndex = pick_distribution( + &r->c_first_name, "first_names", 1, 3, C_FIRST_NAME, dsdGenContext); + pick_distribution( + &r->c_last_name, "last_names", 1, 1, C_LAST_NAME, dsdGenContext); + dist_weight(&nGender, "first_names", nNameIndex, 2, dsdGenContext); + pick_distribution( + &r->c_salutation, + "salutations", + 1, + (nGender == 0) ? 2 : 3, + C_SALUTATION, + dsdGenContext); + + genrand_date( + &dtTemp, + DIST_UNIFORM, + &dtBirthMin, + &dtBirthMax, + NULL, + C_BIRTH_DAY, + dsdGenContext); + r->c_birth_day = dtTemp.day; + r->c_birth_month = dtTemp.month; + r->c_birth_year = dtTemp.year; + genrand_email( + r->c_email_address, + r->c_first_name, + r->c_last_name, + C_EMAIL_ADDRESS, + dsdGenContext); + genrand_date( + &dtTemp, + DIST_UNIFORM, + &dt1YearAgo, + &dtToday, + NULL, + C_LAST_REVIEW_DATE, + dsdGenContext); + r->c_last_review_date = dtTemp.julian; + genrand_date( + &dtTemp, + DIST_UNIFORM, + &dt10YearsAgo, + &dtToday, + NULL, + C_FIRST_SALES_DATE_ID, + dsdGenContext); + r->c_first_sales_date_id = dtTemp.julian; + r->c_first_shipto_date_id = r->c_first_sales_date_id + 30; + + pick_distribution( + &r->c_birth_country, "countries", 1, 1, C_BIRTH_COUNTRY, dsdGenContext); + + void* info = append_info_get(info_arr, CUSTOMER); + append_row_start(info); + + append_key(C_CUSTOMER_SK, info, r->c_customer_sk); + append_varchar(C_CUSTOMER_ID, info, r->c_customer_id); + append_key(C_CURRENT_CDEMO_SK, info, r->c_current_cdemo_sk); + append_key(C_CURRENT_HDEMO_SK, info, r->c_current_hdemo_sk); + append_key(C_CURRENT_ADDR_SK, info, r->c_current_addr_sk); + append_key(C_FIRST_SHIPTO_DATE_ID, info, r->c_first_shipto_date_id); + append_key(C_FIRST_SALES_DATE_ID, info, r->c_first_sales_date_id); + append_varchar(C_SALUTATION, info, r->c_salutation); + append_varchar(C_FIRST_NAME, info, r->c_first_name); + append_varchar(C_LAST_NAME, info, r->c_last_name); + append_varchar( + C_PREFERRED_CUST_FLAG, info, r->c_preferred_cust_flag ? "Y" : "N"); + append_integer(C_BIRTH_DAY, info, r->c_birth_day); + append_integer(C_BIRTH_MONTH, info, r->c_birth_month); + append_integer(C_BIRTH_YEAR, info, r->c_birth_year); + append_varchar(C_BIRTH_COUNTRY, info, r->c_birth_country); + append_varchar(C_LOGIN, info, &r->c_login[0]); + append_varchar(C_EMAIL_ADDRESS, info, &r->c_email_address[0]); + append_key(C_LAST_REVIEW_DATE, info, r->c_last_review_date); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer_address.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer_address.cpp new file mode 100644 index 0000000000000..67fa7375d9eb1 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer_address.cpp @@ -0,0 +1,86 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_customer_address.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "date.h" +#include "decimal.h" +#include "genrand.h" +#include "nulls.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * mk_customer_address + */ +int mk_w_customer_address( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + /* begin locals declarations */ + struct W_CUSTOMER_ADDRESS_TBL* r; + tdef* pTdef = getSimpleTdefsByNumber(CUSTOMER_ADDRESS, dsdGenContext); + + r = &dsdGenContext.g_w_customer_address; + + nullSet(&pTdef->kNullBitMap, CA_NULLS, dsdGenContext); + r->ca_addr_sk = index; + mk_bkey(&r->ca_addr_id[0], index, CA_ADDRESS_ID); + pick_distribution( + &r->ca_location_type, + "location_type", + 1, + 1, + CA_LOCATION_TYPE, + dsdGenContext); + mk_address(&r->ca_address, CA_ADDRESS, dsdGenContext); + + void* info = append_info_get(info_arr, CUSTOMER_ADDRESS); + append_row_start(info); + + char szTemp[128]; + + append_key(CA_ADDRESS_SK, info, r->ca_addr_sk); + append_varchar(CA_ADDRESS_ID, info, r->ca_addr_id); + append_varchar( + CA_ADDRESS_STREET_NUM, info, std::to_string(r->ca_address.street_num)); + if (r->ca_address.street_name2) { + snprintf( + szTemp, + sizeof(szTemp), + "%s %s", + r->ca_address.street_name1, + r->ca_address.street_name2); + append_varchar(CA_ADDRESS_STREET_NAME1, info, szTemp); + } else + append_varchar(CA_ADDRESS_STREET_NAME1, info, r->ca_address.street_name1); + append_varchar(CA_ADDRESS_STREET_TYPE, info, r->ca_address.street_type); + append_varchar(CA_ADDRESS_SUITE_NUM, info, &r->ca_address.suite_num[0]); + append_varchar(CA_ADDRESS_CITY, info, r->ca_address.city); + append_varchar(CA_ADDRESS_COUNTY, info, r->ca_address.county); + append_varchar(CA_ADDRESS_STATE, info, r->ca_address.state); + snprintf(szTemp, sizeof(szTemp), "%05d", r->ca_address.zip); + append_varchar(CA_ADDRESS_ZIP, info, szTemp); + append_varchar(CA_ADDRESS_COUNTRY, info, &r->ca_address.country[0]); + append_integer_decimal(CA_ADDRESS_GMT_OFFSET, info, r->ca_address.gmt_offset); + append_varchar(CA_LOCATION_TYPE, info, r->ca_location_type); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer_demographics.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer_demographics.cpp new file mode 100644 index 0000000000000..4b064431925cc --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_customer_demographics.cpp @@ -0,0 +1,99 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_customer_demographics.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "genrand.h" +#include "nulls.h" +#include "porting.h" +#include "sparse.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * mk_customer_demographics + */ +int mk_w_customer_demographics( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + struct W_CUSTOMER_DEMOGRAPHICS_TBL* r; + ds_key_t kTemp; + tdef* pTdef = getSimpleTdefsByNumber(CUSTOMER_DEMOGRAPHICS, dsdGenContext); + + r = &dsdGenContext.g_w_customer_demographics; + + nullSet(&pTdef->kNullBitMap, CD_NULLS, dsdGenContext); + r->cd_demo_sk = index; + kTemp = r->cd_demo_sk - 1; + bitmap_to_dist( + &r->cd_gender, "gender", &kTemp, 1, CUSTOMER_DEMOGRAPHICS, dsdGenContext); + bitmap_to_dist( + &r->cd_marital_status, + "marital_status", + &kTemp, + 1, + CUSTOMER_DEMOGRAPHICS, + dsdGenContext); + bitmap_to_dist( + &r->cd_education_status, + "education", + &kTemp, + 1, + CUSTOMER_DEMOGRAPHICS, + dsdGenContext); + bitmap_to_dist( + &r->cd_purchase_estimate, + "purchase_band", + &kTemp, + 1, + CUSTOMER_DEMOGRAPHICS, + dsdGenContext); + bitmap_to_dist( + &r->cd_credit_rating, + "credit_rating", + &kTemp, + 1, + CUSTOMER_DEMOGRAPHICS, + dsdGenContext); + r->cd_dep_count = + static_cast((kTemp % static_cast(CD_MAX_CHILDREN))); + kTemp /= static_cast(CD_MAX_CHILDREN); + r->cd_dep_employed_count = + static_cast((kTemp % static_cast(CD_MAX_EMPLOYED))); + kTemp /= static_cast(CD_MAX_EMPLOYED); + r->cd_dep_college_count = + static_cast((kTemp % static_cast(CD_MAX_COLLEGE))); + + void* info = append_info_get(info_arr, CUSTOMER_DEMOGRAPHICS); + append_row_start(info); + + append_key(CD_DEMO_SK, info, r->cd_demo_sk); + append_varchar(CD_GENDER, info, r->cd_gender); + append_varchar(CD_MARITAL_STATUS, info, r->cd_marital_status); + append_varchar(CD_EDUCATION_STATUS, info, r->cd_education_status); + append_integer(CD_PURCHASE_ESTIMATE, info, r->cd_purchase_estimate); + append_varchar(CD_CREDIT_RATING, info, r->cd_credit_rating); + append_integer(CD_DEP_COUNT, info, r->cd_dep_count); + append_integer(CD_DEP_EMPLOYED_COUNT, info, r->cd_dep_employed_count); + append_integer(CD_DEP_COLLEGE_COUNT, info, r->cd_dep_college_count); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_datetbl.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_datetbl.cpp new file mode 100644 index 0000000000000..68817158b8d3d --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_datetbl.cpp @@ -0,0 +1,159 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_datetbl.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "nulls.h" +#include "parallel.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* extern tdef w_tdefs[]; */ + +/* + * Routine: mk_datetbl + * Purpose: populate the date dimension + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +int mk_w_date(void* info_arr, ds_key_t index, DSDGenContext& dsdGenContext) { + int res = 0; + + /* begin locals declarations */ + date_t base_date; + int day_index, nTemp; + date_t temp_date, dTemp2; + struct W_DATE_TBL* r; + tdef* pT = getSimpleTdefsByNumber(DATET, dsdGenContext); + + r = &dsdGenContext.g_w_date; + + if (!dsdGenContext.mk_w_date_init) { + r->d_month_seq = 0; + r->d_week_seq = 1; + r->d_quarter_seq = 1; + r->d_current_month = 0; + r->d_current_quarter = 0; + r->d_current_week = 0; + strtodt(&base_date, "1900-01-01"); + /* Make exceptions to the 1-rng-call-per-row rule */ + dsdGenContext.mk_w_date_init = 1; + } else { + strtodt(&base_date, "1900-01-01"); + } + + nullSet(&pT->kNullBitMap, D_NULLS, dsdGenContext); + nTemp = static_cast(index + base_date.julian); + r->d_date_sk = nTemp; + mk_bkey(&r->d_date_id[0], nTemp, D_DATE_ID); + jtodt(&temp_date, nTemp); + r->d_year = temp_date.year; + r->d_dow = set_dow(&temp_date); + r->d_moy = temp_date.month; + r->d_dom = temp_date.day; + /* set the sequence counts; assumes that the date table starts on a year + * boundary */ + r->d_week_seq = (static_cast(index + 6)) / 7; + r->d_month_seq = (r->d_year - 1900) * 12 + r->d_moy - 1; + r->d_quarter_seq = (r->d_year - 1900) * 4 + r->d_moy / 3 + 1; + day_index = day_number(&temp_date); + dist_member(&r->d_qoy, "calendar", day_index, 6, dsdGenContext); + /* fiscal year is identical to calendar year */ + r->d_fy_year = r->d_year; + r->d_fy_quarter_seq = r->d_quarter_seq; + r->d_fy_week_seq = r->d_week_seq; + r->d_day_name = weekday_names[r->d_dow + 1]; + dist_member(&r->d_holiday, "calendar", day_index, 8, dsdGenContext); + if ((r->d_dow == 5) || (r->d_dow == 6)) + r->d_weekend = 1; + else + r->d_weekend = 0; + if (day_index == 1) + dist_member( + &r->d_following_holiday, + "calendar", + 365 + is_leap(r->d_year - 1), + 8, + dsdGenContext); + else + dist_member( + &r->d_following_holiday, "calendar", day_index - 1, 8, dsdGenContext); + date_t_op(&dTemp2, OP_FIRST_DOM, &temp_date, 0); + r->d_first_dom = dTemp2.julian; + date_t_op(&dTemp2, OP_LAST_DOM, &temp_date, 0); + r->d_last_dom = dTemp2.julian; + date_t_op(&dTemp2, OP_SAME_LY, &temp_date, 0); + r->d_same_day_ly = dTemp2.julian; + date_t_op(&dTemp2, OP_SAME_LQ, &temp_date, 0); + r->d_same_day_lq = dTemp2.julian; + r->d_current_day = (r->d_date_sk == CURRENT_DAY) ? 1 : 0; + r->d_current_year = (r->d_year == CURRENT_YEAR) ? 1 : 0; + if (r->d_current_year) { + r->d_current_month = (r->d_moy == CURRENT_MONTH) ? 1 : 0; + r->d_current_quarter = (r->d_qoy == CURRENT_QUARTER) ? 1 : 0; + r->d_current_week = (r->d_week_seq == CURRENT_WEEK) ? 1 : 0; + } + + char sQuarterName[7]; + + void* info = append_info_get(info_arr, DATET); + append_row_start(info); + + append_key(D_DATE_SK, info, r->d_date_sk); + append_varchar(D_DATE_ID, info, r->d_date_id); + append_date(D_DATE_SK, info, r->d_date_sk); + append_integer(D_MONTH_SEQ, info, r->d_month_seq); + append_integer(D_WEEK_SEQ, info, r->d_week_seq); + append_integer(D_QUARTER_SEQ, info, r->d_quarter_seq); + append_integer(D_YEAR, info, r->d_year); + append_integer(D_DOW, info, r->d_dow); + append_integer(D_MOY, info, r->d_moy); + append_integer(D_DOM, info, r->d_dom); + append_integer(D_QOY, info, r->d_qoy); + append_integer(D_FY_YEAR, info, r->d_fy_year); + append_integer(D_FY_QUARTER_SEQ, info, r->d_fy_quarter_seq); + append_integer(D_FY_WEEK_SEQ, info, r->d_fy_week_seq); + append_varchar(D_DAY_NAME, info, r->d_day_name); + snprintf(sQuarterName, sizeof(sQuarterName), "%4dQ%d", r->d_year, r->d_qoy); + append_varchar(D_QUARTER_NAME, info, sQuarterName); + append_varchar(D_HOLIDAY, info, r->d_holiday ? "Y" : "N"); + append_varchar(D_WEEKEND, info, r->d_weekend ? "Y" : "N"); + append_varchar(D_FOLLOWING_HOLIDAY, info, r->d_following_holiday ? "Y" : "N"); + append_integer(D_FIRST_DOM, info, r->d_first_dom); + append_integer(D_LAST_DOM, info, r->d_last_dom); + append_integer(D_SAME_DAY_LY, info, r->d_same_day_ly); + append_integer(D_SAME_DAY_LQ, info, r->d_same_day_lq); + append_varchar(D_CURRENT_DAY, info, r->d_current_day ? "Y" : "N"); + append_varchar(D_CURRENT_WEEK, info, r->d_current_week ? "Y" : "N"); + append_varchar(D_CURRENT_MONTH, info, r->d_current_month ? "Y" : "N"); + append_varchar(D_CURRENT_QUARTER, info, r->d_current_quarter ? "Y" : "N"); + append_varchar(D_CURRENT_YEAR, info, r->d_current_year ? "Y" : "N"); + + append_row_end(info); + + return (res); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_household_demographics.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_household_demographics.cpp new file mode 100644 index 0000000000000..6d3d0a2350bc4 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_household_demographics.cpp @@ -0,0 +1,78 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_household_demographics.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "nulls.h" +#include "porting.h" +#include "sparse.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * mk_household_demographics + */ +int mk_w_household_demographics( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + /* begin locals declarations */ + ds_key_t nTemp; + struct W_HOUSEHOLD_DEMOGRAPHICS_TBL* r; + tdef* pTdef = getSimpleTdefsByNumber(HOUSEHOLD_DEMOGRAPHICS, dsdGenContext); + + r = &dsdGenContext.g_w_household_demographics; + + nullSet(&pTdef->kNullBitMap, HD_NULLS, dsdGenContext); + r->hd_demo_sk = index; + nTemp = r->hd_demo_sk; + r->hd_income_band_id = (nTemp % distsize("income_band", dsdGenContext)) + 1; + nTemp /= distsize("income_band", dsdGenContext); + bitmap_to_dist( + &r->hd_buy_potential, + "buy_potential", + &nTemp, + 1, + HOUSEHOLD_DEMOGRAPHICS, + dsdGenContext); + bitmap_to_dist( + &r->hd_dep_count, + "dependent_count", + &nTemp, + 1, + HOUSEHOLD_DEMOGRAPHICS, + dsdGenContext); + bitmap_to_dist( + &r->hd_vehicle_count, + "vehicle_count", + &nTemp, + 1, + HOUSEHOLD_DEMOGRAPHICS, + dsdGenContext); + + void* info = append_info_get(info_arr, HOUSEHOLD_DEMOGRAPHICS); + append_row_start(info); + append_key(HD_DEMO_SK, info, r->hd_demo_sk); + append_key(HD_INCOME_BAND_ID, info, r->hd_income_band_id); + append_varchar(HD_BUY_POTENTIAL, info, r->hd_buy_potential); + append_integer(HD_DEP_COUNT, info, r->hd_dep_count); + append_integer(HD_VEHICLE_COUNT, info, r->hd_vehicle_count); + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_income_band.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_income_band.cpp new file mode 100644 index 0000000000000..e354e7c592e2f --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_income_band.cpp @@ -0,0 +1,61 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_income_band.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "nulls.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * mk_income_band + */ +int mk_w_income_band( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + struct W_INCOME_BAND_TBL* r; + tdef* pTdef = getSimpleTdefsByNumber(INCOME_BAND, dsdGenContext); + + r = &dsdGenContext.g_w_income_band; + + nullSet(&pTdef->kNullBitMap, IB_NULLS, dsdGenContext); + r->ib_income_band_id = static_cast(index); + dist_member( + &r->ib_lower_bound, + "income_band", + static_cast(index), + 1, + dsdGenContext); + dist_member( + &r->ib_upper_bound, + "income_band", + static_cast(index), + 2, + dsdGenContext); + + void* info = append_info_get(info_arr, INCOME_BAND); + append_row_start(info); + append_key(IB_INCOME_BAND_ID, info, r->ib_income_band_id); + append_integer(IB_LOWER_BOUND, info, r->ib_lower_bound); + append_integer(IB_UPPER_BOUND, info, r->ib_upper_bound); + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_inventory.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_inventory.cpp new file mode 100644 index 0000000000000..f0544a73c751e --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_inventory.cpp @@ -0,0 +1,137 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_inventory.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "genrand.h" +#include "nulls.h" +#include "porting.h" +#include "scaling.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int mk_w_inventory( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + struct W_INVENTORY_TBL* r; + ds_key_t item_count; + ds_key_t warehouse_count; + int jDate; + date_t base_date_storage; + date_t* base_date = &base_date_storage; + int nTemp; + tdef* pTdef = getSimpleTdefsByNumber(INVENTORY, dsdGenContext); + + r = &dsdGenContext.g_w_inventory; + + if (!dsdGenContext.mk_w_promotion_init) { + memset(&dsdGenContext.g_w_inventory, 0, sizeof(struct W_INVENTORY_TBL)); + dsdGenContext.mk_w_promotion_init = 1; + } + item_count = getIDCount(ITEM, dsdGenContext); + warehouse_count = get_rowcount(WAREHOUSE, dsdGenContext); + strtodt(base_date, DATE_MINIMUM); + jDate = base_date->julian; + set_dow(base_date); + /* Make exceptions to the 1-rng-call-per-row rule */ + + nullSet(&pTdef->kNullBitMap, INV_NULLS, dsdGenContext); + nTemp = static_cast(index - 1); + r->inv_item_sk = (nTemp % item_count) + 1; + nTemp /= static_cast(item_count); + r->inv_warehouse_sk = (nTemp % warehouse_count) + 1; + nTemp /= static_cast(warehouse_count); + r->inv_date_sk = jDate + (nTemp * 7); /* inventory is updated weekly */ + + /* + * the join between item and inventory is tricky. The item_id selected above + * identifies a unique part num but item is an SCD, so we need to account + * for that in selecting the SK to join with + */ + r->inv_item_sk = + matchSCDSK(r->inv_item_sk, r->inv_date_sk, ITEM, dsdGenContext); + + genrand_integer( + &r->inv_quantity_on_hand, + DIST_UNIFORM, + INV_QUANTITY_MIN, + INV_QUANTITY_MAX, + 0, + INV_QUANTITY_ON_HAND, + dsdGenContext); + + void* info = append_info_get(info_arr, INVENTORY); + append_row_start(info); + append_key(INV_DATE_SK, info, r->inv_date_sk); + append_key(INV_ITEM_SK, info, r->inv_item_sk); + append_key(INV_WAREHOUSE_SK, info, r->inv_warehouse_sk); + append_integer(INV_QUANTITY_ON_HAND, info, r->inv_quantity_on_hand); + append_row_end(info); + + return 0; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +ds_key_t sc_w_inventory(int nScale, DSDGenContext& dsdGenContext) { + ds_key_t kRes; + date_t dTemp; + int nDays; + + kRes = getIDCount(ITEM, dsdGenContext); + kRes *= get_rowcount(WAREHOUSE, dsdGenContext); + strtodt(&dTemp, DATE_MAXIMUM); + nDays = dTemp.julian; + strtodt(&dTemp, DATE_MINIMUM); + nDays -= dTemp.julian; + nDays += 1; + nDays += 6; + nDays /= 7; /* each items inventory is updated weekly */ + kRes *= nDays; + + return (kRes); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_item.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_item.cpp new file mode 100644 index 0000000000000..1915ee40a9012 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_item.cpp @@ -0,0 +1,308 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_item.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "porting.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* extern tdef w_tdefs[]; */ + +static struct W_ITEM_TBL g_OldValues; + +/* + * mk_item + */ +int mk_w_item(void* info_arr, ds_key_t index, DSDGenContext& dsdGenContext) { + /* begin locals declarations */ + decimal_t dMinPrice, dMaxPrice, dMarkdown; + decimal_t dMinMarkdown, dMaxMarkdown; + int32_t bUseSize, bFirstRecord = 0, nFieldChangeFlags, nMin, nMax, nIndex, + nTemp; + char* cp = nullptr; + struct W_ITEM_TBL* r; + struct W_ITEM_TBL* rOldValues = &g_OldValues; + char *szMinPrice = nullptr, *szMaxPrice = nullptr; + tdef* pT = getSimpleTdefsByNumber(ITEM, dsdGenContext); + + r = &dsdGenContext.g_w_item; + + strtodec(&dMinMarkdown, MIN_ITEM_MARKDOWN_PCT); + strtodec(&dMaxMarkdown, MAX_ITEM_MARKDOWN_PCT); + memset(r, 0, sizeof(struct W_ITEM_TBL)); + + /* build the new value */ + nullSet(&pT->kNullBitMap, I_NULLS, dsdGenContext); + r->i_item_sk = index; + + nIndex = pick_distribution( + &nMin, "i_manager_id", 2, 1, I_MANAGER_ID, dsdGenContext); + dist_member(&nMax, "i_manager_id", nIndex, 3, dsdGenContext); + genrand_key( + &r->i_manager_id, + DIST_UNIFORM, + static_cast(nMin), + static_cast(nMax), + 0, + I_MANAGER_ID, + dsdGenContext); + + /* if we have generated the required history for this business key and + * generate a new one then reset associated fields (e.g., rec_start_date + * minimums) + */ + if (setSCDKeys( + I_ITEM_ID, + index, + r->i_item_id, + &r->i_rec_start_date_id, + &r->i_rec_end_date_id, + dsdGenContext)) { + /* + * some fields are not changed, even when a new version of the row is + * written + */ + bFirstRecord = 1; + } + + /* + * this is where we select the random number that controls if a field + * changes from one record to the next. + */ + nFieldChangeFlags = next_random(I_SCD, dsdGenContext); + + /* the rest of the record in a history-keeping dimension can either be a new + * data value or not; use a random number and its bit pattern to determine + * which fields to replace and which to retain + */ + gen_text(r->i_item_desc, 1, RS_I_ITEM_DESC, I_ITEM_DESC, dsdGenContext); + changeSCD( + SCD_CHAR, + &r->i_item_desc, + &rOldValues->i_item_desc, + &nFieldChangeFlags, + bFirstRecord); + + nIndex = pick_distribution( + &szMinPrice, "i_current_price", 2, 1, I_CURRENT_PRICE, dsdGenContext); + dist_member(&szMaxPrice, "i_current_price", nIndex, 3, dsdGenContext); + strtodec(&dMinPrice, szMinPrice); + strtodec(&dMaxPrice, szMaxPrice); + genrand_decimal( + &r->i_current_price, + DIST_UNIFORM, + &dMinPrice, + &dMaxPrice, + NULL, + I_CURRENT_PRICE, + dsdGenContext); + changeSCD( + SCD_INT, + &r->i_current_price, + &rOldValues->i_current_price, + &nFieldChangeFlags, + bFirstRecord); + + genrand_decimal( + &dMarkdown, + DIST_UNIFORM, + &dMinMarkdown, + &dMaxMarkdown, + NULL, + I_WHOLESALE_COST, + dsdGenContext); + decimal_t_op(&r->i_wholesale_cost, OP_MULT, &r->i_current_price, &dMarkdown); + changeSCD( + SCD_DEC, + &r->i_wholesale_cost, + &rOldValues->i_wholesale_cost, + &nFieldChangeFlags, + bFirstRecord); + + hierarchy_item( + I_CATEGORY, &r->i_category_id, &r->i_category, index, dsdGenContext); + /* + * changeSCD(SCD_INT, &r->i_category_id, &rOldValues->i_category_id, + * &nFieldChangeFlags, bFirstRecord); + */ + + hierarchy_item(I_CLASS, &r->i_class_id, &r->i_class, index, dsdGenContext); + changeSCD( + SCD_KEY, + &r->i_class_id, + &rOldValues->i_class_id, + &nFieldChangeFlags, + bFirstRecord); + + cp = &r->i_brand[0]; + hierarchy_item(I_BRAND, &r->i_brand_id, &cp, index, dsdGenContext); + changeSCD( + SCD_KEY, + &r->i_brand_id, + &rOldValues->i_brand_id, + &nFieldChangeFlags, + bFirstRecord); + + /* some categories have meaningful sizes, some don't */ + if (r->i_category_id) { + dist_member( + &bUseSize, + "categories", + static_cast(r->i_category_id), + 3, + dsdGenContext); + pick_distribution( + &r->i_size, "sizes", 1, bUseSize + 2, I_SIZE, dsdGenContext); + changeSCD( + SCD_PTR, + &r->i_size, + &rOldValues->i_size, + &nFieldChangeFlags, + bFirstRecord); + } else { + bUseSize = 0; + r->i_size = NULL; + } + + nIndex = pick_distribution( + &nMin, "i_manufact_id", 2, 1, I_MANUFACT_ID, dsdGenContext); + genrand_integer( + &nTemp, + DIST_UNIFORM, + nMin, + dist_member(NULL, "i_manufact_id", nIndex, 3, dsdGenContext), + 0, + I_MANUFACT_ID, + dsdGenContext); + r->i_manufact_id = nTemp; + changeSCD( + SCD_KEY, + &r->i_manufact_id, + &rOldValues->i_manufact_id, + &nFieldChangeFlags, + bFirstRecord); + + mk_word( + r->i_manufact, + "syllables", + static_cast(r->i_manufact_id), + RS_I_MANUFACT, + ITEM, + dsdGenContext); + changeSCD( + SCD_CHAR, + &r->i_manufact, + &rOldValues->i_manufact, + &nFieldChangeFlags, + bFirstRecord); + + gen_charset( + r->i_formulation, + DIGITS, + RS_I_FORMULATION, + RS_I_FORMULATION, + I_FORMULATION, + dsdGenContext); + embed_string(r->i_formulation, "colors", 1, 2, I_FORMULATION, dsdGenContext); + changeSCD( + SCD_CHAR, + &r->i_formulation, + &rOldValues->i_formulation, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution(&r->i_color, "colors", 1, 2, I_COLOR, dsdGenContext); + changeSCD( + SCD_PTR, + &r->i_color, + &rOldValues->i_color, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution(&r->i_units, "units", 1, 1, I_UNITS, dsdGenContext); + changeSCD( + SCD_PTR, + &r->i_units, + &rOldValues->i_units, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution(&r->i_container, "container", 1, 1, ITEM, dsdGenContext); + changeSCD( + SCD_PTR, + &r->i_container, + &rOldValues->i_container, + &nFieldChangeFlags, + bFirstRecord); + + mk_word( + r->i_product_name, + "syllables", + static_cast(index), + RS_I_PRODUCT_NAME, + ITEM, + dsdGenContext); + + r->i_promo_sk = mk_join(I_PROMO_SK, PROMOTION, 1, dsdGenContext); + genrand_integer(&nTemp, DIST_UNIFORM, 1, 100, 0, I_PROMO_SK, dsdGenContext); + if (nTemp > I_PROMO_PERCENTAGE) + r->i_promo_sk = -1; + + /* + * if this is the first of a set of revisions, then baseline the old values + */ + if (bFirstRecord) + memcpy(&g_OldValues, r, sizeof(struct W_ITEM_TBL)); + + if (index == 1) + memcpy(&g_OldValues, r, sizeof(struct W_ITEM_TBL)); + + void* info = append_info_get(info_arr, ITEM); + append_row_start(info); + + append_key(I_ITEM_SK, info, r->i_item_sk); + append_varchar(I_ITEM_ID, info, r->i_item_id); + append_date(I_REC_START_DATE_ID, info, r->i_rec_start_date_id); + append_date(I_REC_END_DATE_ID, info, r->i_rec_end_date_id); + append_varchar(I_ITEM_DESC, info, r->i_item_desc); + append_decimal(I_CURRENT_PRICE, info, &r->i_current_price); + append_decimal(I_WHOLESALE_COST, info, &r->i_wholesale_cost); + append_integer(I_BRAND_ID, info, r->i_brand_id); + append_varchar(I_BRAND, info, r->i_brand); + append_integer(I_CLASS_ID, info, r->i_class_id); + append_varchar(I_CLASS, info, r->i_class); + append_integer(I_CATEGORY_ID, info, r->i_category_id); + append_varchar(I_CATEGORY, info, r->i_category); + append_integer(I_MANUFACT_ID, info, r->i_manufact_id); + append_varchar(I_MANUFACT, info, r->i_manufact); + append_varchar(I_SIZE, info, r->i_size); + append_varchar(I_FORMULATION, info, r->i_formulation); + append_varchar(I_COLOR, info, r->i_color); + append_varchar(I_UNITS, info, r->i_units); + append_varchar(I_CONTAINER, info, r->i_container); + append_integer(I_MANAGER_ID, info, r->i_manager_id); + append_varchar(I_PRODUCT_NAME, info, r->i_product_name); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_promotion.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_promotion.cpp new file mode 100644 index 0000000000000..65405af4c1bb6 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_promotion.cpp @@ -0,0 +1,148 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_promotion.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * Routine: mk_promotion + * Purpose: populate the promotion table + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20020829 jms RNG usage on p_promo_name may be too large + * 20020829 jms RNG usage on P_CHANNEL_DETAILS may be too large + */ +int mk_w_promotion( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + struct W_PROMOTION_TBL* r; + + /* begin locals declarations */ + date_t start_date; + ds_key_t nTemp; + int nFlags; + tdef* pTdef = getSimpleTdefsByNumber(PROMOTION, dsdGenContext); + + r = &dsdGenContext.g_w_promotion; + + if (!dsdGenContext.mk_w_promotion_init) { + memset(&dsdGenContext.g_w_promotion, 0, sizeof(struct W_PROMOTION_TBL)); + strtodt(&start_date, DATE_MINIMUM); + dsdGenContext.mk_w_promotion_init = 1; + } else { + strtodt(&start_date, DATE_MINIMUM); + } + + nullSet(&pTdef->kNullBitMap, P_NULLS, dsdGenContext); + r->p_promo_sk = index; + mk_bkey(&r->p_promo_id[0], index, P_PROMO_ID); + nTemp = index; + r->p_start_date_id = start_date.julian + + genrand_integer(NULL, + DIST_UNIFORM, + PROMO_START_MIN, + PROMO_START_MAX, + PROMO_START_MEAN, + P_START_DATE_ID, + dsdGenContext); + r->p_end_date_id = r->p_start_date_id + + genrand_integer(NULL, + DIST_UNIFORM, + PROMO_LEN_MIN, + PROMO_LEN_MAX, + PROMO_LEN_MEAN, + P_END_DATE_ID, + dsdGenContext); + r->p_item_sk = mk_join(P_ITEM_SK, ITEM, 1, dsdGenContext); + strtodec(&r->p_cost, "1000.00"); + r->p_response_target = 1; + mk_word( + &r->p_promo_name[0], + "syllables", + static_cast(index), + PROMO_NAME_LEN, + P_PROMO_NAME, + dsdGenContext); + nFlags = static_cast(genrand_integer( + NULL, DIST_UNIFORM, 0, 511, 0, P_CHANNEL_DMAIL, dsdGenContext)); + r->p_channel_dmail = nFlags & 0x01; + nFlags <<= 1; + r->p_channel_email = nFlags & 0x01; + nFlags <<= 1; + r->p_channel_catalog = nFlags & 0x01; + nFlags <<= 1; + r->p_channel_tv = nFlags & 0x01; + nFlags <<= 1; + r->p_channel_radio = nFlags & 0x01; + nFlags <<= 1; + r->p_channel_press = nFlags & 0x01; + nFlags <<= 1; + r->p_channel_event = nFlags & 0x01; + nFlags <<= 1; + r->p_channel_demo = nFlags & 0x01; + nFlags <<= 1; + r->p_discount_active = nFlags & 0x01; + gen_text( + &r->p_channel_details[0], + PROMO_DETAIL_LEN_MIN, + PROMO_DETAIL_LEN_MAX, + P_CHANNEL_DETAILS, + dsdGenContext); + pick_distribution( + &r->p_purpose, "promo_purpose", 1, 1, P_PURPOSE, dsdGenContext); + + void* info = append_info_get(info_arr, PROMOTION); + append_row_start(info); + append_key(P_PROMO_SK, info, r->p_promo_sk); + append_varchar(P_PROMO_ID, info, r->p_promo_id); + append_key(P_START_DATE_ID, info, r->p_start_date_id); + append_key(P_END_DATE_ID, info, r->p_end_date_id); + append_key(P_ITEM_SK, info, r->p_item_sk); + append_decimal(P_COST, info, &r->p_cost); + append_integer(P_RESPONSE_TARGET, info, r->p_response_target); + append_varchar(P_PROMO_NAME, info, &r->p_promo_name[0]); + append_varchar(P_CHANNEL_DMAIL, info, r->p_channel_dmail ? "Y" : "N"); + append_varchar(P_CHANNEL_EMAIL, info, r->p_channel_email ? "Y" : "N"); + append_varchar(P_CHANNEL_CATALOG, info, r->p_channel_catalog ? "Y" : "N"); + append_varchar(P_CHANNEL_TV, info, r->p_channel_tv ? "Y" : "N"); + append_varchar(P_CHANNEL_RADIO, info, r->p_channel_radio ? "Y" : "N"); + append_varchar(P_CHANNEL_PRESS, info, r->p_channel_press ? "Y" : "N"); + append_varchar(P_CHANNEL_EVENT, info, r->p_channel_event ? "Y" : "N"); + append_varchar(P_CHANNEL_DEMO, info, r->p_channel_demo ? "Y" : "N"); + append_varchar(P_CHANNEL_DETAILS, info, &r->p_channel_details[0]); + append_varchar(P_PURPOSE, info, r->p_purpose); + append_varchar(P_DISCOUNT_ACTIVE, info, r->p_discount_active ? "Y" : "N"); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_reason.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_reason.cpp new file mode 100644 index 0000000000000..3d5ad8983da7f --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_reason.cpp @@ -0,0 +1,58 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_reason.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "nulls.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * mk_reason + */ +int mk_w_reason(void* info_arr, ds_key_t index, DSDGenContext& dsdGenContext) { + struct W_REASON_TBL* r; + tdef* pTdef = getSimpleTdefsByNumber(REASON, dsdGenContext); + + r = &dsdGenContext.g_w_reason; + + if (!dsdGenContext.mk_w_reason_init) { + memset(&dsdGenContext.g_w_reason, 0, sizeof(struct W_REASON_TBL)); + dsdGenContext.mk_w_reason_init = 1; + } + + nullSet(&pTdef->kNullBitMap, R_NULLS, dsdGenContext); + r->r_reason_sk = index; + mk_bkey(&r->r_reason_id[0], index, R_REASON_ID); + dist_member( + &r->r_reason_description, + "return_reasons", + static_cast(index), + 1, + dsdGenContext); + + void* info = append_info_get(info_arr, REASON); + append_row_start(info); + append_key(R_REASON_SK, info, r->r_reason_sk); + append_varchar(R_REASON_ID, info, r->r_reason_id); + append_varchar(R_REASON_DESCRIPTION, info, r->r_reason_description); + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_ship_mode.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_ship_mode.cpp new file mode 100644 index 0000000000000..8acae0d0f808c --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_ship_mode.cpp @@ -0,0 +1,83 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_ship_mode.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "nulls.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int mk_w_ship_mode( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext) { + struct W_SHIP_MODE_TBL* r; + ds_key_t nTemp; + tdef* pTdef = getSimpleTdefsByNumber(SHIP_MODE, dsdGenContext); + + r = &dsdGenContext.g_w_ship_mode; + + if (dsdGenContext.mk_w_ship_mode_init) { + memset(&dsdGenContext.g_w_ship_mode, 0, sizeof(struct W_SHIP_MODE_TBL)); + dsdGenContext.mk_w_ship_mode_init = 1; + } + + nullSet(&pTdef->kNullBitMap, SM_NULLS, dsdGenContext); + r->sm_ship_mode_sk = kIndex; + mk_bkey(&r->sm_ship_mode_id[0], kIndex, SM_SHIP_MODE_ID); + nTemp = static_cast(kIndex); + bitmap_to_dist( + &r->sm_type, "ship_mode_type", &nTemp, 1, SHIP_MODE, dsdGenContext); + bitmap_to_dist( + &r->sm_code, "ship_mode_code", &nTemp, 1, SHIP_MODE, dsdGenContext); + dist_member( + &r->sm_carrier, + "ship_mode_carrier", + static_cast(kIndex), + 1, + dsdGenContext); + gen_charset( + r->sm_contract, ALPHANUM, 1, RS_SM_CONTRACT, SM_CONTRACT, dsdGenContext); + + void* info = append_info_get(info_arr, SHIP_MODE); + append_row_start(info); + append_key(SM_SHIP_MODE_SK, info, r->sm_ship_mode_sk); + append_varchar(SM_SHIP_MODE_ID, info, r->sm_ship_mode_id); + append_varchar(SM_TYPE, info, r->sm_type); + append_varchar(SM_CODE, info, r->sm_code); + append_varchar(SM_CARRIER, info, r->sm_carrier); + append_varchar(SM_CONTRACT, info, &r->sm_contract[0]); + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store.cpp new file mode 100644 index 0000000000000..012fea609f92e --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store.cpp @@ -0,0 +1,393 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_store.h" + +#include "append_info.h" +#include "build_support.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "parallel.h" +#include "porting.h" +#include "scaling.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" + +#include +#include + +static struct W_STORE_TBL g_store_OldValues; +/* + * mk_store + */ +int mk_w_store(void* info_arr, ds_key_t index, DSDGenContext& dsdGenContext) { + int32_t nFieldChangeFlags = 0, bFirstRecord = 0; + + /* begin locals declarations */ + static decimal_t dRevMin, dRevMax; + char *sName1 = nullptr, *sName2 = nullptr, *szTemp = nullptr; + int32_t nHierarchyTotal, nStoreType, nPercentage, nDaysOpen, nMin, nMax; + static date_t tDate; + static decimal_t min_rev_growth, max_rev_growth, dMinTaxPercentage, + dMaxTaxPercentage; + struct W_STORE_TBL *r, *rOldValues = &g_store_OldValues; + tdef* pT = getSimpleTdefsByNumber(STORE, dsdGenContext); + + r = &dsdGenContext.g_w_store; + + if (!dsdGenContext.mk_w_store_init) { + nHierarchyTotal = static_cast(get_rowcount(DIVISIONS, dsdGenContext)); + nHierarchyTotal *= static_cast(get_rowcount(COMPANY, dsdGenContext)); + strtodt(&tDate, DATE_MINIMUM); + strtodec(&min_rev_growth, STORE_MIN_REV_GROWTH); + strtodec(&max_rev_growth, STORE_MAX_REV_GROWTH); + strtodec(&dRevMin, "1.00"); + strtodec(&dRevMax, "1000000.00"); + strtodec(&dMinTaxPercentage, STORE_MIN_TAX_PERCENTAGE); + strtodec(&dMaxTaxPercentage, STORE_MAX_TAX_PERCENTAGE); + + /* columns that should be dynamic */ + r->rec_end_date_id = -1; + dsdGenContext.mk_w_store_init = 1; + } + + nullSet(&pT->kNullBitMap, W_STORE_NULLS, dsdGenContext); + r->store_sk = index; + + /* if we have generated the required history for this business key and + * generate a new one then reset associate fields (e.g., rec_start_date + * minimums) + */ + if (setSCDKeys( + S_STORE_ID, + index, + r->store_id, + &r->rec_start_date_id, + &r->rec_end_date_id, + dsdGenContext)) { + bFirstRecord = 1; + } + + /* + * this is where we select the random number that controls if a field + * changes from one record to the next. + */ + nFieldChangeFlags = next_random(W_STORE_SCD, dsdGenContext); + + /* the rest of the record in a history-keeping dimension can either be a new + * data value or not; use a random number and its bit pattern to determine + * which fields to replace and which to retain + */ + nPercentage = genrand_integer( + NULL, DIST_UNIFORM, 1, 100, 0, W_STORE_CLOSED_DATE_ID, dsdGenContext); + nDaysOpen = genrand_integer( + NULL, + DIST_UNIFORM, + STORE_MIN_DAYS_OPEN, + STORE_MAX_DAYS_OPEN, + 0, + W_STORE_CLOSED_DATE_ID, + dsdGenContext); + if (nPercentage < STORE_CLOSED_PCT) + r->closed_date_id = tDate.julian + nDaysOpen; + else + r->closed_date_id = -1; + changeSCD( + SCD_KEY, + &r->closed_date_id, + &rOldValues->closed_date_id, + &nFieldChangeFlags, + bFirstRecord); + if (!r->closed_date_id) + r->closed_date_id = -1; /* dates use a special NULL indicator */ + + mk_word( + r->store_name, + "syllables", + static_cast(index), + 5, + W_STORE_NAME, + dsdGenContext); + changeSCD( + SCD_CHAR, + &r->store_name, + &rOldValues->store_name, + &nFieldChangeFlags, + bFirstRecord); + + /* + * use the store type to set the parameters for the rest of the attributes + */ + nStoreType = pick_distribution( + &szTemp, "store_type", 1, 1, W_STORE_TYPE, dsdGenContext); + dist_member(&nMin, "store_type", nStoreType, 2, dsdGenContext); + dist_member(&nMax, "store_type", nStoreType, 3, dsdGenContext); + genrand_integer( + &r->employees, + DIST_UNIFORM, + nMin, + nMax, + 0, + W_STORE_EMPLOYEES, + dsdGenContext); + changeSCD( + SCD_INT, + &r->employees, + &rOldValues->employees, + &nFieldChangeFlags, + bFirstRecord); + + dist_member(&nMin, "store_type", nStoreType, 4, dsdGenContext); + dist_member(&nMax, "store_type", nStoreType, 5, dsdGenContext), + genrand_integer( + &r->floor_space, + DIST_UNIFORM, + nMin, + nMax, + 0, + W_STORE_FLOOR_SPACE, + dsdGenContext); + changeSCD( + SCD_INT, + &r->floor_space, + &rOldValues->floor_space, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution( + &r->hours, "call_center_hours", 1, 1, W_STORE_HOURS, dsdGenContext); + changeSCD( + SCD_PTR, &r->hours, &rOldValues->hours, &nFieldChangeFlags, bFirstRecord); + + pick_distribution( + &sName1, "first_names", 1, 1, W_STORE_MANAGER, dsdGenContext); + pick_distribution( + &sName2, "last_names", 1, 1, W_STORE_MANAGER, dsdGenContext); + snprintf(r->store_manager, sizeof(r->store_manager), "%s %s", sName1, sName2); + changeSCD( + SCD_CHAR, + &r->store_manager, + &rOldValues->store_manager, + &nFieldChangeFlags, + bFirstRecord); + + r->market_id = genrand_integer( + NULL, DIST_UNIFORM, 1, 10, 0, W_STORE_MARKET_ID, dsdGenContext); + changeSCD( + SCD_INT, + &r->market_id, + &rOldValues->market_id, + &nFieldChangeFlags, + bFirstRecord); + + genrand_decimal( + &r->dTaxPercentage, + DIST_UNIFORM, + &dMinTaxPercentage, + &dMaxTaxPercentage, + NULL, + W_STORE_TAX_PERCENTAGE, + dsdGenContext); + changeSCD( + SCD_DEC, + &r->dTaxPercentage, + &rOldValues->dTaxPercentage, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution( + &r->geography_class, + "geography_class", + 1, + 1, + W_STORE_GEOGRAPHY_CLASS, + dsdGenContext); + changeSCD( + SCD_PTR, + &r->geography_class, + &rOldValues->geography_class, + &nFieldChangeFlags, + bFirstRecord); + + gen_text( + &r->market_desc[0], + STORE_DESC_MIN, + RS_S_MARKET_DESC, + W_STORE_MARKET_DESC, + dsdGenContext); + changeSCD( + SCD_CHAR, + &r->market_desc, + &rOldValues->market_desc, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution( + &sName1, "first_names", 1, 1, W_STORE_MARKET_MANAGER, dsdGenContext); + pick_distribution( + &sName2, "last_names", 1, 1, W_STORE_MARKET_MANAGER, dsdGenContext); + snprintf( + r->market_manager, sizeof(r->market_manager), "%s %s", sName1, sName2); + changeSCD( + SCD_CHAR, + &r->market_manager, + &rOldValues->market_manager, + &nFieldChangeFlags, + bFirstRecord); + + r->division_id = pick_distribution( + &r->division_name, + "divisions", + 1, + 1, + W_STORE_DIVISION_NAME, + dsdGenContext); + changeSCD( + SCD_KEY, + &r->division_id, + &rOldValues->division_id, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->division_name, + &rOldValues->division_name, + &nFieldChangeFlags, + bFirstRecord); + + r->company_id = pick_distribution( + &r->company_name, "stores", 1, 1, W_STORE_COMPANY_NAME, dsdGenContext); + changeSCD( + SCD_KEY, + &r->company_id, + &rOldValues->company_id, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->company_name, + &rOldValues->company_name, + &nFieldChangeFlags, + bFirstRecord); + + mk_address(&r->address, W_STORE_ADDRESS, dsdGenContext); + changeSCD( + SCD_PTR, + &r->address.city, + &rOldValues->address.city, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->address.county, + &rOldValues->address.county, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_INT, + &r->address.gmt_offset, + &rOldValues->address.gmt_offset, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->address.state, + &rOldValues->address.state, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->address.street_type, + &rOldValues->address.street_type, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->address.street_name1, + &rOldValues->address.street_name1, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->address.street_name2, + &rOldValues->address.street_name2, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_INT, + &r->address.street_num, + &rOldValues->address.street_num, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_INT, + &r->address.zip, + &rOldValues->address.zip, + &nFieldChangeFlags, + bFirstRecord); + + char szTemp2[128]; + + void* info = append_info_get(info_arr, STORE); + append_row_start(info); + + append_key(W_STORE_SK, info, r->store_sk); + append_varchar(W_STORE_ID, info, r->store_id); + append_date(W_STORE_REC_START_DATE_ID, info, r->rec_start_date_id); + append_date(W_STORE_REC_END_DATE_ID, info, r->rec_end_date_id); + append_key(W_STORE_CLOSED_DATE_ID, info, r->closed_date_id); + append_varchar(W_STORE_NAME, info, r->store_name); + append_integer(W_STORE_EMPLOYEES, info, r->employees); + append_integer(W_STORE_FLOOR_SPACE, info, r->floor_space); + append_varchar(W_STORE_HOURS, info, r->hours); + append_varchar(W_STORE_MANAGER, info, &r->store_manager[0]); + append_integer(W_STORE_MARKET_ID, info, r->market_id); + append_varchar(W_STORE_GEOGRAPHY_CLASS, info, r->geography_class); + append_varchar(W_STORE_MARKET_DESC, info, &r->market_desc[0]); + append_varchar(W_STORE_MARKET_MANAGER, info, &r->market_manager[0]); + append_integer(W_STORE_DIVISION_ID, info, r->division_id); + append_varchar(W_STORE_DIVISION_NAME, info, r->division_name); + append_integer(W_STORE_COMPANY_ID, info, r->company_id); + append_varchar(W_STORE_COMPANY_NAME, info, r->company_name); + append_varchar( + W_STORE_ADDRESS_STREET_NUM, info, std::to_string(r->address.street_num)); + if (r->address.street_name2) { + snprintf( + szTemp2, + sizeof(szTemp2), + "%s %s", + r->address.street_name1, + r->address.street_name2); + append_varchar(W_STORE_ADDRESS_STREET_NAME1, info, szTemp2); + } else + append_varchar(W_STORE_ADDRESS_STREET_NAME1, info, r->address.street_name1); + append_varchar(W_STORE_ADDRESS_STREET_TYPE, info, r->address.street_type); + append_varchar(W_STORE_ADDRESS_SUITE_NUM, info, r->address.suite_num); + append_varchar(W_STORE_ADDRESS_CITY, info, r->address.city); + append_varchar(W_STORE_ADDRESS_COUNTY, info, r->address.county); + append_varchar(W_STORE_ADDRESS_STATE, info, r->address.state); + snprintf(szTemp2, sizeof(szTemp2), "%05d", r->address.zip); + append_varchar(W_STORE_ADDRESS_ZIP, info, szTemp2); + append_varchar(W_STORE_ADDRESS_COUNTRY, info, r->address.country); + append_integer_decimal( + W_STORE_ADDRESS_GMT_OFFSET, info, r->address.gmt_offset); + append_decimal(W_STORE_TAX_PERCENTAGE, info, &r->dTaxPercentage); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store_returns.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store_returns.cpp new file mode 100644 index 0000000000000..e993c480ab9c0 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store_returns.cpp @@ -0,0 +1,114 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_store_returns.h" +#include +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "genrand.h" +#include "nulls.h" +#include "parallel.h" +#include "porting.h" +#include "pricing.h" +#include "tables.h" +#include "tdefs.h" +#include "w_store_sales.h" + +/* + * Routine: mk_store_returns() + * Purpose: populate a return fact *sync'd with a sales fact* + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int mk_w_store_returns( + void* row, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int res = 0, nTemp; + struct W_STORE_RETURNS_TBL* r; + struct W_STORE_SALES_TBL* sale = &dsdGenContext.g_w_store_sales; + tdef* pT = getSimpleTdefsByNumber(STORE_RETURNS, dsdGenContext); + + decimal_t dMin, dMax; + /* begin locals declarations */ + if (row == NULL) + r = &dsdGenContext.g_w_store_returns; + else + r = static_cast(row); + + strtodec(&dMin, "1.00"); + strtodec(&dMax, "100000.00"); + + nullSet(&pT->kNullBitMap, SR_NULLS, dsdGenContext); + /* + * Some of the information in the return is taken from the original sale + * which has been regenerated + */ + r->sr_ticket_number = sale->ss_ticket_number; + r->sr_item_sk = sale->ss_sold_item_sk; + memcpy( + static_cast(&r->sr_pricing), + static_cast(&sale->ss_pricing), + sizeof(ds_pricing_t)); + + /* + * some of the fields are conditionally taken from the sale + */ + r->sr_customer_sk = mk_join(SR_CUSTOMER_SK, CUSTOMER, 1, dsdGenContext); + if (genrand_integer( + NULL, DIST_UNIFORM, 1, 100, 0, SR_TICKET_NUMBER, dsdGenContext) < + SR_SAME_CUSTOMER) + r->sr_customer_sk = sale->ss_sold_customer_sk; + + /* + * the rest of the columns are generated for this specific return + */ + /* the items cannot be returned until they are sold; offset is handled in + * mk_join, based on sales date */ + r->sr_returned_date_sk = + mk_join(SR_RETURNED_DATE_SK, DATET, sale->ss_sold_date_sk, dsdGenContext); + genrand_integer( + &nTemp, + DIST_UNIFORM, + (8 * 3600) - 1, + (17 * 3600) - 1, + 0, + SR_RETURNED_TIME_SK, + dsdGenContext); + r->sr_returned_time_sk = nTemp; + r->sr_cdemo_sk = + mk_join(SR_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 1, dsdGenContext); + r->sr_hdemo_sk = + mk_join(SR_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 1, dsdGenContext); + r->sr_addr_sk = mk_join(SR_ADDR_SK, CUSTOMER_ADDRESS, 1, dsdGenContext); + r->sr_store_sk = mk_join(SR_STORE_SK, STORE, 1, dsdGenContext); + r->sr_reason_sk = mk_join(SR_REASON_SK, REASON, 1, dsdGenContext); + genrand_integer( + &r->sr_pricing.quantity, + DIST_UNIFORM, + 1, + sale->ss_pricing.quantity, + 0, + SR_PRICING, + dsdGenContext); + set_pricing(SR_PRICING, &r->sr_pricing, dsdGenContext); + + return (res); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store_sales.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store_sales.cpp new file mode 100644 index 0000000000000..b8448192c6005 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_store_sales.cpp @@ -0,0 +1,259 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_store_sales.h" + +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "decimal.h" +#include "genrand.h" +#include "nulls.h" +#include "parallel.h" +#include "permute.h" +#include "porting.h" +#include "scaling.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" +#include "w_store_returns.h" + +// ds_key_t +// skipDays(int nTable, ds_key_t* pRemainder, DSDGenContext& dsdGenContext); + +/* + * mk_store_sales + */ +W_STORE_SALES_TBL* mk_master_store_sales( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + decimal_t dMin, dMax; + int nMaxItemCount; + struct W_STORE_SALES_TBL* r; + r = &dsdGenContext.g_w_store_sales; + + if (!dsdGenContext.mk_master_store_sales_init) { + strtodec(&dMin, "1.00"); + strtodec(&dMax, "100000.00"); + nMaxItemCount = 20; + dsdGenContext.pStoreSalesItemPermutation = makePermutation( + NULL, + dsdGenContext.nStoreSalesItemCount = + static_cast(getIDCount(ITEM, dsdGenContext)), + SS_PERMUTATION, + dsdGenContext); + + dsdGenContext.mk_master_store_sales_init = 1; + } else { + strtodec(&dMin, "1.00"); + strtodec(&dMax, "100000.00"); + } + + r->ss_sold_store_sk = mk_join(SS_SOLD_STORE_SK, STORE, 1, dsdGenContext); + r->ss_sold_time_sk = mk_join(SS_SOLD_TIME_SK, TIME, 1, dsdGenContext); + r->ss_sold_date_sk = mk_join(SS_SOLD_DATE_SK, DATET, 1, dsdGenContext); + r->ss_sold_customer_sk = + mk_join(SS_SOLD_CUSTOMER_SK, CUSTOMER, 1, dsdGenContext); + r->ss_sold_cdemo_sk = + mk_join(SS_SOLD_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 1, dsdGenContext); + r->ss_sold_hdemo_sk = + mk_join(SS_SOLD_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 1, dsdGenContext); + r->ss_sold_addr_sk = + mk_join(SS_SOLD_ADDR_SK, CUSTOMER_ADDRESS, 1, dsdGenContext); + r->ss_ticket_number = index; + genrand_integer( + &dsdGenContext.nStoreSalesItemIndex, + DIST_UNIFORM, + 1, + dsdGenContext.nStoreSalesItemCount, + 0, + SS_SOLD_ITEM_SK, + dsdGenContext); + + return r; +} + +void mk_detail( + void* info_arr, + int bPrint, + struct W_STORE_SALES_TBL* r, + DSDGenContext& dsdGenContext) { + int nTemp; + tdef* pT = getSimpleTdefsByNumber(STORE_SALES, dsdGenContext); + + nullSet(&pT->kNullBitMap, SS_NULLS, dsdGenContext); + /* + * items need to be unique within an order + * use a sequence within the permutation + */ + if (++dsdGenContext.nStoreSalesItemIndex > dsdGenContext.nStoreSalesItemCount) + dsdGenContext.nStoreSalesItemIndex = 1; + int getperm = getPermutationEntry( + dsdGenContext.pStoreSalesItemPermutation, + dsdGenContext.nStoreSalesItemIndex); + r->ss_sold_item_sk = + matchSCDSK(getperm, r->ss_sold_date_sk, ITEM, dsdGenContext); + r->ss_sold_promo_sk = mk_join(SS_SOLD_PROMO_SK, PROMOTION, 1, dsdGenContext); + set_pricing(SS_PRICING, &r->ss_pricing, dsdGenContext); + + /** + * having gone to the trouble to make the sale, now let's see if it gets + * returned + */ + genrand_integer( + &nTemp, DIST_UNIFORM, 0, 99, 0, SR_IS_RETURNED, dsdGenContext); + if (nTemp < SR_RETURN_PCT) { + struct W_STORE_RETURNS_TBL w_web_returns; + struct W_STORE_RETURNS_TBL* rr = &w_web_returns; + mk_w_store_returns(rr, 1, dsdGenContext); + + void* info = append_info_get(info_arr, STORE_RETURNS); + append_row_start(info); + + append_key(SR_RETURNED_DATE_SK, info, rr->sr_returned_date_sk); + append_key(SR_RETURNED_TIME_SK, info, rr->sr_returned_time_sk); + append_key(SR_ITEM_SK, info, rr->sr_item_sk); + append_key(SR_CUSTOMER_SK, info, rr->sr_customer_sk); + append_key(SR_CDEMO_SK, info, rr->sr_cdemo_sk); + append_key(SR_HDEMO_SK, info, rr->sr_hdemo_sk); + append_key(SR_ADDR_SK, info, rr->sr_addr_sk); + append_key(SR_STORE_SK, info, rr->sr_store_sk); + append_key(SR_REASON_SK, info, rr->sr_reason_sk); + append_key(SR_TICKET_NUMBER, info, rr->sr_ticket_number); + append_integer(SR_PRICING_QUANTITY, info, rr->sr_pricing.quantity); + append_decimal(SR_PRICING_NET_PAID, info, &rr->sr_pricing.net_paid); + append_decimal(SR_PRICING_EXT_TAX, info, &rr->sr_pricing.ext_tax); + append_decimal( + SR_PRICING_NET_PAID_INC_TAX, info, &rr->sr_pricing.net_paid_inc_tax); + append_decimal(SR_PRICING_FEE, info, &rr->sr_pricing.fee); + append_decimal( + SR_PRICING_EXT_SHIP_COST, info, &rr->sr_pricing.ext_ship_cost); + append_decimal( + SR_PRICING_REFUNDED_CASH, info, &rr->sr_pricing.refunded_cash); + append_decimal( + SR_PRICING_REVERSED_CHARGE, info, &rr->sr_pricing.reversed_charge); + append_decimal(SR_PRICING_STORE_CREDIT, info, &rr->sr_pricing.store_credit); + append_decimal(SR_PRICING_NET_LOSS, info, &rr->sr_pricing.net_loss); + append_row_end(info); + } + + void* info = append_info_get(info_arr, STORE_SALES); + append_row_start(info); + + append_key(SS_SOLD_DATE_SK, info, r->ss_sold_date_sk); + append_key(SS_SOLD_TIME_SK, info, r->ss_sold_time_sk); + append_key(SS_SOLD_ITEM_SK, info, r->ss_sold_item_sk); + append_key(SS_SOLD_CUSTOMER_SK, info, r->ss_sold_customer_sk); + append_key(SS_SOLD_CDEMO_SK, info, r->ss_sold_cdemo_sk); + append_key(SS_SOLD_HDEMO_SK, info, r->ss_sold_hdemo_sk); + append_key(SS_SOLD_ADDR_SK, info, r->ss_sold_addr_sk); + append_key(SS_SOLD_STORE_SK, info, r->ss_sold_store_sk); + append_key(SS_SOLD_PROMO_SK, info, r->ss_sold_promo_sk); + append_key(SS_TICKET_NUMBER, info, r->ss_ticket_number); + append_integer(SS_PRICING_QUANTITY, info, r->ss_pricing.quantity); + append_decimal( + SS_PRICING_WHOLESALE_COST, info, &r->ss_pricing.wholesale_cost); + append_decimal(SS_PRICING_LIST_PRICE, info, &r->ss_pricing.list_price); + append_decimal(SS_PRICING_SALES_PRICE, info, &r->ss_pricing.sales_price); + append_decimal(SS_PRICING_COUPON_AMT, info, &r->ss_pricing.coupon_amt); + append_decimal( + SS_PRICING_EXT_SALES_PRICE, info, &r->ss_pricing.ext_sales_price); + append_decimal( + SS_PRICING_EXT_WHOLESALE_COST, info, &r->ss_pricing.ext_wholesale_cost); + append_decimal( + SS_PRICING_EXT_LIST_PRICE, info, &r->ss_pricing.ext_list_price); + append_decimal(SS_PRICING_EXT_TAX, info, &r->ss_pricing.ext_tax); + append_decimal(SS_PRICING_COUPON_AMT, info, &r->ss_pricing.coupon_amt); + append_decimal(SS_PRICING_NET_PAID, info, &r->ss_pricing.net_paid); + append_decimal( + SS_PRICING_NET_PAID_INC_TAX, info, &r->ss_pricing.net_paid_inc_tax); + append_decimal(SS_PRICING_NET_PROFIT, info, &r->ss_pricing.net_profit); + + append_row_end(info); + + return; +} + +/* + * mk_store_sales + */ +int mk_w_store_sales( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int nLineitems, i; + row_skip(STORE_RETURNS, (index - 1), dsdGenContext); + + /* build the static portion of an order */ + struct W_STORE_SALES_TBL* r; + r = mk_master_store_sales(info_arr, index, dsdGenContext); + + /* set the number of lineitems and build them */ + genrand_integer( + &nLineitems, DIST_UNIFORM, 8, 16, 0, SS_TICKET_NUMBER, dsdGenContext); + for (i = 1; i <= nLineitems; i++) { + mk_detail(info_arr, 1, r, dsdGenContext); + } + + /** + * and finally return 1 since we have already printed the rows + */ + return 0; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int vld_w_store_sales( + int nTable, + ds_key_t kRow, + int* Permutation, + DSDGenContext& dsdGenContext) { + int nLineitem, nMaxLineitem, i; + + row_skip(nTable, kRow - 1, dsdGenContext); + row_skip(STORE_RETURNS, kRow - 1, dsdGenContext); + // dsdGenContext.jDate = + // skipDays(STORE_SALES, &dsdGenContext.kNewDateIndex, dsdGenContext); + + struct W_STORE_SALES_TBL* r; + r = mk_master_store_sales(NULL, kRow, dsdGenContext); + genrand_integer( + &nMaxLineitem, DIST_UNIFORM, 8, 16, 9, SS_TICKET_NUMBER, dsdGenContext); + genrand_integer( + &nLineitem, + DIST_UNIFORM, + 1, + nMaxLineitem, + 0, + SS_PRICING_QUANTITY, + dsdGenContext); + for (i = 1; i < nLineitem; i++) { + mk_detail(NULL, 0, r, dsdGenContext); + } + mk_detail(NULL, 1, r, dsdGenContext); + + return (0); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_timetbl.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_timetbl.cpp new file mode 100644 index 0000000000000..b06d87547821a --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_timetbl.cpp @@ -0,0 +1,70 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_timetbl.h" + +#include "append_info.h" +#include "build_support.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * mk_time + */ +int mk_w_time(void* info_arr, ds_key_t index, DSDGenContext& dsdGenContext) { + /* begin locals declarations */ + int nTemp; + struct W_TIME_TBL* r; + tdef* pT = getSimpleTdefsByNumber(TIME, dsdGenContext); + + r = &dsdGenContext.g_w_time; + + nullSet(&pT->kNullBitMap, T_NULLS, dsdGenContext); + r->t_time_sk = index - 1; + mk_bkey(&r->t_time_id[0], index, T_TIME_ID); + r->t_time = static_cast(index - 1); + nTemp = static_cast(index - 1); + r->t_second = nTemp % 60; + nTemp /= 60; + r->t_minute = nTemp % 60; + nTemp /= 60; + r->t_hour = nTemp % 24; + dist_member(&r->t_am_pm, "hours", r->t_hour + 1, 2, dsdGenContext); + dist_member(&r->t_shift, "hours", r->t_hour + 1, 3, dsdGenContext); + dist_member(&r->t_sub_shift, "hours", r->t_hour + 1, 4, dsdGenContext); + dist_member(&r->t_meal_time, "hours", r->t_hour + 1, 5, dsdGenContext); + + void* info = append_info_get(info_arr, TIME); + append_row_start(info); + append_key(T_TIME_SK, info, r->t_time_sk); + append_varchar(T_TIME_ID, info, r->t_time_id); + append_integer(T_TIME, info, r->t_time); + append_integer(T_HOUR, info, r->t_hour); + append_integer(T_MINUTE, info, r->t_minute); + append_integer(T_SECOND, info, r->t_second); + append_varchar(T_AM_PM, info, r->t_am_pm); + append_varchar(T_SHIFT, info, r->t_shift); + append_varchar(T_SUB_SHIFT, info, r->t_sub_shift); + append_varchar(T_MEAL_TIME, info, r->t_meal_time, false); + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_warehouse.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_warehouse.cpp new file mode 100644 index 0000000000000..93651e85c6f92 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_warehouse.cpp @@ -0,0 +1,97 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_warehouse.h" + +#include "address.h" +#include "append_info.h" +#include "build_support.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "porting.h" +#include "tables.h" +#include "tdefs.h" + +#include + +/* + * mk_warehouse + */ +int mk_w_warehouse( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + /* begin locals declarations */ + struct W_WAREHOUSE_TBL* r; + tdef* pT = getSimpleTdefsByNumber(WAREHOUSE, dsdGenContext); + + r = &dsdGenContext.g_w_warehouse; + + nullSet(&pT->kNullBitMap, W_NULLS, dsdGenContext); + r->w_warehouse_sk = index; + mk_bkey(&r->w_warehouse_id[0], index, W_WAREHOUSE_ID); + gen_text( + &r->w_warehouse_name[0], + W_NAME_MIN, + RS_W_WAREHOUSE_NAME, + W_WAREHOUSE_NAME, + dsdGenContext); + r->w_warehouse_sq_ft = genrand_integer( + NULL, + DIST_UNIFORM, + W_SQFT_MIN, + W_SQFT_MAX, + 0, + W_WAREHOUSE_SQ_FT, + dsdGenContext); + + mk_address(&r->w_address, W_WAREHOUSE_ADDRESS, dsdGenContext); + + char szTemp[128]; + + void* info = append_info_get(info_arr, WAREHOUSE); + append_row_start(info); + + append_key(W_WAREHOUSE_SK, info, r->w_warehouse_sk); + append_varchar(W_WAREHOUSE_ID, info, r->w_warehouse_id); + append_varchar(W_WAREHOUSE_NAME, info, &r->w_warehouse_name[0]); + append_integer(W_WAREHOUSE_SQ_FT, info, r->w_warehouse_sq_ft); + append_varchar( + W_ADDRESS_STREET_NUM, info, std::to_string(r->w_address.street_num)); + if (r->w_address.street_name2 != NULL) { + snprintf( + szTemp, + sizeof(szTemp), + "%s %s", + r->w_address.street_name1, + r->w_address.street_name2); + append_varchar(W_ADDRESS_STREET_NAME1, info, szTemp); + } else + append_varchar(W_ADDRESS_STREET_NAME1, info, r->w_address.street_name1); + append_varchar(W_ADDRESS_STREET_TYPE, info, r->w_address.street_type); + append_varchar(W_ADDRESS_SUITE_NUM, info, r->w_address.suite_num); + append_varchar(W_ADDRESS_CITY, info, r->w_address.city); + append_varchar(W_ADDRESS_COUNTY, info, r->w_address.county); + append_varchar(W_ADDRESS_STATE, info, r->w_address.state); + snprintf(szTemp, sizeof(szTemp), "%05d", r->w_address.zip); + append_varchar(W_ADDRESS_ZIP, info, szTemp); + append_varchar(W_ADDRESS_COUNTRY, info, r->w_address.country); + append_integer_decimal(W_ADDRESS_GMT_OFFSET, info, r->w_address.gmt_offset); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_page.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_page.cpp new file mode 100644 index 0000000000000..7b6a495533fb6 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_page.cpp @@ -0,0 +1,250 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_web_page.h" + +#include "append_info.h" +#include "build_support.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "porting.h" +#include "scaling.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" + +#include + +static struct W_WEB_PAGE_TBL g_web_page_OldValues; + +/* + * Routine: mk_web_page() + * Purpose: populate the web_page table + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + * 20020815 jms check text generation/seed usage + */ +int mk_w_web_page( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int32_t bFirstRecord = 0, nFieldChangeFlags; + date_t dToday; + ds_key_t nConcurrent, nRevisions; + + /* begin locals declarations */ + int32_t nTemp, nAccess; + char szTemp[16]; + struct W_WEB_PAGE_TBL *r, *rOldValues = &g_web_page_OldValues; + tdef* pT = getSimpleTdefsByNumber(WEB_PAGE, dsdGenContext); + + r = &dsdGenContext.g_w_web_page; + + /* setup invariant values */ + snprintf( + szTemp, + sizeof(szTemp), + "%d-%d-%d", + CURRENT_YEAR, + CURRENT_MONTH, + CURRENT_DAY); + strtodt(&dToday, szTemp); + /* set up for the SCD handling */ + nConcurrent = + static_cast(get_rowcount(CONCURRENT_WEB_SITES, dsdGenContext)); + nRevisions = + static_cast(get_rowcount(WEB_PAGE, dsdGenContext) / nConcurrent); + + nullSet(&pT->kNullBitMap, WP_NULLS, dsdGenContext); + r->wp_page_sk = index; + + /* if we have generated the required history for this business key and + * generate a new one then reset associate fields (e.g., rec_start_date + * minimums) + */ + if (setSCDKeys( + WP_PAGE_ID, + index, + r->wp_page_id, + &r->wp_rec_start_date_id, + &r->wp_rec_end_date_id, + dsdGenContext)) { + /* + * some fields are not changed, even when a new version of the row is + * written + */ + bFirstRecord = 1; + } + + /* + * this is where we select the random number that controls if a field + * changes from one record to the next. + */ + nFieldChangeFlags = next_random(WP_SCD, dsdGenContext); + + r->wp_creation_date_sk = + mk_join(WP_CREATION_DATE_SK, DATET, index, dsdGenContext); + changeSCD( + SCD_KEY, + &r->wp_creation_date_sk, + &rOldValues->wp_creation_date_sk, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &nAccess, + DIST_UNIFORM, + 0, + WP_IDLE_TIME_MAX, + 0, + WP_ACCESS_DATE_SK, + dsdGenContext); + r->wp_access_date_sk = dToday.julian - nAccess; + changeSCD( + SCD_KEY, + &r->wp_access_date_sk, + &rOldValues->wp_access_date_sk, + &nFieldChangeFlags, + bFirstRecord); + if (r->wp_access_date_sk == 0) + r->wp_access_date_sk = -1; /* special case for dates */ + + genrand_integer( + &nTemp, DIST_UNIFORM, 0, 99, 0, WP_AUTOGEN_FLAG, dsdGenContext); + r->wp_autogen_flag = (nTemp < WP_AUTOGEN_PCT) ? 1 : 0; + changeSCD( + SCD_INT, + &r->wp_autogen_flag, + &rOldValues->wp_autogen_flag, + &nFieldChangeFlags, + bFirstRecord); + + r->wp_customer_sk = mk_join(WP_CUSTOMER_SK, CUSTOMER, 1, dsdGenContext); + changeSCD( + SCD_KEY, + &r->wp_customer_sk, + &rOldValues->wp_customer_sk, + &nFieldChangeFlags, + bFirstRecord); + + if (!r->wp_autogen_flag) + r->wp_customer_sk = -1; + + genrand_url(r->wp_url, WP_URL); + changeSCD( + SCD_CHAR, + &r->wp_url, + &rOldValues->wp_url, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution(&r->wp_type, "web_page_use", 1, 1, WP_TYPE, dsdGenContext); + changeSCD( + SCD_PTR, + &r->wp_type, + &rOldValues->wp_type, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->wp_link_count, + DIST_UNIFORM, + WP_LINK_MIN, + WP_LINK_MAX, + 0, + WP_LINK_COUNT, + dsdGenContext); + changeSCD( + SCD_INT, + &r->wp_link_count, + &rOldValues->wp_link_count, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->wp_image_count, + DIST_UNIFORM, + WP_IMAGE_MIN, + WP_IMAGE_MAX, + 0, + WP_IMAGE_COUNT, + dsdGenContext); + changeSCD( + SCD_INT, + &r->wp_image_count, + &rOldValues->wp_image_count, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->wp_max_ad_count, + DIST_UNIFORM, + WP_AD_MIN, + WP_AD_MAX, + 0, + WP_MAX_AD_COUNT, + dsdGenContext); + changeSCD( + SCD_INT, + &r->wp_max_ad_count, + &rOldValues->wp_max_ad_count, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->wp_char_count, + DIST_UNIFORM, + r->wp_link_count * 125 + r->wp_image_count * 50, + r->wp_link_count * 300 + r->wp_image_count * 150, + 0, + WP_CHAR_COUNT, + dsdGenContext); + changeSCD( + SCD_INT, + &r->wp_char_count, + &rOldValues->wp_char_count, + &nFieldChangeFlags, + bFirstRecord); + + void* info = append_info_get(info_arr, WEB_PAGE); + append_row_start(info); + + append_key(WP_PAGE_SK, info, r->wp_page_sk); + append_varchar(WP_PAGE_ID, info, r->wp_page_id); + append_date(WP_REC_START_DATE_ID, info, r->wp_rec_start_date_id); + append_date(WP_REC_END_DATE_ID, info, r->wp_rec_end_date_id); + append_key(WP_CREATION_DATE_SK, info, r->wp_creation_date_sk); + append_key(WP_ACCESS_DATE_SK, info, r->wp_access_date_sk); + append_varchar(WP_AUTOGEN_FLAG, info, r->wp_autogen_flag ? "Y" : "N"); + append_key(WP_CUSTOMER_SK, info, r->wp_customer_sk); + append_varchar(WP_URL, info, &r->wp_url[0]); + append_varchar(WP_TYPE, info, &r->wp_type[0]); + append_integer(WP_CHAR_COUNT, info, r->wp_char_count); + append_integer(WP_LINK_COUNT, info, r->wp_link_count); + append_integer(WP_IMAGE_COUNT, info, r->wp_image_count); + append_integer(WP_MAX_AD_COUNT, info, r->wp_max_ad_count); + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_returns.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_returns.cpp new file mode 100644 index 0000000000000..1d4fd92ca588d --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_returns.cpp @@ -0,0 +1,123 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_web_returns.h" +#include +#include "build_support.h" +#include "config.h" +#include "date.h" +#include "decimal.h" +#include "error_msg.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "porting.h" +#include "pricing.h" +#include "tables.h" +#include "tdefs.h" +#include "w_web_sales.h" + +/* + * Routine: mk_web_returns() + * Purpose: populate a return fact *sync'd with a sales fact* + * Algorithm: Since the returns need to be in line with a prior sale, they are + *built by a call from the mk_catalog_sales() routine, and then add + *return-related information Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int mk_w_web_returns(void* row, ds_key_t index, DSDGenContext& dsdGenContext) { + int res = 0; + + decimal_t dMin, dMax; + struct W_WEB_SALES_TBL* sale = &dsdGenContext.g_w_web_sales; + struct W_WEB_RETURNS_TBL* r; + tdef* pT = getSimpleTdefsByNumber(WEB_RETURNS, dsdGenContext); + + if (row == NULL) + r = &dsdGenContext.g_w_web_returns; + else + r = static_cast(row); + + strtodec(&dMin, "1.00"); + strtodec(&dMax, "100000.00"); + + nullSet(&pT->kNullBitMap, WR_NULLS, dsdGenContext); + + /* + * Some of the information in the return is taken from the original sale + * which has been regenerated + */ + r->wr_item_sk = sale->ws_item_sk; + r->wr_order_number = sale->ws_order_number; + memcpy( + static_cast(&r->wr_pricing), + static_cast(&sale->ws_pricing), + sizeof(ds_pricing_t)); + r->wr_web_page_sk = sale->ws_web_page_sk; + + /* + * the rest of the columns are generated for this specific return + */ + /* the items cannot be returned until they are shipped; offset is handled in + * mk_join, based on sales date */ + r->wr_returned_date_sk = + mk_join(WR_RETURNED_DATE_SK, DATET, sale->ws_ship_date_sk, dsdGenContext); + r->wr_returned_time_sk = mk_join(WR_RETURNED_TIME_SK, TIME, 1, dsdGenContext); + + /* most items are returned by the people they were shipped to, but some are + * returned by other folks + */ + r->wr_refunded_customer_sk = + mk_join(WR_REFUNDED_CUSTOMER_SK, CUSTOMER, 1, dsdGenContext); + r->wr_refunded_cdemo_sk = + mk_join(WR_REFUNDED_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 1, dsdGenContext); + r->wr_refunded_hdemo_sk = + mk_join(WR_REFUNDED_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 1, dsdGenContext); + r->wr_refunded_addr_sk = + mk_join(WR_REFUNDED_ADDR_SK, CUSTOMER_ADDRESS, 1, dsdGenContext); + if (genrand_integer( + NULL, + DIST_UNIFORM, + 0, + 99, + 0, + WR_RETURNING_CUSTOMER_SK, + dsdGenContext) < WS_GIFT_PCT) { + r->wr_refunded_customer_sk = sale->ws_ship_customer_sk; + r->wr_refunded_cdemo_sk = sale->ws_ship_cdemo_sk; + r->wr_refunded_hdemo_sk = sale->ws_ship_hdemo_sk; + r->wr_refunded_addr_sk = sale->ws_ship_addr_sk; + } + r->wr_returning_customer_sk = r->wr_refunded_customer_sk; + r->wr_returning_cdemo_sk = r->wr_refunded_cdemo_sk; + r->wr_returning_hdemo_sk = r->wr_refunded_hdemo_sk; + r->wr_returning_addr_sk = r->wr_refunded_addr_sk; + + r->wr_reason_sk = mk_join(WR_REASON_SK, REASON, 1, dsdGenContext); + genrand_integer( + &r->wr_pricing.quantity, + DIST_UNIFORM, + 1, + sale->ws_pricing.quantity, + 0, + WR_PRICING, + dsdGenContext); + set_pricing(WR_PRICING, &r->wr_pricing, dsdGenContext); + + return (res); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_sales.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_sales.cpp new file mode 100644 index 0000000000000..429e2d9b690d2 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_sales.cpp @@ -0,0 +1,326 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_web_sales.h" + +#include "append_info.h" +#include "build_support.h" +#include "config.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "parallel.h" +#include "permute.h" +#include "porting.h" +#include "pricing.h" +#include "scaling.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" +#include "w_web_returns.h" + +#include + +// ds_key_t +// skipDays(int nTable, ds_key_t* pRemainder, DSDGenContext& dsdGenContext); + +/* + * the validation process requires generating a single lineitem + * so the main mk_xxx routine has been split into a master record portion + * and a detail/lineitem portion. + */ +W_WEB_SALES_TBL* mk_web_sales_master( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + decimal_t dMin, dMax; + int nGiftPct; + struct W_WEB_SALES_TBL* r; + r = &dsdGenContext.g_w_web_sales; + + if (!dsdGenContext.mk_master_web_sales_init) { + dsdGenContext.pWebSalesItemPermutation = makePermutation( + NULL, + dsdGenContext.nWebSalesItemCount = + static_cast(getIDCount(ITEM, dsdGenContext)), + WS_PERMUTATION, + dsdGenContext); + dsdGenContext.mk_master_web_sales_init = 1; + } + strtodec(&dMin, "1.00"); + strtodec(&dMax, "100000.00"); + + /*** + * some attributes reamin the same for each lineitem in an order; others are + * different for each lineitem. Since the number of lineitems per order is + * static, we can use a modulo to determine when to change the semi-static + * values + */ + + r->ws_sold_date_sk = mk_join(WS_SOLD_DATE_SK, DATET, 1, dsdGenContext); + r->ws_sold_time_sk = mk_join(WS_SOLD_TIME_SK, TIME, 1, dsdGenContext); + r->ws_bill_customer_sk = + mk_join(WS_BILL_CUSTOMER_SK, CUSTOMER, 1, dsdGenContext); + r->ws_bill_cdemo_sk = + mk_join(WS_BILL_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 1, dsdGenContext); + r->ws_bill_hdemo_sk = + mk_join(WS_BILL_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 1, dsdGenContext); + r->ws_bill_addr_sk = + mk_join(WS_BILL_ADDR_SK, CUSTOMER_ADDRESS, 1, dsdGenContext); + + /* most orders are for the ordering customers, some are not */ + genrand_integer( + &nGiftPct, DIST_UNIFORM, 0, 99, 0, WS_SHIP_CUSTOMER_SK, dsdGenContext); + if (nGiftPct > WS_GIFT_PCT) { + r->ws_ship_customer_sk = + mk_join(WS_SHIP_CUSTOMER_SK, CUSTOMER, 2, dsdGenContext); + r->ws_ship_cdemo_sk = + mk_join(WS_SHIP_CDEMO_SK, CUSTOMER_DEMOGRAPHICS, 2, dsdGenContext); + r->ws_ship_hdemo_sk = + mk_join(WS_SHIP_HDEMO_SK, HOUSEHOLD_DEMOGRAPHICS, 2, dsdGenContext); + r->ws_ship_addr_sk = + mk_join(WS_SHIP_ADDR_SK, CUSTOMER_ADDRESS, 2, dsdGenContext); + } else { + r->ws_ship_customer_sk = r->ws_bill_customer_sk; + r->ws_ship_cdemo_sk = r->ws_bill_cdemo_sk; + r->ws_ship_hdemo_sk = r->ws_bill_hdemo_sk; + r->ws_ship_addr_sk = r->ws_bill_addr_sk; + } + + r->ws_order_number = index; + genrand_integer( + &dsdGenContext.nWebSalesItemIndex, + DIST_UNIFORM, + 1, + dsdGenContext.nWebSalesItemCount, + 0, + WS_ITEM_SK, + dsdGenContext); + + return r; +} + +void mk_detail( + void* info_arr, + int bPrint, + struct W_WEB_SALES_TBL* r, + DSDGenContext& dsdGenContext) { + int nShipLag, nTemp; + tdef* pT = getSimpleTdefsByNumber(WEB_SALES, dsdGenContext); + // r = &dsdGenContext.g_w_web_sales; + + nullSet(&pT->kNullBitMap, WS_NULLS, dsdGenContext); + + /* orders are shipped some number of days after they are ordered, + * and not all lineitems ship at the same time + */ + genrand_integer( + &nShipLag, + DIST_UNIFORM, + WS_MIN_SHIP_DELAY, + WS_MAX_SHIP_DELAY, + 0, + WS_SHIP_DATE_SK, + dsdGenContext); + r->ws_ship_date_sk = r->ws_sold_date_sk + nShipLag; + + if (++dsdGenContext.nWebSalesItemIndex > dsdGenContext.nWebSalesItemCount) + dsdGenContext.nWebSalesItemIndex = 1; + r->ws_item_sk = matchSCDSK( + getPermutationEntry( + dsdGenContext.pWebSalesItemPermutation, + dsdGenContext.nWebSalesItemIndex), + r->ws_sold_date_sk, + ITEM, + dsdGenContext); + + /* the web page needs to be valid for the sale date */ + r->ws_web_page_sk = + mk_join(WS_WEB_PAGE_SK, WEB_PAGE, r->ws_sold_date_sk, dsdGenContext); + r->ws_web_site_sk = + mk_join(WS_WEB_SITE_SK, WEB_SITE, r->ws_sold_date_sk, dsdGenContext); + + r->ws_ship_mode_sk = mk_join(WS_SHIP_MODE_SK, SHIP_MODE, 1, dsdGenContext); + r->ws_warehouse_sk = mk_join(WS_WAREHOUSE_SK, WAREHOUSE, 1, dsdGenContext); + r->ws_promo_sk = mk_join(WS_PROMO_SK, PROMOTION, 1, dsdGenContext); + set_pricing(WS_PRICING, &r->ws_pricing, dsdGenContext); + + /** + * having gone to the trouble to make the sale, now let's see if it gets + * returned + */ + genrand_integer( + &nTemp, DIST_UNIFORM, 0, 99, 0, WR_IS_RETURNED, dsdGenContext); + if (nTemp < WR_RETURN_PCT) { + struct W_WEB_RETURNS_TBL w_web_returns; + struct W_WEB_RETURNS_TBL* rr = &dsdGenContext.g_w_web_returns; + mk_w_web_returns(rr, 1, dsdGenContext); + + void* info = append_info_get(info_arr, WEB_RETURNS); + append_row_start(info); + + append_key(WR_RETURNED_DATE_SK, info, rr->wr_returned_date_sk); + append_key(WR_RETURNED_TIME_SK, info, rr->wr_returned_time_sk); + append_key(WR_ITEM_SK, info, rr->wr_item_sk); + append_key(WR_REFUNDED_CUSTOMER_SK, info, rr->wr_refunded_customer_sk); + append_key(WR_REFUNDED_CDEMO_SK, info, rr->wr_refunded_cdemo_sk); + append_key(WR_REFUNDED_HDEMO_SK, info, rr->wr_refunded_hdemo_sk); + append_key(WR_REFUNDED_ADDR_SK, info, rr->wr_refunded_addr_sk); + append_key(WR_RETURNING_CUSTOMER_SK, info, rr->wr_returning_customer_sk); + append_key(WR_RETURNING_CDEMO_SK, info, rr->wr_returning_cdemo_sk); + append_key(WR_RETURNING_HDEMO_SK, info, rr->wr_returning_hdemo_sk); + append_key(WR_RETURNING_ADDR_SK, info, rr->wr_returning_addr_sk); + append_key(WR_WEB_PAGE_SK, info, rr->wr_web_page_sk); + append_key(WR_REASON_SK, info, rr->wr_reason_sk); + append_key(WR_ORDER_NUMBER, info, rr->wr_order_number); + append_integer(WR_PRICING_QUANTITY, info, rr->wr_pricing.quantity); + append_decimal(WR_PRICING_NET_PAID, info, &rr->wr_pricing.net_paid); + append_decimal(WR_PRICING_EXT_TAX, info, &rr->wr_pricing.ext_tax); + append_decimal( + WR_PRICING_NET_PAID_INC_TAX, info, &rr->wr_pricing.net_paid_inc_tax); + append_decimal(WR_PRICING_FEE, info, &rr->wr_pricing.fee); + append_decimal( + WR_PRICING_EXT_SHIP_COST, info, &rr->wr_pricing.ext_ship_cost); + append_decimal( + WR_PRICING_REFUNDED_CASH, info, &rr->wr_pricing.refunded_cash); + append_decimal( + WR_PRICING_REVERSED_CHARGE, info, &rr->wr_pricing.reversed_charge); + append_decimal(WR_PRICING_STORE_CREDIT, info, &rr->wr_pricing.store_credit); + append_decimal(WR_PRICING_NET_LOSS, info, &rr->wr_pricing.net_loss); + + append_row_end(info); + } + + void* info = append_info_get(info_arr, WEB_SALES); + append_row_start(info); + + append_key(WS_SOLD_DATE_SK, info, r->ws_sold_date_sk); + append_key(WS_SOLD_TIME_SK, info, r->ws_sold_time_sk); + append_key(WS_SHIP_DATE_SK, info, r->ws_ship_date_sk); + append_key(WS_ITEM_SK, info, r->ws_item_sk); + append_key(WS_BILL_CUSTOMER_SK, info, r->ws_bill_customer_sk); + append_key(WS_BILL_CDEMO_SK, info, r->ws_bill_cdemo_sk); + append_key(WS_BILL_HDEMO_SK, info, r->ws_bill_hdemo_sk); + append_key(WS_BILL_ADDR_SK, info, r->ws_bill_addr_sk); + append_key(WS_SHIP_CUSTOMER_SK, info, r->ws_ship_customer_sk); + append_key(WS_SHIP_CDEMO_SK, info, r->ws_ship_cdemo_sk); + append_key(WS_SHIP_HDEMO_SK, info, r->ws_ship_hdemo_sk); + append_key(WS_SHIP_ADDR_SK, info, r->ws_ship_addr_sk); + append_key(WS_WEB_PAGE_SK, info, r->ws_web_page_sk); + append_key(WS_WEB_SITE_SK, info, r->ws_web_site_sk); + append_key(WS_SHIP_MODE_SK, info, r->ws_ship_mode_sk); + append_key(WS_WAREHOUSE_SK, info, r->ws_warehouse_sk); + append_key(WS_PROMO_SK, info, r->ws_promo_sk); + append_key(WS_ORDER_NUMBER, info, r->ws_order_number); + append_integer(WS_PRICING_QUANTITY, info, r->ws_pricing.quantity); + append_decimal( + WS_PRICING_WHOLESALE_COST, info, &r->ws_pricing.wholesale_cost); + append_decimal(WS_PRICING_LIST_PRICE, info, &r->ws_pricing.list_price); + append_decimal(WS_PRICING_SALES_PRICE, info, &r->ws_pricing.sales_price); + append_decimal( + WS_PRICING_EXT_DISCOUNT_AMT, info, &r->ws_pricing.ext_discount_amt); + append_decimal( + WS_PRICING_EXT_SALES_PRICE, info, &r->ws_pricing.ext_sales_price); + append_decimal( + WS_PRICING_EXT_WHOLESALE_COST, info, &r->ws_pricing.ext_wholesale_cost); + append_decimal( + WS_PRICING_EXT_LIST_PRICE, info, &r->ws_pricing.ext_list_price); + append_decimal(WS_PRICING_EXT_TAX, info, &r->ws_pricing.ext_tax); + append_decimal(WS_PRICING_COUPON_AMT, info, &r->ws_pricing.coupon_amt); + append_decimal(WS_PRICING_EXT_SHIP_COST, info, &r->ws_pricing.ext_ship_cost); + append_decimal(WS_PRICING_NET_PAID, info, &r->ws_pricing.net_paid); + append_decimal( + WS_PRICING_NET_PAID_INC_TAX, info, &r->ws_pricing.net_paid_inc_tax); + append_decimal( + WS_PRICING_NET_PAID_INC_SHIP, info, &r->ws_pricing.net_paid_inc_ship); + append_decimal( + WS_PRICING_NET_PAID_INC_SHIP_TAX, + info, + &r->ws_pricing.net_paid_inc_ship_tax); + append_decimal(WS_PRICING_NET_PROFIT, info, &r->ws_pricing.net_profit); + + append_row_end(info); + + return; +} + +/* + * mk_web_sales + */ +int mk_w_web_sales( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int nLineitems, i; + + row_skip(WEB_RETURNS, (index - 1), dsdGenContext); + /* build the static portion of an order */ + struct W_WEB_SALES_TBL* r; + r = mk_web_sales_master(info_arr, index, dsdGenContext); + + /* set the number of lineitems and build them */ + genrand_integer( + &nLineitems, DIST_UNIFORM, 8, 16, 9, WS_ORDER_NUMBER, dsdGenContext); + for (i = 1; i <= nLineitems; i++) { + mk_detail(info_arr, 1, r, dsdGenContext); + } + + /** + * and finally return 1 since we have already printed the rows + */ + return 0; +} + +/* + * Routine: + * Purpose: + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: None + */ +int vld_web_sales( + int nTable, + ds_key_t kRow, + int* Permutation, + DSDGenContext& dsdGenContext) { + int nLineitem, nMaxLineitem, i; + + row_skip(nTable, kRow - 1, dsdGenContext); + row_skip(WEB_RETURNS, (kRow - 1), dsdGenContext); + struct W_WEB_SALES_TBL* r; + r = mk_web_sales_master(NULL, kRow, dsdGenContext); + genrand_integer( + &nMaxLineitem, DIST_UNIFORM, 8, 16, 9, WS_ORDER_NUMBER, dsdGenContext); + genrand_integer( + &nLineitem, + DIST_UNIFORM, + 1, + nMaxLineitem, + 0, + WS_PRICING_QUANTITY, + dsdGenContext); + for (i = 1; i < nLineitem; i++) { + mk_detail(NULL, 0, r, dsdGenContext); + } + mk_detail(NULL, 1, r, dsdGenContext); + + return (0); +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_site.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_site.cpp new file mode 100644 index 0000000000000..6e78ab1d6fe4c --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/w_web_site.cpp @@ -0,0 +1,313 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "w_web_site.h" + +#include "address.h" +#include "append_info.h" +#include "build_support.h" +#include "columns.h" +#include "config.h" +#include "constants.h" +#include "genrand.h" +#include "misc.h" +#include "nulls.h" +#include "porting.h" +#include "scaling.h" +#include "scd.h" +#include "tables.h" +#include "tdefs.h" + +#include + +static struct W_WEB_SITE_TBL g_OldValues; + +/* + * Routine: mk_web_site() + * Purpose: populate the web_site table + * Algorithm: + * Data Structures: + * + * Params: + * Returns: + * Called By: + * Calls: + * Assumptions: + * Side Effects: + * TODO: + */ +int mk_w_web_site( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext) { + int32_t nFieldChangeFlags, bFirstRecord = 0; + decimal_t dMinTaxPercentage, dMaxTaxPercentage; + + /* begin locals declarations */ + char szTemp[16], *sName1 = nullptr, *sName2 = nullptr; + struct W_WEB_SITE_TBL *r, *rOldValues = &g_OldValues; + tdef* pT = getSimpleTdefsByNumber(WEB_SITE, dsdGenContext); + + r = &dsdGenContext.g_w_web_site; + + snprintf( + szTemp, + sizeof(szTemp), + "%d-%d-%d", + CURRENT_YEAR, + CURRENT_MONTH, + CURRENT_DAY); + strcpy(r->web_class, "Unknown"); + strtodec(&dMinTaxPercentage, WEB_MIN_TAX_PERCENTAGE); + strtodec(&dMaxTaxPercentage, WEB_MAX_TAX_PERCENTAGE); + + nullSet(&pT->kNullBitMap, WEB_NULLS, dsdGenContext); + r->web_site_sk = index; + + /* if we have generated the required history for this business key and + * generate a new one then reset associate fields (e.g., rec_start_date + * minimums) + */ + if (setSCDKeys( + WEB_SITE_ID, + index, + r->web_site_id, + &r->web_rec_start_date_id, + &r->web_rec_end_date_id, + dsdGenContext)) { + r->web_open_date = mk_join(WEB_OPEN_DATE, DATET, index, dsdGenContext); + r->web_close_date = mk_join(WEB_CLOSE_DATE, DATET, index, dsdGenContext); + if (r->web_close_date > r->web_rec_end_date_id) + r->web_close_date = -1; + snprintf( + r->web_name, + sizeof(r->web_name), + "site_%d", + static_cast(index / 6)); + bFirstRecord = 1; + } + + /* + * this is where we select the random number that controls if a field + * changes from one record to the next. + */ + nFieldChangeFlags = next_random(WEB_SCD, dsdGenContext); + + /* the rest of the record in a history-keeping dimension can either be a new + * data value or not; use a random number and its bit pattern to determine + * which fields to replace and which to retain + */ + pick_distribution(&sName1, "first_names", 1, 1, WEB_MANAGER, dsdGenContext); + pick_distribution(&sName2, "last_names", 1, 1, WEB_MANAGER, dsdGenContext); + snprintf(r->web_manager, sizeof(r->web_manager), "%s %s", sName1, sName2); + changeSCD( + SCD_CHAR, + &r->web_manager, + &rOldValues->web_manager, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->web_market_id, DIST_UNIFORM, 1, 6, 0, WEB_MARKET_ID, dsdGenContext); + changeSCD( + SCD_INT, + &r->web_market_id, + &rOldValues->web_market_id, + &nFieldChangeFlags, + bFirstRecord); + + gen_text( + r->web_market_class, + 20, + RS_WEB_MARKET_CLASS, + WEB_MARKET_CLASS, + dsdGenContext); + changeSCD( + SCD_CHAR, + &r->web_market_class, + &rOldValues->web_market_class, + &nFieldChangeFlags, + bFirstRecord); + + gen_text( + r->web_market_desc, + 20, + RS_WEB_MARKET_DESC, + WEB_MARKET_DESC, + dsdGenContext); + changeSCD( + SCD_CHAR, + &r->web_market_desc, + &rOldValues->web_market_desc, + &nFieldChangeFlags, + bFirstRecord); + + pick_distribution( + &sName1, "first_names", 1, 1, WEB_MARKET_MANAGER, dsdGenContext); + pick_distribution( + &sName2, "last_names", 1, 1, WEB_MARKET_MANAGER, dsdGenContext); + snprintf( + r->web_market_manager, + sizeof(r->web_market_manager), + "%s %s", + sName1, + sName2); + changeSCD( + SCD_CHAR, + &r->web_market_manager, + &rOldValues->web_market_manager, + &nFieldChangeFlags, + bFirstRecord); + + genrand_integer( + &r->web_company_id, DIST_UNIFORM, 1, 6, 0, WEB_COMPANY_ID, dsdGenContext); + changeSCD( + SCD_INT, + &r->web_company_id, + &rOldValues->web_company_id, + &nFieldChangeFlags, + bFirstRecord); + + mk_word( + r->web_company_name, + "syllables", + r->web_company_id, + RS_WEB_COMPANY_NAME, + WEB_COMPANY_NAME, + dsdGenContext); + changeSCD( + SCD_CHAR, + &r->web_company_name, + &rOldValues->web_company_name, + &nFieldChangeFlags, + bFirstRecord); + + mk_address(&r->web_address, WEB_ADDRESS, dsdGenContext); + changeSCD( + SCD_PTR, + &r->web_address.city, + &rOldValues->web_address.city, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->web_address.county, + &rOldValues->web_address.county, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_INT, + &r->web_address.gmt_offset, + &rOldValues->web_address.gmt_offset, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->web_address.state, + &rOldValues->web_address.state, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->web_address.street_type, + &rOldValues->web_address.street_type, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->web_address.street_name1, + &rOldValues->web_address.street_name1, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_PTR, + &r->web_address.street_name2, + &rOldValues->web_address.street_name2, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_INT, + &r->web_address.street_num, + &rOldValues->web_address.street_num, + &nFieldChangeFlags, + bFirstRecord); + changeSCD( + SCD_INT, + &r->web_address.zip, + &rOldValues->web_address.zip, + &nFieldChangeFlags, + bFirstRecord); + + genrand_decimal( + &r->web_tax_percentage, + DIST_UNIFORM, + &dMinTaxPercentage, + &dMaxTaxPercentage, + NULL, + WEB_TAX_PERCENTAGE, + dsdGenContext); + changeSCD( + SCD_DEC, + &r->web_tax_percentage, + &rOldValues->web_tax_percentage, + &nFieldChangeFlags, + bFirstRecord); + + void* info = append_info_get(info_arr, WEB_SITE); + append_row_start(info); + + char szStreetName[128]; + + append_key(WEB_SITE_SK, info, r->web_site_sk); + append_varchar(WEB_SITE_ID, info, &r->web_site_id[0]); + append_date( + WEB_REC_START_DATE_ID, info, static_cast(r->web_rec_start_date_id)); + append_date( + WEB_REC_END_DATE_ID, info, static_cast(r->web_rec_end_date_id)); + append_varchar(WEB_NAME, info, &r->web_name[0]); + append_key(WEB_OPEN_DATE, info, r->web_open_date); + append_key(WEB_CLOSE_DATE, info, r->web_close_date); + append_varchar(WEB_CLASS, info, &r->web_class[0]); + append_varchar(WEB_MANAGER, info, &r->web_manager[0]); + append_integer(WEB_MARKET_ID, info, r->web_market_id); + append_varchar(WEB_MARKET_CLASS, info, &r->web_market_class[0]); + append_varchar(WEB_MARKET_DESC, info, &r->web_market_desc[0]); + append_varchar(WEB_MARKET_MANAGER, info, &r->web_market_manager[0]); + append_integer(WEB_COMPANY_ID, info, r->web_company_id); + append_varchar(WEB_COMPANY_NAME, info, &r->web_company_name[0]); + append_varchar( + WEB_ADDRESS_STREET_NUM, info, std::to_string(r->web_address.street_num)); + if (r->web_address.street_name2) { + snprintf( + szStreetName, + sizeof(szStreetName), + "%s %s", + r->web_address.street_name1, + r->web_address.street_name2); + append_varchar(WEB_ADDRESS_STREET_NAME1, info, szStreetName); + } else + append_varchar(WEB_ADDRESS_STREET_NAME1, info, r->web_address.street_name1); + append_varchar(WEB_ADDRESS_STREET_TYPE, info, r->web_address.street_type); + append_varchar(WEB_ADDRESS_SUITE_NUM, info, r->web_address.suite_num); + append_varchar(WEB_ADDRESS_CITY, info, r->web_address.city); + append_varchar(WEB_ADDRESS_COUNTY, info, r->web_address.county); + append_varchar(WEB_ADDRESS_STATE, info, r->web_address.state); + snprintf(szStreetName, sizeof(szStreetName), "%05d", r->web_address.zip); + append_varchar(WEB_ADDRESS_ZIP, info, szStreetName); + append_varchar(WEB_ADDRESS_COUNTRY, info, r->web_address.country); + append_integer_decimal( + WEB_ADDRESS_GMT_OFFSET, info, r->web_address.gmt_offset); + append_decimal(WEB_TAX_PERCENTAGE, info, &r->web_tax_percentage); + + append_row_end(info); + + return 0; +} diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/StringBuffer.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/StringBuffer.h new file mode 100644 index 0000000000000..c8a8b8c6fe577 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/StringBuffer.h @@ -0,0 +1,30 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef STRING_BUFFER_H +#define STRING_BUFFER_H + +#define SB_INIT 0x01 + +typedef struct STRING_BUFFER_T { + int nFlags; + int nBytesAllocated; + int nBytesUsed; + int nIncrement; + char* pText; +} StringBuffer_t; + +StringBuffer_t* InitBuffer(int nSize, int nIncrement); +int AddBuffer(StringBuffer_t* pBuf, char* pStr); +int ResetBuffer(StringBuffer_t* pBuf); +char* GetBuffer(StringBuffer_t* pBuf); +void FreeBuffer(StringBuffer_t* pBuf); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/address.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/address.h new file mode 100644 index 0000000000000..ffba8b6a2cd54 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/address.h @@ -0,0 +1,46 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef DS_ADDRESS_H +#define DS_ADDRESS_H + +#include "constants.h" +#include "dist.h" + +#define DS_ADDR_SUITE_NUM 0 +#define DS_ADDR_STREET_NUM 1 +#define DS_ADDR_STREET_NAME1 2 +#define DS_ADDR_STREET_NAME2 3 +#define DS_ADDR_STREET_TYPE 4 +#define DS_ADDR_CITY 5 +#define DS_ADDR_COUNTY 6 +#define DS_ADDR_STATE 7 +#define DS_ADDR_COUNTRY 8 +#define DS_ADDR_ZIP 9 +#define DS_ADDR_PLUS4 10 +#define DS_ADDR_GMT_OFFSET 11 + +int mk_address(ds_addr_t* pDest, int nColumn, DSDGenContext& dsdGenContext); +int mk_streetnumber(int nTable, int* dest, DSDGenContext& dsdGenContext); +int mk_suitenumber(int nTable, char* dest, DSDGenContext& dsdGenContext); +int mk_streetname(int nTable, char* dest); +int mk_city(int nTable, char** dest, DSDGenContext& dsdGenContext); +int city_hash(int nTable, char* name); +int mk_zipcode( + int nTable, + char* dest, + int nRegion, + char* city, + DSDGenContext& dsdGenContext); +// void printAddressPart(FILE *fp, ds_addr_t *pAddr, int nAddressPart); +void resetCountCount(void); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/append_info.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/append_info.h new file mode 100644 index 0000000000000..be33b5da739bc --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/append_info.h @@ -0,0 +1,44 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef R_APPEND_H +#define R_APPEND_H + +#include +#include + +#include "decimal.h" + +typedef void* append_info; + +append_info* append_info_get(void* info_list, int table_id); + +void append_row_start(append_info info); +void append_row_end(append_info info); + +void append_varchar( + int32_t column, + append_info info, + const char* value, + bool fillEmptyStringAsNull = true); +void append_varchar( + int32_t column, + append_info info, + std::string value, + bool fillEmptyStringAsNull = true); +void append_key(int32_t column, append_info info, int64_t value); +void append_date(int32_t column, append_info info, int64_t value); +void append_integer(int32_t column, append_info info, int32_t value); +void append_decimal(int32_t column, append_info info, decimal_t* val); +void append_boolean(int32_t column, append_info info, int32_t val); +void append_integer_decimal(int32_t column, append_info info, int32_t val); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/build_support.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/build_support.h new file mode 100644 index 0000000000000..316b5ce65188f --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/build_support.h @@ -0,0 +1,88 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef BUILD_SUPPORT_H +#define BUILD_SUPPORT_H + +#include "columns.h" +#include "date.h" +#include "decimal.h" +#include "dist.h" +#include "pricing.h" + +void bitmap_to_dist( + void* pDest, + const char* distname, + ds_key_t* modulus, + int vset, + int stream, + DSDGenContext& dsdGenContext); +void dist_to_bitmap( + int* pDest, + const char* szDistName, + int nValue, + int nWeight, + int nStream); +void random_to_bitmap( + int* pDest, + int nDist, + int nMin, + int nMax, + int nMean, + int nStream); +int city_hash(int nTable, char* city); +void hierarchy_item( + int h_level, + ds_key_t* id, + char** name, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); +ds_key_t mk_join( + int from_tbl, + int to_tbl, + ds_key_t ref_key, + DSDGenContext& dsdGenContext); +ds_key_t getCatalogNumberFromPage(ds_key_t kPageNumber); +void mk_word( + char* dest, + const char* syl_set, + ds_key_t src, + int char_cnt, + int col, + DSDGenContext& dsdGenContext); +int set_locale(int nRegion, decimal_t* longitude, decimal_t* latitude); +int adj_time( + ds_key_t* res_date, + ds_key_t* res_time, + ds_key_t base_date, + ds_key_t base_time, + ds_key_t offset_key, + int tabid); +void mk_bkey(char* szDest, ds_key_t kPrimary, int nStream); +int embed_string( + char* szDest, + const char* szDist, + int nValue, + int nWeight, + int nStream, + DSDGenContext& dsdGenContext); +int mk_companyname( + char* dest, + int nTable, + int nCompany, + DSDGenContext& dsdGenContext); +void setUpdateDateRange( + int nTable, + date_t* pMinDate, + date_t* pMaxDate, + DSDGenContext& dsdGenContext); + +#endif /* BUILD_SUPPORT_H */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/columns.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/columns.h new file mode 100644 index 0000000000000..8e6fc0ed4f8d7 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/columns.h @@ -0,0 +1,942 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +/* + * THIS IS A GENERATED FILE + * SEE COLUMNS.LIST + */ +#ifndef COLUMNS_H +#define COLUMNS_H +#define CALL_CENTER_START 1 +#define CC_CALL_CENTER_SK 1 +#define CC_CALL_CENTER_ID 2 +#define CC_REC_START_DATE_ID 3 +#define CC_REC_END_DATE_ID 4 +#define CC_CLOSED_DATE_ID 5 +#define CC_OPEN_DATE_ID 6 +#define CC_NAME 7 +#define CC_CLASS 8 +#define CC_EMPLOYEES 9 +#define CC_SQ_FT 10 +#define CC_HOURS 11 +#define CC_MANAGER 12 +#define CC_MARKET_ID 13 +#define CC_MARKET_CLASS 14 +#define CC_MARKET_DESC 15 +#define CC_MARKET_MANAGER 16 +#define CC_DIVISION 17 +#define CC_DIVISION_NAME 18 +#define CC_COMPANY 19 +#define CC_COMPANY_NAME 20 +#define CC_STREET_NUMBER 21 +#define CC_STREET_NAME 22 +#define CC_STREET_TYPE 23 +#define CC_SUITE_NUMBER 24 +#define CC_CITY 25 +#define CC_COUNTY 26 +#define CC_STATE 27 +#define CC_ZIP 28 +#define CC_COUNTRY 29 +#define CC_GMT_OFFSET 30 +#define CC_ADDRESS 31 +#define CC_TAX_PERCENTAGE 32 +#define CC_SCD 33 +#define CC_NULLS 34 +#define CALL_CENTER_END 34 +#define CATALOG_PAGE_START 35 +#define CP_CATALOG_PAGE_SK 35 +#define CP_CATALOG_PAGE_ID 36 +#define CP_START_DATE_ID 37 +#define CP_END_DATE_ID 38 +#define CP_PROMO_ID 39 +#define CP_DEPARTMENT 40 +#define CP_CATALOG_NUMBER 41 +#define CP_CATALOG_PAGE_NUMBER 42 +#define CP_DESCRIPTION 43 +#define CP_TYPE 44 +#define CP_NULLS 45 +#define CATALOG_PAGE_END 45 +#define CATALOG_RETURNS_START 46 +#define CR_RETURNED_DATE_SK 46 +#define CR_RETURNED_TIME_SK 47 +#define CR_ITEM_SK 48 +#define CR_REFUNDED_CUSTOMER_SK 49 +#define CR_REFUNDED_CDEMO_SK 50 +#define CR_REFUNDED_HDEMO_SK 51 +#define CR_REFUNDED_ADDR_SK 52 +#define CR_RETURNING_CUSTOMER_SK 53 +#define CR_RETURNING_CDEMO_SK 54 +#define CR_RETURNING_HDEMO_SK 55 +#define CR_RETURNING_ADDR_SK 56 +#define CR_CALL_CENTER_SK 57 +#define CR_CATALOG_PAGE_SK 58 +#define CR_SHIP_MODE_SK 59 +#define CR_WAREHOUSE_SK 60 +#define CR_REASON_SK 61 +#define CR_ORDER_NUMBER 62 +#define CR_PRICING_QUANTITY 63 +#define CR_PRICING_NET_PAID 64 +#define CR_PRICING_EXT_TAX 65 +#define CR_PRICING_NET_PAID_INC_TAX 66 +#define CR_PRICING_FEE 67 +#define CR_PRICING_EXT_SHIP_COST 68 +#define CR_PRICING_REFUNDED_CASH 69 +#define CR_PRICING_REVERSED_CHARGE 70 +#define CR_PRICING_STORE_CREDIT 71 +#define CR_PRICING_NET_LOSS 72 +#define CR_NULLS 73 +#define CR_PRICING 74 +#define CATALOG_RETURNS_END 74 +#define CATALOG_SALES_START 75 +#define CS_SOLD_DATE_SK 75 +#define CS_SOLD_TIME_SK 76 +#define CS_SHIP_DATE_SK 77 +#define CS_BILL_CUSTOMER_SK 78 +#define CS_BILL_CDEMO_SK 79 +#define CS_BILL_HDEMO_SK 80 +#define CS_BILL_ADDR_SK 81 +#define CS_SHIP_CUSTOMER_SK 82 +#define CS_SHIP_CDEMO_SK 83 +#define CS_SHIP_HDEMO_SK 84 +#define CS_SHIP_ADDR_SK 85 +#define CS_CALL_CENTER_SK 86 +#define CS_CATALOG_PAGE_SK 87 +#define CS_SHIP_MODE_SK 88 +#define CS_WAREHOUSE_SK 89 +#define CS_SOLD_ITEM_SK 90 +#define CS_PROMO_SK 91 +#define CS_ORDER_NUMBER 92 +#define CS_PRICING_QUANTITY 93 +#define CS_PRICING_WHOLESALE_COST 94 +#define CS_PRICING_LIST_PRICE 95 +#define CS_PRICING_SALES_PRICE 96 +#define CS_PRICING_COUPON_AMT 97 +#define CS_PRICING_EXT_SALES_PRICE 98 +#define CS_PRICING_EXT_DISCOUNT_AMOUNT 99 +#define CS_PRICING_EXT_WHOLESALE_COST 100 +#define CS_PRICING_EXT_LIST_PRICE 101 +#define CS_PRICING_EXT_TAX 102 +#define CS_PRICING_EXT_SHIP_COST 103 +#define CS_PRICING_NET_PAID 104 +#define CS_PRICING_NET_PAID_INC_TAX 105 +#define CS_PRICING_NET_PAID_INC_SHIP 106 +#define CS_PRICING_NET_PAID_INC_SHIP_TAX 107 +#define CS_PRICING_NET_PROFIT 108 +#define CS_PRICING 109 +#define CS_PERMUTE 110 +#define CS_NULLS 111 +#define CR_IS_RETURNED 112 +#define CS_PERMUTATION 113 +#define CATALOG_SALES_END 113 +#define CUSTOMER_START 114 +#define C_CUSTOMER_SK 114 +#define C_CUSTOMER_ID 115 +#define C_CURRENT_CDEMO_SK 116 +#define C_CURRENT_HDEMO_SK 117 +#define C_CURRENT_ADDR_SK 118 +#define C_FIRST_SHIPTO_DATE_ID 119 +#define C_FIRST_SALES_DATE_ID 120 +#define C_SALUTATION 121 +#define C_FIRST_NAME 122 +#define C_LAST_NAME 123 +#define C_PREFERRED_CUST_FLAG 124 +#define C_BIRTH_DAY 125 +#define C_BIRTH_MONTH 126 +#define C_BIRTH_YEAR 127 +#define C_BIRTH_COUNTRY 128 +#define C_LOGIN 129 +#define C_EMAIL_ADDRESS 130 +#define C_LAST_REVIEW_DATE 131 +#define C_NULLS 132 +#define CUSTOMER_END 132 +#define CUSTOMER_ADDRESS_START 133 +#define CA_ADDRESS_SK 133 +#define CA_ADDRESS_ID 134 +#define CA_ADDRESS_STREET_NUM 135 +#define CA_ADDRESS_STREET_NAME1 136 +#define CA_ADDRESS_STREET_TYPE 137 +#define CA_ADDRESS_SUITE_NUM 138 +#define CA_ADDRESS_CITY 139 +#define CA_ADDRESS_COUNTY 140 +#define CA_ADDRESS_STATE 141 +#define CA_ADDRESS_ZIP 142 +#define CA_ADDRESS_COUNTRY 143 +#define CA_ADDRESS_GMT_OFFSET 144 +#define CA_LOCATION_TYPE 145 +#define CA_NULLS 146 +#define CA_ADDRESS 147 +#define CA_ADDRESS_STREET_NAME2 148 +#define CUSTOMER_ADDRESS_END 148 +#define CUSTOMER_DEMOGRAPHICS_START 149 +#define CD_DEMO_SK 149 +#define CD_GENDER 150 +#define CD_MARITAL_STATUS 151 +#define CD_EDUCATION_STATUS 152 +#define CD_PURCHASE_ESTIMATE 153 +#define CD_CREDIT_RATING 154 +#define CD_DEP_COUNT 155 +#define CD_DEP_EMPLOYED_COUNT 156 +#define CD_DEP_COLLEGE_COUNT 157 +#define CD_NULLS 158 +#define CUSTOMER_DEMOGRAPHICS_END 158 +#define DATE_START 159 +#define D_DATE_SK 159 +#define D_DATE_ID 160 +#define D_DATE 161 +#define D_MONTH_SEQ 162 +#define D_WEEK_SEQ 163 +#define D_QUARTER_SEQ 164 +#define D_YEAR 165 +#define D_DOW 166 +#define D_MOY 167 +#define D_DOM 168 +#define D_QOY 169 +#define D_FY_YEAR 170 +#define D_FY_QUARTER_SEQ 171 +#define D_FY_WEEK_SEQ 172 +#define D_DAY_NAME 173 +#define D_QUARTER_NAME 174 +#define D_HOLIDAY 175 +#define D_WEEKEND 176 +#define D_FOLLOWING_HOLIDAY 177 +#define D_FIRST_DOM 178 +#define D_LAST_DOM 179 +#define D_SAME_DAY_LY 180 +#define D_SAME_DAY_LQ 181 +#define D_CURRENT_DAY 182 +#define D_CURRENT_WEEK 183 +#define D_CURRENT_MONTH 184 +#define D_CURRENT_QUARTER 185 +#define D_CURRENT_YEAR 186 +#define D_NULLS 187 +#define DATE_END 187 +#define HOUSEHOLD_DEMOGRAPHICS_START 188 +#define HD_DEMO_SK 188 +#define HD_INCOME_BAND_ID 189 +#define HD_BUY_POTENTIAL 190 +#define HD_DEP_COUNT 191 +#define HD_VEHICLE_COUNT 192 +#define HD_NULLS 193 +#define HOUSEHOLD_DEMOGRAPHICS_END 193 +#define INCOME_BAND_START 194 +#define IB_INCOME_BAND_ID 194 +#define IB_LOWER_BOUND 195 +#define IB_UPPER_BOUND 196 +#define IB_NULLS 197 +#define INCOME_BAND_END 197 +#define INVENTORY_START 198 +#define INV_DATE_SK 198 +#define INV_ITEM_SK 199 +#define INV_WAREHOUSE_SK 200 +#define INV_QUANTITY_ON_HAND 201 +#define INV_NULLS 202 +#define INVENTORY_END 202 +#define ITEM_START 203 +#define I_ITEM_SK 203 +#define I_ITEM_ID 204 +#define I_REC_START_DATE_ID 205 +#define I_REC_END_DATE_ID 206 +#define I_ITEM_DESC 207 +#define I_CURRENT_PRICE 208 +#define I_WHOLESALE_COST 209 +#define I_BRAND_ID 210 +#define I_BRAND 211 +#define I_CLASS_ID 212 +#define I_CLASS 213 +#define I_CATEGORY_ID 214 +#define I_CATEGORY 215 +#define I_MANUFACT_ID 216 +#define I_MANUFACT 217 +#define I_SIZE 218 +#define I_FORMULATION 219 +#define I_COLOR 220 +#define I_UNITS 221 +#define I_CONTAINER 222 +#define I_MANAGER_ID 223 +#define I_PRODUCT_NAME 224 +#define I_NULLS 225 +#define I_SCD 226 +#define I_PROMO_SK 227 +#define ITEM_END 227 +#define PROMOTION_START 228 +#define P_PROMO_SK 228 +#define P_PROMO_ID 229 +#define P_START_DATE_ID 230 +#define P_END_DATE_ID 231 +#define P_ITEM_SK 232 +#define P_COST 233 +#define P_RESPONSE_TARGET 234 +#define P_PROMO_NAME 235 +#define P_CHANNEL_DMAIL 236 +#define P_CHANNEL_EMAIL 237 +#define P_CHANNEL_CATALOG 238 +#define P_CHANNEL_TV 239 +#define P_CHANNEL_RADIO 240 +#define P_CHANNEL_PRESS 241 +#define P_CHANNEL_EVENT 242 +#define P_CHANNEL_DEMO 243 +#define P_CHANNEL_DETAILS 244 +#define P_PURPOSE 245 +#define P_DISCOUNT_ACTIVE 246 +#define P_NULLS 247 +#define PROMOTION_END 247 +#define REASON_START 248 +#define R_REASON_SK 248 +#define R_REASON_ID 249 +#define R_REASON_DESCRIPTION 250 +#define R_NULLS 251 +#define REASON_END 251 +#define SHIP_MODE_START 252 +#define SM_SHIP_MODE_SK 252 +#define SM_SHIP_MODE_ID 253 +#define SM_TYPE 254 +#define SM_CODE 255 +#define SM_CONTRACT 256 +#define SM_CARRIER 257 +#define SM_NULLS 258 +#define SHIP_MODE_END 258 +#define STORE_START 259 +#define W_STORE_SK 259 +#define W_STORE_ID 260 +#define W_STORE_REC_START_DATE_ID 261 +#define W_STORE_REC_END_DATE_ID 262 +#define W_STORE_CLOSED_DATE_ID 263 +#define W_STORE_NAME 264 +#define W_STORE_EMPLOYEES 265 +#define W_STORE_FLOOR_SPACE 266 +#define W_STORE_HOURS 267 +#define W_STORE_MANAGER 268 +#define W_STORE_MARKET_ID 269 +#define W_STORE_TAX_PERCENTAGE 270 +#define W_STORE_GEOGRAPHY_CLASS 271 +#define W_STORE_MARKET_DESC 272 +#define W_STORE_MARKET_MANAGER 273 +#define W_STORE_DIVISION_ID 274 +#define W_STORE_DIVISION_NAME 275 +#define W_STORE_COMPANY_ID 276 +#define W_STORE_COMPANY_NAME 277 +#define W_STORE_ADDRESS_STREET_NUM 278 +#define W_STORE_ADDRESS_STREET_NAME1 279 +#define W_STORE_ADDRESS_STREET_TYPE 280 +#define W_STORE_ADDRESS_SUITE_NUM 281 +#define W_STORE_ADDRESS_CITY 282 +#define W_STORE_ADDRESS_COUNTY 283 +#define W_STORE_ADDRESS_STATE 284 +#define W_STORE_ADDRESS_ZIP 285 +#define W_STORE_ADDRESS_COUNTRY 286 +#define W_STORE_ADDRESS_GMT_OFFSET 287 +#define W_STORE_NULLS 288 +#define W_STORE_TYPE 289 +#define W_STORE_SCD 290 +#define W_STORE_ADDRESS 291 +#define STORE_END 291 +#define STORE_RETURNS_START 292 +#define SR_RETURNED_DATE_SK 292 +#define SR_RETURNED_TIME_SK 293 +#define SR_ITEM_SK 294 +#define SR_CUSTOMER_SK 295 +#define SR_CDEMO_SK 296 +#define SR_HDEMO_SK 297 +#define SR_ADDR_SK 298 +#define SR_STORE_SK 299 +#define SR_REASON_SK 300 +#define SR_TICKET_NUMBER 301 +#define SR_PRICING_QUANTITY 302 +#define SR_PRICING_NET_PAID 303 +#define SR_PRICING_EXT_TAX 304 +#define SR_PRICING_NET_PAID_INC_TAX 305 +#define SR_PRICING_FEE 306 +#define SR_PRICING_EXT_SHIP_COST 307 +#define SR_PRICING_REFUNDED_CASH 308 +#define SR_PRICING_REVERSED_CHARGE 309 +#define SR_PRICING_STORE_CREDIT 310 +#define SR_PRICING_NET_LOSS 311 +#define SR_PRICING 312 +#define SR_NULLS 313 +#define STORE_RETURNS_END 313 +#define STORE_SALES_START 314 +#define SS_SOLD_DATE_SK 314 +#define SS_SOLD_TIME_SK 315 +#define SS_SOLD_ITEM_SK 316 +#define SS_SOLD_CUSTOMER_SK 317 +#define SS_SOLD_CDEMO_SK 318 +#define SS_SOLD_HDEMO_SK 319 +#define SS_SOLD_ADDR_SK 320 +#define SS_SOLD_STORE_SK 321 +#define SS_SOLD_PROMO_SK 322 +#define SS_TICKET_NUMBER 323 +#define SS_PRICING_QUANTITY 324 +#define SS_PRICING_WHOLESALE_COST 325 +#define SS_PRICING_LIST_PRICE 326 +#define SS_PRICING_SALES_PRICE 327 +#define SS_PRICING_COUPON_AMT 328 +#define SS_PRICING_EXT_SALES_PRICE 329 +#define SS_PRICING_EXT_WHOLESALE_COST 330 +#define SS_PRICING_EXT_LIST_PRICE 331 +#define SS_PRICING_EXT_TAX 332 +#define SS_PRICING_NET_PAID 333 +#define SS_PRICING_NET_PAID_INC_TAX 334 +#define SS_PRICING_NET_PROFIT 335 +#define SR_IS_RETURNED 336 +#define SS_PRICING 337 +#define SS_NULLS 338 +#define SS_PERMUTATION 339 +#define STORE_SALES_END 339 +#define TIME_START 340 +#define T_TIME_SK 340 +#define T_TIME_ID 341 +#define T_TIME 342 +#define T_HOUR 343 +#define T_MINUTE 344 +#define T_SECOND 345 +#define T_AM_PM 346 +#define T_SHIFT 347 +#define T_SUB_SHIFT 348 +#define T_MEAL_TIME 349 +#define T_NULLS 350 +#define TIME_END 350 +#define WAREHOUSE_START 351 +#define W_WAREHOUSE_SK 351 +#define W_WAREHOUSE_ID 352 +#define W_WAREHOUSE_NAME 353 +#define W_WAREHOUSE_SQ_FT 354 +#define W_ADDRESS_STREET_NUM 355 +#define W_ADDRESS_STREET_NAME1 356 +#define W_ADDRESS_STREET_TYPE 357 +#define W_ADDRESS_SUITE_NUM 358 +#define W_ADDRESS_CITY 359 +#define W_ADDRESS_COUNTY 360 +#define W_ADDRESS_STATE 361 +#define W_ADDRESS_ZIP 362 +#define W_ADDRESS_COUNTRY 363 +#define W_ADDRESS_GMT_OFFSET 364 +#define W_NULLS 365 +#define W_WAREHOUSE_ADDRESS 366 +#define WAREHOUSE_END 366 +#define WEB_PAGE_START 367 +#define WP_PAGE_SK 367 +#define WP_PAGE_ID 368 +#define WP_REC_START_DATE_ID 369 +#define WP_REC_END_DATE_ID 370 +#define WP_CREATION_DATE_SK 371 +#define WP_ACCESS_DATE_SK 372 +#define WP_AUTOGEN_FLAG 373 +#define WP_CUSTOMER_SK 374 +#define WP_URL 375 +#define WP_TYPE 376 +#define WP_CHAR_COUNT 377 +#define WP_LINK_COUNT 378 +#define WP_IMAGE_COUNT 379 +#define WP_MAX_AD_COUNT 380 +#define WP_NULLS 381 +#define WP_SCD 382 +#define WEB_PAGE_END 382 +#define WEB_RETURNS_START 383 +#define WR_RETURNED_DATE_SK 383 +#define WR_RETURNED_TIME_SK 384 +#define WR_ITEM_SK 385 +#define WR_REFUNDED_CUSTOMER_SK 386 +#define WR_REFUNDED_CDEMO_SK 387 +#define WR_REFUNDED_HDEMO_SK 388 +#define WR_REFUNDED_ADDR_SK 389 +#define WR_RETURNING_CUSTOMER_SK 390 +#define WR_RETURNING_CDEMO_SK 391 +#define WR_RETURNING_HDEMO_SK 392 +#define WR_RETURNING_ADDR_SK 393 +#define WR_WEB_PAGE_SK 394 +#define WR_REASON_SK 395 +#define WR_ORDER_NUMBER 396 +#define WR_PRICING_QUANTITY 397 +#define WR_PRICING_NET_PAID 398 +#define WR_PRICING_EXT_TAX 399 +#define WR_PRICING_NET_PAID_INC_TAX 400 +#define WR_PRICING_FEE 401 +#define WR_PRICING_EXT_SHIP_COST 402 +#define WR_PRICING_REFUNDED_CASH 403 +#define WR_PRICING_REVERSED_CHARGE 404 +#define WR_PRICING_STORE_CREDIT 405 +#define WR_PRICING_NET_LOSS 406 +#define WR_PRICING 407 +#define WR_NULLS 408 +#define WEB_RETURNS_END 408 +#define WEB_SALES_START 409 +#define WS_SOLD_DATE_SK 409 +#define WS_SOLD_TIME_SK 410 +#define WS_SHIP_DATE_SK 411 +#define WS_ITEM_SK 412 +#define WS_BILL_CUSTOMER_SK 413 +#define WS_BILL_CDEMO_SK 414 +#define WS_BILL_HDEMO_SK 415 +#define WS_BILL_ADDR_SK 416 +#define WS_SHIP_CUSTOMER_SK 417 +#define WS_SHIP_CDEMO_SK 418 +#define WS_SHIP_HDEMO_SK 419 +#define WS_SHIP_ADDR_SK 420 +#define WS_WEB_PAGE_SK 421 +#define WS_WEB_SITE_SK 422 +#define WS_SHIP_MODE_SK 423 +#define WS_WAREHOUSE_SK 424 +#define WS_PROMO_SK 425 +#define WS_ORDER_NUMBER 426 +#define WS_PRICING_QUANTITY 427 +#define WS_PRICING_WHOLESALE_COST 428 +#define WS_PRICING_LIST_PRICE 429 +#define WS_PRICING_SALES_PRICE 430 +#define WS_PRICING_EXT_DISCOUNT_AMT 431 +#define WS_PRICING_EXT_SALES_PRICE 432 +#define WS_PRICING_EXT_WHOLESALE_COST 433 +#define WS_PRICING_EXT_LIST_PRICE 434 +#define WS_PRICING_EXT_TAX 435 +#define WS_PRICING_COUPON_AMT 436 +#define WS_PRICING_EXT_SHIP_COST 437 +#define WS_PRICING_NET_PAID 438 +#define WS_PRICING_NET_PAID_INC_TAX 439 +#define WS_PRICING_NET_PAID_INC_SHIP 440 +#define WS_PRICING_NET_PAID_INC_SHIP_TAX 441 +#define WS_PRICING_NET_PROFIT 442 +#define WS_PRICING 443 +#define WS_NULLS 444 +#define WR_IS_RETURNED 445 +#define WS_PERMUTATION 446 +#define WEB_SALES_END 446 +#define WEB_SITE_START 447 +#define WEB_SITE_SK 447 +#define WEB_SITE_ID 448 +#define WEB_REC_START_DATE_ID 449 +#define WEB_REC_END_DATE_ID 450 +#define WEB_NAME 451 +#define WEB_OPEN_DATE 452 +#define WEB_CLOSE_DATE 453 +#define WEB_CLASS 454 +#define WEB_MANAGER 455 +#define WEB_MARKET_ID 456 +#define WEB_MARKET_CLASS 457 +#define WEB_MARKET_DESC 458 +#define WEB_MARKET_MANAGER 459 +#define WEB_COMPANY_ID 460 +#define WEB_COMPANY_NAME 461 +#define WEB_ADDRESS_STREET_NUM 462 +#define WEB_ADDRESS_STREET_NAME1 463 +#define WEB_ADDRESS_STREET_TYPE 464 +#define WEB_ADDRESS_SUITE_NUM 465 +#define WEB_ADDRESS_CITY 466 +#define WEB_ADDRESS_COUNTY 467 +#define WEB_ADDRESS_STATE 468 +#define WEB_ADDRESS_ZIP 469 +#define WEB_ADDRESS_COUNTRY 470 +#define WEB_ADDRESS_GMT_OFFSET 471 +#define WEB_TAX_PERCENTAGE 472 +#define WEB_NULLS 473 +#define WEB_ADDRESS 474 +#define WEB_SCD 475 +#define WEB_SITE_END 475 +#define DBGEN_VERSION_START 476 +#define DV_VERSION 476 +#define DV_CREATE_DATE 477 +#define DV_CREATE_TIME 478 +#define DV_CMDLINE_ARGS 479 +#define VALIDATE_STREAM 480 +#define DBGEN_VERSION_END 480 +#define S_BRAND_START 481 +#define S_BRAND_ID 481 +#define S_BRAND_SUBCLASS_ID 482 +#define S_BRAND_MANAGER_ID 483 +#define S_BRAND_MANUFACTURER_ID 484 +#define S_BRAND_NAME 485 +#define S_BRAND_END 485 +#define S_CUSTOMER_ADDRESS_START 486 +#define S_CADR_ID 486 +#define S_CADR_ADDRESS_STREET_NUMBER 487 +#define S_CADR_ADDRESS_STREET_NAME1 488 +#define S_CADR_ADDRESS_STREET_NAME2 489 +#define S_CADR_ADDRESS_STREET_TYPE 490 +#define S_CADR_ADDRESS_SUITE_NUM 491 +#define S_CADR_ADDRESS_CITY 492 +#define S_CADR_ADDRESS_COUNTY 493 +#define S_CADR_ADDRESS_STATE 494 +#define S_CADR_ADDRESS_ZIP 495 +#define S_CADR_ADDRESS_COUNTRY 496 +#define S_BADDR_ADDRESS 497 +#define S_CUSTOMER_ADDRESS_END 497 +#define S_CALL_CENTER_START 498 +#define S_CALL_CENTER_ID 498 +#define S_CALL_CENTER_DIVISION_ID 499 +#define S_CALL_CENTER_OPEN_DATE 500 +#define S_CALL_CENTER_CLOSED_DATE 501 +#define S_CALL_CENTER_NAME 502 +#define S_CALL_CENTER_CLASS 503 +#define S_CALL_CENTER_EMPLOYEES 504 +#define S_CALL_CENTER_SQFT 505 +#define S_CALL_CENTER_HOURS 506 +#define S_CALL_CENTER_MANAGER_ID 507 +#define S_CALL_CENTER_MARKET_ID 508 +#define S_CALL_CENTER_ADDRESS_ID 509 +#define S_CALL_CENTER_TAX_PERCENTAGE 510 +#define S_CALL_CENTER_SCD 511 +#define S_CALL_CENTER_END 511 +#define S_CATALOG_START 512 +#define S_CATALOG_NUMBER 512 +#define S_CATALOG_START_DATE 513 +#define S_CATALOG_END_DATE 514 +#define S_CATALOG_DESC 515 +#define S_CATALOG_TYPE 516 +#define S_CATALOG_END 516 +#define S_CATALOG_ORDER_START 517 +#define S_CORD_ID 517 +#define S_CORD_BILL_CUSTOMER_ID 518 +#define S_CORD_SHIP_CUSTOMER_ID 519 +#define S_CORD_ORDER_DATE 520 +#define S_CORD_ORDER_TIME 521 +#define S_CORD_SHIP_MODE_ID 522 +#define S_CORD_CALL_CENTER_ID 523 +#define S_CLIN_ITEM_ID 524 +#define S_CORD_COMMENT 525 +#define S_CATALOG_ORDER_END 525 +#define S_CATALOG_ORDER_LINEITEM_START 526 +#define S_CLIN_ORDER_ID 526 +#define S_CLIN_LINE_NUMBER 527 +#define S_CLIN_PROMOTION_ID 528 +#define S_CLIN_QUANTITY 529 +#define S_CLIN_COUPON_AMT 530 +#define S_CLIN_WAREHOUSE_ID 531 +#define S_CLIN_SHIP_DATE 532 +#define S_CLIN_CATALOG_ID 533 +#define S_CLIN_CATALOG_PAGE_ID 534 +#define S_CLIN_PRICING 535 +#define S_CLIN_SHIP_COST 536 +#define S_CLIN_IS_RETURNED 537 +#define S_CLIN_PERMUTE 538 +#define S_CATALOG_ORDER_LINEITEM_END 538 +#define S_CATALOG_PAGE_START 539 +#define S_CATALOG_PAGE_CATALOG_NUMBER 539 +#define S_CATALOG_PAGE_NUMBER 540 +#define S_CATALOG_PAGE_DEPARTMENT 541 +#define S_CP_ID 542 +#define S_CP_START_DATE 543 +#define S_CP_END_DATE 544 +#define S_CP_DESCRIPTION 545 +#define S_CP_TYPE 546 +#define S_CATALOG_PAGE_END 546 +#define S_CATALOG_PROMOTIONAL_ITEM_START 547 +#define S_CATALOG_PROMOTIONAL_ITEM_CATALOG_NUMBER 547 +#define S_CATALOG_PROMOTIONAL_ITEM_CATALOG_PAGE_NUMBER 548 +#define S_CATALOG_PROMOTIONAL_ITEM_ITEM_ID 549 +#define S_CATALOG_PROMOTIONAL_ITEM_PROMOTION_ID 550 +#define S_CATALOG_PROMOTIONAL_ITEM_END 550 +#define S_CATALOG_RETURNS_START 551 +#define S_CRET_CALL_CENTER_ID 551 +#define S_CRET_ORDER_ID 552 +#define S_CRET_LINE_NUMBER 553 +#define S_CRET_ITEM_ID 554 +#define S_CRET_RETURN_CUSTOMER_ID 555 +#define S_CRET_REFUND_CUSTOMER_ID 556 +#define S_CRET_DATE 557 +#define S_CRET_TIME 558 +#define S_CRET_QUANTITY 559 +#define S_CRET_AMOUNT 560 +#define S_CRET_TAX 561 +#define S_CRET_FEE 562 +#define S_CRET_SHIP_COST 563 +#define S_CRET_REFUNDED_CASH 564 +#define S_CRET_REVERSED_CHARGE 565 +#define S_CRET_MERCHANT_CREDIT 566 +#define S_CRET_REASON_ID 567 +#define S_CRET_PRICING 568 +#define S_CRET_SHIPMODE_ID 569 +#define S_CRET_WAREHOUSE_ID 570 +#define S_CRET_CATALOG_PAGE_ID 571 +#define S_CATALOG_RETURNS_END 571 +#define S_CATEGORY_START 572 +#define S_CATEGORY_ID 572 +#define S_CATEGORY_NAME 573 +#define S_CATEGORY_DESC 574 +#define S_CATEGORY_END 574 +#define S_CLASS_START 575 +#define S_CLASS_ID 575 +#define S_CLASS_SUBCAT_ID 576 +#define S_CLASS_DESC 577 +#define S_CLASS_END 577 +#define S_COMPANY_START 578 +#define S_COMPANY_ID 578 +#define S_COMPANY_NAME 579 +#define S_COMPANY_END 579 +#define S_CUSTOMER_START 580 +#define S_CUST_ID 580 +#define S_CUST_SALUTATION 581 +#define S_CUST_LAST_NAME 582 +#define S_CUST_FIRST_NAME 583 +#define S_CUST_PREFERRED_FLAG 584 +#define S_CUST_BIRTH_DATE 585 +#define S_CUST_FIRST_PURCHASE_DATE 586 +#define S_CUST_FIRST_SHIPTO_DATE 587 +#define S_CUST_BIRTH_COUNTRY 588 +#define S_CUST_LOGIN 589 +#define S_CUST_EMAIL 590 +#define S_CUST_LAST_LOGIN 591 +#define S_CUST_LAST_REVIEW 592 +#define S_CUST_PRIMARY_MACHINE 593 +#define S_CUST_SECONDARY_MACHINE 594 +#define S_CUST_ADDRESS 595 +#define S_CUST_ADDRESS_STREET_NUM 596 +#define S_CUST_ADDRESS_STREET_NAME1 597 +#define S_CUST_ADDRESS_STREET_NAME2 598 +#define S_CUST_ADDRESS_STREET_TYPE 599 +#define S_CUST_ADDRESS_SUITE_NUM 600 +#define S_CUST_ADDRESS_CITY 601 +#define S_CUST_ADDRESS_ZIP 602 +#define S_CUST_ADDRESS_COUNTY 603 +#define S_CUST_ADDRESS_STATE 604 +#define S_CUST_ADDRESS_COUNTRY 605 +#define S_CUST_LOCATION_TYPE 606 +#define S_CUST_GENDER 607 +#define S_CUST_MARITAL_STATUS 608 +#define S_CUST_EDUCATION 609 +#define S_CUST_CREDIT_RATING 610 +#define S_CUST_PURCHASE_ESTIMATE 611 +#define S_CUST_BUY_POTENTIAL 612 +#define S_CUST_DEPENDENT_CNT 613 +#define S_CUST_EMPLOYED_CNT 614 +#define S_CUST_COLLEGE_CNT 615 +#define S_CUST_VEHICLE_CNT 616 +#define S_CUST_INCOME 617 +#define S_CUSTOMER_END 617 +#define S_DIVISION_START 618 +#define S_DIVISION_ID 618 +#define S_DIVISION_COMPANY 619 +#define S_DIVISION_NAME 620 +#define S_DIVISION_END 620 +#define S_INVENTORY_START 621 +#define S_INVN_WAREHOUSE 621 +#define S_INVN_ITEM 622 +#define S_INVN_DATE 623 +#define S_INVN_QUANTITY 624 +#define S_INVENTORY_END 624 +#define S_ITEM_START 625 +#define S_ITEM_ID 625 +#define S_ITEM_PERMUTE 626 +#define S_ITEM_PRODUCT_ID 627 +#define S_ITEM_DESC 628 +#define S_ITEM_LIST_PRICE 629 +#define S_ITEM_WHOLESALE_COST 630 +#define S_ITEM_MANAGER_ID 631 +#define S_ITEM_SIZE 632 +#define S_ITEM_FORMULATION 633 +#define S_ITEM_FLAVOR 634 +#define S_ITEM_UNITS 635 +#define S_ITEM_CONTAINER 636 +#define S_ITEM_SCD 637 +#define S_ITEM_END 637 +#define S_MANAGER_START 638 +#define S_MANAGER_ID 638 +#define S_MANAGER_NAME 639 +#define S_MANAGER_END 639 +#define S_MANUFACTURER_START 640 +#define S_MANUFACTURER_ID 640 +#define S_MANUFACTURER_NAME 641 +#define S_MANUFACTURER_END 641 +#define S_MARKET_START 642 +#define S_MARKET_ID 642 +#define S_MARKET_CLASS_NAME 643 +#define S_MARKET_DESC 644 +#define S_MARKET_MANAGER_ID 645 +#define S_MARKET_END 645 +#define S_PRODUCT_START 646 +#define S_PRODUCT_ID 646 +#define S_PRODUCT_BRAND_ID 647 +#define S_PRODUCT_NAME 648 +#define S_PRODUCT_TYPE 649 +#define S_PRODUCT_END 649 +#define S_PROMOTION_START 650 +#define S_PROMOTION_ID 650 +#define S_PROMOTION_ITEM_ID 651 +#define S_PROMOTION_START_DATE 652 +#define S_PROMOTION_END_DATE 653 +#define S_PROMOTION_COST 654 +#define S_PROMOTION_RESPONSE_TARGET 655 +#define S_PROMOTION_DMAIL 656 +#define S_PROMOTION_EMAIL 657 +#define S_PROMOTION_CATALOG 658 +#define S_PROMOTION_TV 659 +#define S_PROMOTION_RADIO 660 +#define S_PROMOTION_PRESS 661 +#define S_PROMOTION_EVENT 662 +#define S_PROMOTION_DEMO 663 +#define S_PROMOTION_DETAILS 664 +#define S_PROMOTION_PURPOSE 665 +#define S_PROMOTION_DISCOUNT_ACTIVE 666 +#define S_PROMOTION_DISCOUNT_PCT 667 +#define S_PROMOTION_NAME 668 +#define S_PROMOTION_BITFIELD 669 +#define S_PROMOTION_END 669 +#define S_PURCHASE_START 670 +#define S_PURCHASE_ID 670 +#define S_PURCHASE_STORE_ID 671 +#define S_PURCHASE_CUSTOMER_ID 672 +#define S_PURCHASE_DATE 673 +#define S_PURCHASE_TIME 674 +#define S_PURCHASE_REGISTER 675 +#define S_PURCHASE_CLERK 676 +#define S_PURCHASE_COMMENT 677 +#define S_PURCHASE_PRICING 678 +#define S_PLINE_ITEM_ID 679 +#define S_PURCHASE_END 679 +#define S_PURCHASE_LINEITEM_START 680 +#define S_PLINE_PURCHASE_ID 680 +#define S_PLINE_NUMBER 681 +#define S_PLINE_PROMOTION_ID 682 +#define S_PLINE_SALE_PRICE 683 +#define S_PLINE_QUANTITY 684 +#define S_PLINE_COUPON_AMT 685 +#define S_PLINE_COMMENT 686 +#define S_PLINE_PRICING 687 +#define S_PLINE_IS_RETURNED 688 +#define S_PLINE_PERMUTE 689 +#define S_PURCHASE_LINEITEM_END 689 +#define S_REASON_START 690 +#define S_REASON_ID 690 +#define S_REASON_DESC 691 +#define S_REASON_END 691 +#define S_STORE_START 692 +#define S_STORE_ID 692 +#define S_STORE_ADDRESS_ID 693 +#define S_STORE_DIVISION_ID 694 +#define S_STORE_OPEN_DATE 695 +#define S_STORE_CLOSE_DATE 696 +#define S_STORE_NAME 697 +#define S_STORE_CLASS 698 +#define S_STORE_EMPLOYEES 699 +#define S_STORE_FLOOR_SPACE 700 +#define S_STORE_HOURS 701 +#define S_STORE_MARKET_MANAGER_ID 702 +#define S_STORE_MANAGER_ID 703 +#define S_STORE_MARKET_ID 704 +#define S_STORE_GEOGRAPHY_CLASS 705 +#define S_STORE_TAX_PERCENTAGE 706 +#define S_STORE_END 706 +#define S_STORE_PROMOTIONAL_ITEM_START 707 +#define S_SITM_PROMOTION_ID 707 +#define S_SITM_ITEM_ID 708 +#define S_SITM_STORE_ID 709 +#define S_STORE_PROMOTIONAL_ITEM_END 709 +#define S_STORE_RETURNS_START 710 +#define S_SRET_STORE_ID 710 +#define S_SRET_PURCHASE_ID 711 +#define S_SRET_LINENUMBER 712 +#define S_SRET_ITEM_ID 713 +#define S_SRET_CUSTOMER_ID 714 +#define S_SRET_RETURN_DATE 715 +#define S_SRET_RETURN_TIME 716 +#define S_SRET_TICKET_NUMBER 717 +#define S_SRET_RETURN_QUANTITY 718 +#define S_SRET_RETURN_AMT 719 +#define S_SRET_RETURN_TAX 720 +#define S_SRET_RETURN_FEE 721 +#define S_SRET_RETURN_SHIP_COST 722 +#define S_SRET_REFUNDED_CASH 723 +#define S_SRET_REVERSED_CHARGE 724 +#define S_SRET_MERCHANT_CREDIT 725 +#define S_SRET_REASON_ID 726 +#define S_SRET_PRICING 727 +#define S_STORE_RETURNS_END 727 +#define S_SUBCATEGORY_START 728 +#define S_SBCT_ID 728 +#define S_SBCT_CATEGORY_ID 729 +#define S_SBCT_NAME 730 +#define S_SBCT_DESC 731 +#define S_SUBCATEGORY_END 731 +#define S_SUBCLASS_START 732 +#define S_SUBC_ID 732 +#define S_SUBC_CLASS_ID 733 +#define S_SUBC_NAME 734 +#define S_SUBC_DESC 735 +#define S_SUBCLASS_END 735 +#define S_WAREHOUSE_START 736 +#define S_WRHS_ID 736 +#define S_WRHS_DESC 737 +#define S_WRHS_SQFT 738 +#define S_WRHS_ADDRESS_ID 739 +#define S_WAREHOUSE_END 739 +#define S_WEB_ORDER_START 740 +#define S_WORD_ID 740 +#define S_WORD_BILL_CUSTOMER_ID 741 +#define S_WORD_SHIP_CUSTOMER_ID 742 +#define S_WORD_ORDER_DATE 743 +#define S_WORD_ORDER_TIME 744 +#define S_WORD_SHIP_MODE_ID 745 +#define S_WORD_WEB_SITE_ID 746 +#define S_WORD_COMMENT 747 +#define S_WLIN_ITEM_ID 748 +#define S_WEB_ORDER_END 748 +#define S_WEB_ORDER_LINEITEM_START 749 +#define S_WLIN_ID 749 +#define S_WLIN_LINE_NUMBER 750 +#define S_WLIN_PROMOTION_ID 751 +#define S_WLIN_QUANTITY 752 +#define S_WLIN_COUPON_AMT 753 +#define S_WLIN_WAREHOUSE_ID 754 +#define S_WLIN_SHIP_DATE 755 +#define S_WLIN_WEB_PAGE_ID 756 +#define S_WLIN_PRICING 757 +#define S_WLIN_SHIP_COST 758 +#define S_WLIN_IS_RETURNED 759 +#define S_WLIN_PERMUTE 760 +#define S_WEB_ORDER_LINEITEM_END 760 +#define S_WEB_PAGE_START 761 +#define S_WPAG_SITE_ID 761 +#define S_WPAG_ID 762 +#define S_WPAG_CREATE_DATE 763 +#define S_WPAG_ACCESS_DATE 764 +#define S_WPAG_AUTOGEN_FLAG 765 +#define S_WPAG_DEPARTMENT 766 +#define S_WPAG_URL 767 +#define S_WPAG_TYPE 768 +#define S_WPAG_CHAR_CNT 769 +#define S_WPAG_LINK_CNT 770 +#define S_WPAG_IMAGE_CNT 771 +#define S_WPAG_MAX_AD_CNT 772 +#define S_WPAG_PERMUTE 773 +#define S_WEB_PAGE_END 773 +#define S_WEB_PROMOTIONAL_ITEM_START 774 +#define S_WITM_SITE_ID 774 +#define S_WITM_PAGE_ID 775 +#define S_WITM_ITEM_ID 776 +#define S_WITM_PROMOTION_ID 777 +#define S_WEB_PROMOTIONAL_ITEM_END 777 +#define S_WEB_RETURNS_START 778 +#define S_WRET_SITE_ID 778 +#define S_WRET_ORDER_ID 779 +#define S_WRET_LINE_NUMBER 780 +#define S_WRET_ITEM_ID 781 +#define S_WRET_RETURN_CUST_ID 782 +#define S_WRET_REFUND_CUST_ID 783 +#define S_WRET_RETURN_DATE 784 +#define S_WRET_RETURN_TIME 785 +#define S_WRET_REASON_ID 786 +#define S_WRET_PRICING 787 +#define S_WEB_RETURNS_END 787 +#define S_WEB_SITE_START 788 +#define S_WSIT_ID 788 +#define S_WSIT_OPEN_DATE 789 +#define S_WSIT_CLOSE_DATE 790 +#define S_WSIT_NAME 791 +#define S_WSIT_ADDRESS_ID 792 +#define S_WSIT_DIVISION_ID 793 +#define S_WSIT_CLASS 794 +#define S_WSIT_MANAGER_ID 795 +#define S_WSIT_MARKET_ID 796 +#define S_WSIT_TAX_PERCENTAGE 797 +#define S_WEB_SITE_END 797 +#define S_ZIPG_START 798 +#define S_ZIPG_ZIP 798 +#define S_ZIPG_GMT 799 +#define S_ZIPG_END 799 +#define MAX_COLUMN 799 +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/config.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/config.h new file mode 100644 index 0000000000000..4c0c33fa7ef68 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/config.h @@ -0,0 +1,156 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef CONFIG_H +#define CONFIG_H + +// #ifdef MACOS +#define SUPPORT_64BITS +#define HUGE_TYPE int64_t +#define HUGE_FORMAT "%lld" +#define HUGE_COUNT 1 +#define USE_STRING_H +#define USE_STDLIB_H +#define USE_LIMITS_H +#include +#define MAXINT INT_MAX + +// #define FLEX +// #endif /* MACOS */ + +#ifdef NCR +#define STDLIB_HAS_GETOPT +#define USE_STRING_H +#define USE_VALUES_H +#ifdef SQLSERVER +#define WIN32 +#else +/* the 64 bit defines are for the Metaware compiler */ +#define SUPPORT_64BITS +#define HUGE_TYPE long long +#define HUGE_COUNT 1 +#define HUGE_FORMAT "%LLd" +#define int32_t int +#endif /* SQLSERVER or MP/RAS */ +#endif /* NCR */ + +#ifdef AIX +#define _ALL_SOURCE +#define USE_STRING_H +#define USE_LIMITS_H +/* + * if the C compiler is 3.1 or later, then uncomment the + * lines for 64 bit seed generation + */ +#define SUPPORT_64BITS +#define HUGE_TYPE long long +#define HUGE_COUNT 1 +#define HUGE_FORMAT "%lld" +#define STDLIB_HAS_GETOPT +#define USE_STDLIB_H +#define FLEX +#endif /* AIX */ + +#ifdef CYGWIN +#define USE_STRING_H +#define PATH_SEP '\\' +#define SUPPORT_64BITS +#define HUGE_TYPE __int64 +#define HUGE_COUNT 1 +#define HUGE_FORMAT "%I64d" +#endif /* WIN32 */ + +#ifdef HPUX +#define SUPPORT_64BITS +#define HUGE_TYPE long long int +#define HUGE_FORMAT "%lld" +#define HUGE_COUNT 1 +#define USE_STRING_H +#define USE_VALUES_H +#define USE_STDLIB_H +#define FLEX +#endif /* HPUX */ + +#ifdef INTERIX +#define USE_LIMITS_H +#define SUPPORT_64BITS +#define HUGE_TYPE long long int +#define HUGE_FORMAT "%lld" +#define HUGE_COUNT 1 +#endif /* INTERIX */ + +#ifdef LINUX +#define SUPPORT_64BITS +#define HUGE_TYPE int64_t +#define HUGE_FORMAT "%lld" +#define HUGE_COUNT 1 +#define USE_STRING_H +#define USE_VALUES_H +#define USE_STDLIB_H +#define FLEX +#endif /* LINUX */ + +#ifdef SOLARIS +#define SUPPORT_64BITS +#define HUGE_TYPE long long +#define HUGE_FORMAT "%lld" +#define HUGE_COUNT 1 +#define USE_STRING_H +#define USE_VALUES_H +#define USE_STDLIB_H +#endif /* SOLARIS */ + +#ifdef SOL86 +#define SUPPORT_64BITS +#define HUGE_TYPE long long +#define HUGE_FORMAT "%lld" +#define HUGE_COUNT 1 +#define USE_STRING_H +#define USE_VALUES_H +#define USE_STDLIB_H +#endif /* SOLARIS */ + +#ifdef WIN32 +#define USE_STRING_H +#define USE_LIMITS_H +#define PATH_SEP '\\' +#define SUPPORT_64BITS +#define HUGE_TYPE __int64 +#define HUGE_COUNT 1 +#define HUGE_FORMAT "%I64d" +#endif /* WIN32 */ + +/* preliminary defines for 64-bit windows compile */ +#ifdef WIN64 +#define USE_STRING_H +#define PATH_SEP '\\' +#define SUPPORT_64BITS +#define HUGE_TYPE __int64 +#define HUGE_COUNT 1 +#define HUGE_FORMAT "%I64d" +#endif /* WIN32 */ + +#ifndef PATH_SEP +#define PATH_SEP '/' +#endif /* PATH_SEP */ + +#ifndef HUGE_TYPE +#error The code now requires 64b support +#endif + +/*** + ** DATABASE DEFINES + ***/ +#ifdef _MYSQL +#define STR_QUOTES +#endif + +#endif /* CONFIG_H */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/constants.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/constants.h new file mode 100644 index 0000000000000..8fb90df1a208b --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/constants.h @@ -0,0 +1,310 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef CONSTANTS_H +#define CONSTANTS_H +/*** +*** Multi-table/Global Defines +***/ +#define DATA_START_DATE "1998-01-01" /* earliest date in the data set */ +#define DATA_END_DATE "2003-12-31" /* latest date in the data set */ +#define LINES_PER_ORDER \ + 16 /* max number of lineitems per order for all channels */ + +/*** +*** C_xxx Cutomer Defines +***/ +#define C_PREFERRED_PCT 50 + +/*** + *** CC_xxx Call Center Defines + ***/ +#define CC_EMPLOYEE_MAX 7 /* rises ~ scale ^ 2 */ + +/*** + *** CP_xxx Catalog Page Defines + ***/ +#define CP_CATALOGS_PER_YEAR 18 +#define CP_SK(c, s, p) (c * s + p) + +/*** +*** CR_xxx Catalog Returns Defines +***/ +#define CR_RETURN_PCT 10 /* percentage of catalog sales that are returned */ + +/*** +*** CS_xxx Customer Sales Defines +***/ +#define CS_QUANTITY_MAX "100" +#define CS_MARKUP_MAX "2.00" +#define CS_DISCOUNT_MAX "1.00" +#define CS_WHOLESALE_MAX "100.00" +#define CS_COUPON_MAX "0.50" +#define CS_MIN_SHIP_DELAY 2 /* minimum days from order to ship */ +#define CS_MAX_SHIP_DELAY 90 /* maximum days from order to ship */ +#define CS_ITEMS_PER_ORDER 10 /* number of items in each order */ +#define CS_GIFT_PCT 10 /* ship-to != bill-to */ + +/* + * DATE SETTINGS + * + * The benchmarks sense of "today". Should this be a sliding scale/parameter? + */ +#define CURRENT_YEAR 2003 +#define CURRENT_MONTH 1 +#define CURRENT_DAY 8 +#define CURRENT_QUARTER 1 +#define CURRENT_WEEK 2 +#define DATE_MINIMUM "1998-01-01" +#define DATE_MAXIMUM "2002-12-31" +#define YEAR_MINIMUM 1998 +#define YEAR_MAXIMUM 2002 +#define WAREHOUSE_LOAD_DATE "2001-07-18" +#define UPDATE_INTERVAL 30 /* refresh interval in days */ +#define TODAYS_DATE "2003-01-08" + +/*** + *** INV_xxx Inventory Defines + ***/ +#define INV_QUANTITY_MIN 0 +#define INV_QUANTITY_MAX 1000 + +/*** + *** ITEM_xxx Item Defines + ***/ +#define ITEM_DESC_LEN 5 +#define ITEM_NAME_LEN 10 +#define ITEM_MANFACTURER_COUNT \ + 1000 /* number of brands handled by a particular manufacturer */ + +/*** + *** PROMO_xxx Promotions Defines + ***/ +#define PROMO_NAME_LEN 5 +#define PROMO_START_MIN -720 +#define PROMO_START_MAX 100 +#define PROMO_START_MEAN 0 +#define PROMO_LEN_MIN 1 +#define PROMO_LEN_MAX 60 +#define PROMO_LEN_MEAN 0 +#define PROMO_DETAIL_LEN_MIN 20 +#define PROMO_DETAIL_LEN_MAX 60 + +/*** +*** SR_xxx Store Returns Defines +***/ +#define SR_RETURN_PCT 10 /* percentage of store sales that are returned */ + +/*** +*** SS_xxx Store Sales Defines +***/ +#define SS_MIN_SHIP_DELAY 2 /* minimum days from order to ship */ +#define SS_MAX_SHIP_DELAY 90 /* maximum days from order to ship */ +#define SS_QUANTITY_MAX "100" +#define SS_MARKUP_MAX "1.00" +#define SS_DISCOUNT_MAX "1.00" +#define SS_WHOLESALE_MAX "100.00" +#define SS_COUPON_MAX "0.50" + +/*** +*** WP_xxx Web Page Defines +***/ +#define WP_AUTOGEN_PCT 30 +#define WP_LINK_MIN 2 +#define WP_LINK_MAX 25 +#define WP_IMAGE_MIN 1 +#define WP_IMAGE_MAX 7 +#define WP_AD_MIN 0 +#define WP_AD_MAX 4 +#define WP_MAX_REC_DURATION \ + 1000 /* maximum time from start to end of record \ + */ +#define WP_IDLE_TIME_MAX 100 /* maximum time since last page access */ + +/*** +*** W_xxx Warehouse Defines +***/ +#define W_DESC_MIN 5 +#define W_SQFT_MIN 50000 +#define W_SQFT_MAX 1000000 +#define W_NAME_MIN 10 + +/*** +*** WR_xxx Web Returns Defines +***/ +#define WR_RETURN_PCT 10 /* percentage of web sales that are returned */ +#define WR_SHIP_LAG_MIN 2 /* lag time between receiving and returning */ +#define WR_SHIP_LAG_MAX 12 + +/*** +*** WEB_xxx Web Site Defines +***/ +#define WEB_START_DATE \ + DATE_MINIMUM /* range of open/close dates; actual dates can exceed these \ + values */ +#define WEB_END_DATE DATE_MAXIMUM /* due to staggered start of each site */ +#define WEB_DATE_STAGGER \ + 17 /* time between site creation on leading/trailing edge */ +#define WEB_PAGES_PER_SITE 123 /* number of pages on a web site */ +/* some of the web sites are completely replaced in the date range. */ +#define WEB_MORTALITY \ + 50 /* percentage of sites that "die" between start and end */ +#define WEB_IS_REPLACED(j) \ + ((j % (100 / WEB_MORTALITY)) == 0) /* does this site get replaced? */ +#define WEB_IS_REPLACEMENT(j) \ + ((j / (100 / WEB_MORTALITY)) % 2) /* is this the replacement? */ + +/*** + *** SOURCE SCHEMA CONSTANTS + ***/ +#define DAYS_PER_UPDATE 3 + +/*** +*** RS_xxx: Row and column sizes +***/ +/* sizes used in various tables */ +#define RS_BKEY 16 +/* table-specific sizes */ + +#define RS_BRND_NAME 50 +#define RS_C_SALUTATION 5 +#define RS_C_FIRST_NAME 20 +#define RS_C_LAST_NAME 30 +#define RS_C_BIRTH_COUNTRY 20 +#define RS_C_LOGIN 13 +#define RS_C_PASSWORD 13 +#define RS_C_EMAIL 50 +#define RS_C_PRIMARY_MACHINE_ID 15 +#define RS_C_SECONDARY_MACHINE_ID 15 +#define RS_CA_SUITE_NUMBER 10 +#define RS_CA_STREET_NAME 60 +#define RS_CA_STREET_TYPE 15 +#define RS_CA_CITY 60 +#define RS_CA_COUNTY 30 +#define RS_CA_STATE 2 +#define RS_CA_COUNTRY 20 +#define RS_CA_ZIP 10 +#define RS_CA_LOCATION_TYPE 20 +#define RS_CATG_DESC 20 +#define RS_CC_NAME 50 +#define RS_CC_CLASS 50 +#define RS_CC_HOURS 20 +#define RS_CC_MANAGER 40 +#define RS_CC_MARKET_MANAGER 40 +#define RS_CC_MARKET_CLASS 50 +#define RS_CC_MARKET_DESC 100 +#define RS_CC_DIVISION_NAME 50 +#define RS_CC_COMPANY_NAME 60 +#define RS_CC_SUITE_NUM 10 +#define RS_CC_STREET_NAME 60 +#define RS_CC_STREET_TYPE 15 +#define RS_CC_CITY 60 +#define RS_CC_COUNTY 30 +#define RS_CC_STATE 2 +#define RS_CC_COUNTRY 20 +#define RS_CC_ZIP 10 +#define RS_CD_GENDER 1 +#define RS_CD_MARITAL_STATUS 1 +#define RS_CD_EDUCATION_STATUS 20 +#define RS_CD_CREDIT_RATING 10 +#define RS_CP_DEPARTMENT 20 +#define RS_CLAS_DESC 100 +#define RS_CMPY_NAME 50 +#define RS_CP_DESCRIPTION 100 +#define RS_CP_TYPE 100 +#define RS_CTGR_NAME 25 +#define RS_CTGR_DESC 100 +#define RS_CUST_CREDIT 100 +#define RS_D_DAY_NAME 4 +#define RS_D_QUARTER_NAME 4 +#define RS_DVSN_NAME 50 +#define RS_HD_BUY_POTENTIAL 7 +#define RS_I_ITEM_DESC 200 +#define RS_I_BRAND 50 +#define RS_I_SUBCLASS 50 +#define RS_I_CLASS 50 +#define RS_I_SUBCATEGORY 50 +#define RS_I_CATEGORY 50 +#define RS_I_MANUFACT 50 +#define RS_I_SIZE 20 +#define RS_I_FORMULATION 20 +#define RS_I_FLAVOR 20 +#define RS_I_UNITS 10 +#define RS_I_CONTAINER 10 +#define RS_I_PRODUCT_NAME 50 +#define RS_MANF_NAME 50 +#define RS_MNGR_NAME 50 +#define RS_P_PROMO_NAME 50 +#define RS_P_CHANNEL_DETAILS 100 +#define RS_P_PURPOSE 15 +#define RS_PB_DESCRIPTION 100 +#define RS_PLIN_COMMENT 100 +#define RS_PROD_NAME 100 +#define RS_PROD_TYPE 100 +#define RS_R_REASON_DESCRIPTION 100 +#define RS_STORE_NAME 50 +#define RS_STORE_HOURS 20 +#define RS_S_STORE_MANAGER 40 +#define RS_S_GEOGRAPHY_CLASS 100 +#define RS_S_MARKET_DESC 100 +#define RS_S_MARKET_MANAGER 40 +#define RS_S_DIVISION_NAME 50 +#define RS_S_COMPANY_NAME 50 +#define RS_S_SUITE_NUM 10 +#define RS_S_STREET_NAME 60 +#define RS_S_STREET_TYPE 15 +#define RS_S_CITY 60 +#define RS_S_STATE 2 +#define RS_S_COUNTY 30 +#define RS_S_COUNTRY 30 +#define RS_S_ZIP 10 +#define RS_SM_TYPE 30 +#define RS_SM_CODE 10 +#define RS_SM_CONTRACT 20 +#define RS_SM_CARRIER 20 +#define RS_SBCT_NAME 100 +#define RS_SBCT_DESC 100 +#define RS_SUBC_NAME 100 +#define RS_SUBC_DESC 100 +#define RS_T_AM_PM 2 +#define RS_T_SHIFT 20 +#define RS_T_SUB_SHIFT 20 +#define RS_T_MEAL_TIME 20 +#define RS_W_WAREHOUSE_NAME 20 +#define RS_W_STREET_NAME 60 +#define RS_W_SUITE_NUM 10 +#define RS_W_STREET_TYPE 15 +#define RS_W_CITY 60 +#define RS_W_COUNTY 30 +#define RS_W_STATE 2 +#define RS_W_COUNTRY 20 +#define RS_W_ZIP 10 +#define RS_WEB_MANAGER 50 +#define RS_WEB_NAME 50 +#define RS_WEB_CLASS 50 +#define RS_WEB_MARKET_CLASS 50 +#define RS_WEB_MARKET_DESC 100 +#define RS_WEB_MARKET_MANAGER 40 +#define RS_WEB_COMPANY_NAME 100 +#define RS_WEB_SUITE_NUMBER 10 +#define RS_WEB_STREET_NAME 60 +#define RS_WEB_STREET_TYPE 15 +#define RS_WEB_CITY 60 +#define RS_WEB_COUNTY 30 +#define RS_WEB_STATE 2 +#define RS_WEB_COUNTRY 20 +#define RS_WEB_ZIP 10 +#define RS_WP_URL 100 +#define RS_WEB_TYPE 50 +#define RS_WRHS_DESC 100 +#define RS_WORD_COMMENT 100 +#define RS_ZIPG_ZIP 5 +#endif /* CONSTANTS_H */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/date.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/date.h new file mode 100644 index 0000000000000..19a14d106799c --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/date.h @@ -0,0 +1,54 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef R_DATE_H +#define R_DATE_H + +#include "mathops.h" + +typedef struct DATE_T { + int flags; + int year; + int month; + int day; + int julian; +} date_t; + +date_t* mk_date(void); + +int jtodt(date_t* dest, int i); +int strtodt(date_t* dest, char* s); +date_t* strtodate(char* str); +int strtotime(char* str); + +char* dttostr(date_t* d); +int dttoj(date_t* d); + +int date_t_op(date_t* dest, int o, date_t* d1, date_t* d2); +int set_dow(date_t* d); +int is_leap(int year); +int day_number(date_t* d); +int date_part(date_t* d, int p); +int set_outfile(int i); +int getDateWeightFromJulian(int jDay, int nDistribution); +#define CENTURY_SHIFT 20 /* years before this are assumed to be 2000's */ +/* + * DATE OPERATORS + */ +#define OP_FIRST_DOM 0x01 /* get date of first day of current month */ +#define OP_LAST_DOM \ + 0x02 /* get date of last day of current month; LY == 2/28) */ +#define OP_SAME_LY 0x03 /* get date for same day/month, last year */ +#define OP_SAME_LQ 0x04 /* get date for same offset in the prior quarter */ + +extern char* weekday_names[]; + +#endif /* R_DATE_H */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dbgen_version.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dbgen_version.h new file mode 100644 index 0000000000000..05e228d2f01b1 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dbgen_version.h @@ -0,0 +1,23 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef DBGEN_VERSION_H +#define DBGEN_VERSION_H + +#include "dist.h" + +int mk_dbgen_version( + void* pDest, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); +int pr_dbgen_version(void* pSrc); +int ld_dbgen_version(void* pSrc); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dcomp.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dcomp.h new file mode 100644 index 0000000000000..3e02672e3b996 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dcomp.h @@ -0,0 +1,62 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef DCOMP_H +#define DCOMP_H + +#include "config.h" +#include "dist.h" +#include "grammar.h" +#include "porting.h" + +/* + * query template grammar definition + */ +#define TKN_UNKNOWN 0 +#define TKN_CREATE 1 +#define TKN_WEIGHTS 2 +#define TKN_TYPES 3 +#define TKN_INCLUDE 4 +#define TKN_SET 5 +#define TKN_VARCHAR 6 +#define TKN_INT 7 +#define TKN_ADD 8 +#define TKN_DATE 9 +#define TKN_DECIMAL 10 +#define TKN_NAMES 11 +#define MAX_TOKEN 11 + +int ProcessDistribution(char* s, token_t* t); +int ProcessTypes(char* s, token_t* t); +int ProcessInclude(char* s, token_t* t); +int ProcessSet(char* s, token_t* t); +int ProcessAdd(char* s, token_t* t); + +#ifdef DECLARER +token_t dcomp_tokens[MAX_TOKEN + 2] = { + {TKN_UNKNOWN, "", NULL}, + {TKN_CREATE, "create", ProcessDistribution}, + {TKN_WEIGHTS, "weights", NULL}, + {TKN_TYPES, "types", NULL}, + {TKN_INCLUDE, "#include", ProcessInclude}, + {TKN_SET, "set", ProcessSet}, + {TKN_VARCHAR, "varchar", NULL}, + {TKN_INT, "int", NULL}, + {TKN_ADD, "add", ProcessAdd}, + {TKN_DATE, "date", NULL}, + {TKN_DECIMAL, "decimal", NULL}, + {TKN_NAMES, "names", NULL}, + {-1, "", NULL}}; +#else +extern token_t tokens[]; +#endif + +#endif /* DCOMP_H */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/decimal.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/decimal.h new file mode 100644 index 0000000000000..bbcb0c3dfb5eb --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/decimal.h @@ -0,0 +1,36 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef R_DECIMAL_H +#define R_DECIMAL_H +#include +#include "config.h" +#include "dist.h" +#include "mathops.h" +#include "porting.h" + +#define FL_INIT 0x0004 + +decimal_t* mk_decimal(int s, int p); + +int itodec(decimal_t* dest, int i); +int ftodec(decimal_t* d, double f); +int strtodec(decimal_t* d, char* src); + +int dectostr(char* dest, decimal_t* d); +int dectof(double* dest, decimal_t*); +#define dectoi(d) atoi(d->number) + +int decimal_t_op(decimal_t* dest, int o, decimal_t* d1, decimal_t* d2); +void print_decimal(int nColumn, decimal_t* d, int s); +void set_precision(decimal_t* d, int sie, int precision); +#define NegateDecimal(d) (d)->number *= -1 +#endif /* R_DECIMAL_H */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dist.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dist.h new file mode 100644 index 0000000000000..d0c62331b3b32 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/dist.h @@ -0,0 +1,3985 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#pragma once +#include +#include +#include +#include +#include +#include "algorithm" +#include "columns.h" +#include "config.h" +#include "iostream" +#include "tables.h" +#include "vector" + +#ifndef STREAMS_H +#define STREAMS_H +#endif +#include "constants.h" +#include "tables.h" + +#ifndef R_DIST_H +#define R_DIST_H +#endif + +/*** + *** RELEASE INFORMATION + ***/ +#define VERSION 2 +#define RELEASE 10 +#define MODIFICATION 0 +#define PATCH "" +#define COPYRIGHT "Transaction Processing Performance Council (TPC)" +#define C_DATES "2001 - 2018" + +#define D_NAME_LEN 20 +#define MAX_STREAM 805 + +#define RS_W_STORE_NAME 50 +#define RS_W_STORE_MGR 40 +#define RS_W_MARKET_MGR 40 +#define RS_W_MARKET_DESC 100 +#define STORE_MIN_TAX_PERCENTAGE "0.00" +#define STORE_MAX_TAX_PERCENTAGE "0.11" + +/*** + *** STORE_xxx Store Defines + ***/ +#define STORE_MIN_DAYS_OPEN 5 +#define STORE_MAX_DAYS_OPEN 500 +#define STORE_CLOSED_PCT 30 +#define STORE_MIN_REV_GROWTH "-0.05" +#define STORE_MAX_REV_GROWTH "0.50" +#define STORE_DESC_MIN 15 + +#define RS_VERSION_LENGTH 100 +#define RS_CMDLINARGS_LENGTH 200 + +#define OPT_NONE 0x00 +#define OPT_FLG 0x01 /* option is a flag; no parameter */ +#define OPT_INT 0x02 /* argument is an integer */ +#define OPT_STR 0x04 /* argument is a string */ +#define OPT_NOP 0x08 /* flags non-operational options */ +#define OPT_SUB 0x10 /* sub-option defined */ +#define OPT_ADV 0x20 /* advanced option */ +#define OPT_SET \ + 0x40 /* not changeable -- used for default/file/command precedence */ +#define OPT_DFLT 0x80 /* param set to non-zero default */ +#define OPT_MULTI 0x100 /* param may be set repeatedly */ +#define OPT_HIDE 0x200 /* hidden option -- not listed in usage */ +#define TYPE_MASK 0x07 + +/* + * Flag field definitions used in tdefs[] + */ +#define FL_NONE 0x0000 /* this table is not defined */ +#define FL_NOP 0x0001 /* this table is not defined */ +#define FL_DATE_BASED 0x0002 /* this table is produced in date order */ +#define FL_CHILD 0x0004 /* this table is the child in a parent/child link */ +#define FL_OPEN 0x0008 /* this table has a valid output destination */ +#define FL_DUP_NAME 0x0010 /* to keep find_table() from complaining twice */ +#define FL_TYPE_2 \ + 0x0020 /* this dimension keeps history -- rowcount shows unique entities \ + (not including revisions) */ +#define FL_SMALL 0x0040 /* this table has low rowcount; used by address.c */ +#define FL_SPARSE 0x0080 +/* unused 0x0100 */ +#define FL_NO_UPDATE \ + 0x0200 /* this table is not altered by the update process */ +#define FL_SOURCE_DDL 0x0400 /* table in the souce schema */ +#define FL_JOIN_ERROR 0x0800 /* join called without an explicit rule */ +#define FL_PARENT 0x1000 /* this table has a child in nParam */ +#define FL_FACT_TABLE 0x2000 +#define FL_PASSTHRU 0x4000 /* verify routine uses warehouse without change */ +#define FL_VPRINT 0x8000 /* verify routine includes print function */ + +#define JMS 1 + +typedef HUGE_TYPE ds_key_t; + +struct DSDGenContext; + +typedef struct DIST_T { + int* type_vector; + int** weight_sets; + int* maximums; + int** value_sets; + char* strings; + char* names; + int size; +} dist_t; + +struct DBGEN_VERSION_TBL { + char szVersion[RS_VERSION_LENGTH + 1]; + char szDate[26]; + char szTime[26]; + char szCmdLineArgs[RS_CMDLINARGS_LENGTH + 1]; +}; + +typedef struct D_IDX_T { + char name[D_NAME_LEN + 1]; + int index; + int nAllocatedLength; + int nRemainingStrSpace; + int offset; + int str_space; + int name_space; + int length; + int w_width; + int v_width; + int flags; + dist_t* dist; +} d_idx_t; + +typedef struct DISTINDEX_T { + int nDistCount; + int nAllocatedCount; + d_idx_t* pEntries; +} distindex_t; + +/* + * a precise decimal data type, using scaled integer + * arithmetic. + */ +typedef struct DECIMAL_T { + int flags; + int precision; + int scale; + ds_key_t number; +} decimal_t; + +typedef struct OPTION_T { + const char* name; + int flags; + int index; + const char* usage; + int (*action)( + const char* szPName, + const char* optarg, + DSDGenContext& dsdGenContext); + const char* dflt; +} option_t; + +typedef struct DS_PRICING_T { + decimal_t wholesale_cost; + decimal_t list_price; + decimal_t sales_price; + int quantity; + decimal_t ext_discount_amt; + decimal_t ext_sales_price; + decimal_t ext_wholesale_cost; + decimal_t ext_list_price; + decimal_t tax_pct; + decimal_t ext_tax; + decimal_t coupon_amt; + decimal_t ship_cost; + decimal_t ext_ship_cost; + decimal_t net_paid; + decimal_t net_paid_inc_tax; + decimal_t net_paid_inc_ship; + decimal_t net_paid_inc_ship_tax; + decimal_t net_profit; + decimal_t refunded_cash; + decimal_t reversed_charge; + decimal_t store_credit; + decimal_t fee; + decimal_t net_loss; +} ds_pricing_t; + +typedef struct DS_ADDR_T { + char suite_num[RS_CC_SUITE_NUM + 1]; + int street_num; + char* street_name1; + char* street_name2; + char* street_type; + char* city; + char* county; + char* state; + char country[RS_CC_COUNTRY + 1]; + int zip; + int plus4; + int gmt_offset; +} ds_addr_t; + +/* + * STORE_SALES table structure + */ +struct W_STORE_SALES_TBL { + ds_key_t ss_sold_date_sk; + ds_key_t ss_sold_time_sk; + ds_key_t ss_sold_item_sk; + ds_key_t ss_sold_customer_sk; + ds_key_t ss_sold_cdemo_sk; + ds_key_t ss_sold_hdemo_sk; + ds_key_t ss_sold_addr_sk; + ds_key_t ss_sold_store_sk; + ds_key_t ss_sold_promo_sk; + ds_key_t ss_ticket_number; + ds_pricing_t ss_pricing; +}; + +/* + * STORE_RETURNS table structure + */ +struct W_STORE_RETURNS_TBL { + ds_key_t sr_returned_date_sk; + ds_key_t sr_returned_time_sk; + ds_key_t sr_item_sk; + ds_key_t sr_customer_sk; + ds_key_t sr_cdemo_sk; + ds_key_t sr_hdemo_sk; + ds_key_t sr_addr_sk; + ds_key_t sr_store_sk; + ds_key_t sr_reason_sk; + ds_key_t sr_ticket_number; + ds_pricing_t sr_pricing; +}; + +typedef struct RNG_T { + int nUsed; + int nUsedPerRow; + long nSeed; + long nInitialSeed; /* used to allow skip_row() to back up */ + int nColumn; /* column where this stream is used */ + int nTable; /* table where this stream is used */ + int nDuplicateOf; /* duplicate streams allow independent tables to share + data streams */ +#ifdef JMS + ds_key_t nTotal; +#endif +} rng_t; + +struct W_DATE_TBL { + ds_key_t d_date_sk; + char d_date_id[RS_BKEY + 1]; + /* this is generated at output from d_date_sk */ + /* date_t d_date; */ + int d_month_seq; + int d_week_seq; + int d_quarter_seq; + int d_year; + int d_dow; + int d_moy; + int d_dom; + int d_qoy; + int d_fy_year; + int d_fy_quarter_seq; + int d_fy_week_seq; + char* d_day_name; + /* char d_quarter_name[RS_D_QUARTER_NAME + 1]; derived at print + * time */ + int d_holiday; + int d_weekend; + int d_following_holiday; + int d_first_dom; + int d_last_dom; + int d_same_day_ly; + int d_same_day_lq; + int d_current_day; + int d_current_week; + int d_current_month; + int d_current_quarter; + int d_current_year; +}; + +/* + * STORE table structure + */ +struct W_STORE_TBL { + ds_key_t store_sk; + char store_id[RS_BKEY + 1]; + ds_key_t rec_start_date_id; + ds_key_t rec_end_date_id; + ds_key_t closed_date_id; + char store_name[RS_W_STORE_NAME + 1]; + int employees; + int floor_space; + char* hours; + char store_manager[RS_W_STORE_MGR + 1]; + int market_id; + decimal_t dTaxPercentage; + char* geography_class; + char market_desc[RS_W_MARKET_DESC + 1]; + char market_manager[RS_W_MARKET_MGR + 1]; + ds_key_t division_id; + char* division_name; + ds_key_t company_id; + char* company_name; + ds_addr_t address; +}; + +/* + * CALL_CENTER table structure + */ +struct CALL_CENTER_TBL { + ds_key_t cc_call_center_sk; + char cc_call_center_id[RS_BKEY + 1]; + ds_key_t cc_rec_start_date_id; + ds_key_t cc_rec_end_date_id; + ds_key_t cc_closed_date_id; + ds_key_t cc_open_date_id; + char cc_name[RS_CC_NAME + 1]; + char* cc_class; + int cc_employees; + int cc_sq_ft; + char* cc_hours; + char cc_manager[RS_CC_MANAGER + 1]; + int cc_market_id; + char cc_market_class[RS_CC_MARKET_CLASS + 1]; + char cc_market_desc[RS_CC_MARKET_DESC + 1]; + char cc_market_manager[RS_CC_MARKET_MANAGER + 1]; + int cc_division_id; + char cc_division_name[RS_CC_DIVISION_NAME + 1]; + int cc_company; + char cc_company_name[RS_CC_COMPANY_NAME + 1]; + ds_addr_t cc_address; + decimal_t cc_tax_percentage; +}; + +struct SCALING_T { + ds_key_t kBaseRowcount; + ds_key_t kNextInsertValue; + int nUpdatePercentage; + ds_key_t kDayRowcount[6]; +}; + +/* + * CATALOG_PAGE table structure + */ +struct CATALOG_PAGE_TBL { + ds_key_t cp_catalog_page_sk; + char cp_catalog_page_id[RS_BKEY + 1]; + ds_key_t cp_start_date_id; + ds_key_t cp_end_date_id; + char cp_department[RS_CP_DEPARTMENT + 1]; + int cp_catalog_number; + int cp_catalog_page_number; + char cp_description[RS_CP_DESCRIPTION + 1]; + char* cp_type; +}; + +/* + * CATALOG_RETURNS table structure + */ +struct W_CATALOG_RETURNS_TBL { + ds_key_t cr_returned_date_sk; + ds_key_t cr_returned_time_sk; + ds_key_t cr_item_sk; + ds_key_t cr_refunded_customer_sk; + ds_key_t cr_refunded_cdemo_sk; + ds_key_t cr_refunded_hdemo_sk; + ds_key_t cr_refunded_addr_sk; + ds_key_t cr_returning_customer_sk; + ds_key_t cr_returning_cdemo_sk; + ds_key_t cr_returning_hdemo_sk; + ds_key_t cr_returning_addr_sk; + ds_key_t cr_call_center_sk; + ds_key_t cr_catalog_page_sk; + ds_key_t cr_ship_mode_sk; + ds_key_t cr_warehouse_sk; + ds_key_t cr_reason_sk; + ds_key_t cr_order_number; + ds_pricing_t cr_pricing; + decimal_t cr_fee; + decimal_t cr_refunded_cash; + decimal_t cr_reversed_charge; + decimal_t cr_store_credit; + decimal_t cr_net_loss; +}; + +/* + * CATALOG_SALES table structure + */ +struct W_CATALOG_SALES_TBL { + ds_key_t cs_sold_date_sk; + ds_key_t cs_sold_time_sk; + ds_key_t cs_ship_date_sk; + ds_key_t cs_bill_customer_sk; + ds_key_t cs_bill_cdemo_sk; + ds_key_t cs_bill_hdemo_sk; + ds_key_t cs_bill_addr_sk; + ds_key_t cs_ship_customer_sk; + ds_key_t cs_ship_cdemo_sk; + ds_key_t cs_ship_hdemo_sk; + ds_key_t cs_ship_addr_sk; + ds_key_t cs_call_center_sk; + ds_key_t cs_catalog_page_sk; + ds_key_t cs_ship_mode_sk; + ds_key_t cs_warehouse_sk; + ds_key_t cs_sold_item_sk; + ds_key_t cs_promo_sk; + ds_key_t cs_order_number; + ds_pricing_t cs_pricing; +}; + +/* + * CUSTOMER table structure + */ +struct W_CUSTOMER_TBL { + ds_key_t c_customer_sk; + char c_customer_id[RS_BKEY + 1]; + ds_key_t c_current_cdemo_sk; + ds_key_t c_current_hdemo_sk; + ds_key_t c_current_addr_sk; + int c_first_shipto_date_id; + int c_first_sales_date_id; + char* c_salutation; + char* c_first_name; + char* c_last_name; + int c_preferred_cust_flag; + int c_birth_day; + int c_birth_month; + int c_birth_year; + char* c_birth_country; + char c_login[RS_C_LOGIN + 1] = {}; + char c_email_address[RS_C_EMAIL + 1]; + int c_last_review_date; +}; + +/* + * CUSTOMER_ADDRESS table structure + */ +struct W_CUSTOMER_ADDRESS_TBL { + ds_key_t ca_addr_sk; + char ca_addr_id[RS_BKEY + 1]; + ds_addr_t ca_address; + char* ca_location_type; +}; + +/* + * CUSTOMER_DEMOGRAPHICS table structure + */ +struct W_CUSTOMER_DEMOGRAPHICS_TBL { + ds_key_t cd_demo_sk; + char* cd_gender; + char* cd_marital_status; + char* cd_education_status; + int cd_purchase_estimate; + char* cd_credit_rating; + int cd_dep_count; + int cd_dep_employed_count; + int cd_dep_college_count; +}; + +/* + * INVENTORY table structure + */ +struct W_INVENTORY_TBL { + ds_key_t inv_date_sk; + ds_key_t inv_item_sk; + ds_key_t inv_warehouse_sk; + int inv_quantity_on_hand; +}; + +/* + * TIME_DIM table structure + */ +struct W_TIME_TBL { + ds_key_t t_time_sk; + char t_time_id[RS_BKEY + 1]; + int t_time; + int t_hour; + int t_minute; + int t_second; + char* t_am_pm; + char* t_shift; + char* t_sub_shift; + char* t_meal_time; +}; + +/* + * INCOME_BAND table structure + */ +struct W_INCOME_BAND_TBL { + int ib_income_band_id; + int ib_lower_bound; + int ib_upper_bound; +}; + +/* + * HOUSEHOLD_DEMOGRAPHICS table structure + */ +struct W_HOUSEHOLD_DEMOGRAPHICS_TBL { + ds_key_t hd_demo_sk; + ds_key_t hd_income_band_id; + char* hd_buy_potential; + int hd_dep_count; + int hd_vehicle_count; +}; + +/* + * SHIP_MODE table structure + */ +struct W_SHIP_MODE_TBL { + ds_key_t sm_ship_mode_sk; + char sm_ship_mode_id[RS_BKEY + 1]; + char* sm_type; + char* sm_code; + char* sm_carrier; + char sm_contract[RS_SM_CONTRACT + 1]; +}; + +/* + * PROMOTION table structure + */ +struct W_PROMOTION_TBL { + ds_key_t p_promo_sk; + char p_promo_id[RS_BKEY + 1]; + ds_key_t p_start_date_id; + ds_key_t p_end_date_id; + ds_key_t p_item_sk; + decimal_t p_cost; + int p_response_target; + char p_promo_name[RS_P_PROMO_NAME + 1]; + int p_channel_dmail; + int p_channel_email; + int p_channel_catalog; + int p_channel_tv; + int p_channel_radio; + int p_channel_press; + int p_channel_event; + int p_channel_demo; + char p_channel_details[RS_P_CHANNEL_DETAILS + 1]; + char* p_purpose; + int p_discount_active; +}; + +/* + * REASON table structure + */ +struct W_REASON_TBL { + ds_key_t r_reason_sk; + char r_reason_id[RS_BKEY + 1]; + char* r_reason_description; +}; + +/* + * WAREHOUSE table structure + */ +struct W_WAREHOUSE_TBL { + ds_key_t w_warehouse_sk; + char w_warehouse_id[RS_BKEY + 1]; + char w_warehouse_name[RS_W_WAREHOUSE_NAME + 1]; + int w_warehouse_sq_ft; + ds_addr_t w_address; +}; + +/* + * WEB_SALES table structure + */ +struct W_WEB_SALES_TBL { + ds_key_t ws_sold_date_sk; + ds_key_t ws_sold_time_sk; + ds_key_t ws_ship_date_sk; + ds_key_t ws_item_sk; + ds_key_t ws_bill_customer_sk; + ds_key_t ws_bill_cdemo_sk; + ds_key_t ws_bill_hdemo_sk; + ds_key_t ws_bill_addr_sk; + ds_key_t ws_ship_customer_sk; + ds_key_t ws_ship_cdemo_sk; + ds_key_t ws_ship_hdemo_sk; + ds_key_t ws_ship_addr_sk; + ds_key_t ws_web_page_sk; + ds_key_t ws_web_site_sk; + ds_key_t ws_ship_mode_sk; + ds_key_t ws_warehouse_sk; + ds_key_t ws_promo_sk; + ds_key_t ws_order_number; + ds_pricing_t ws_pricing; +}; + +/* + * WEB_RETURNS table structure + */ +struct W_WEB_RETURNS_TBL { + ds_key_t wr_returned_date_sk; + ds_key_t wr_returned_time_sk; + ds_key_t wr_item_sk; + ds_key_t wr_refunded_customer_sk; + ds_key_t wr_refunded_cdemo_sk; + ds_key_t wr_refunded_hdemo_sk; + ds_key_t wr_refunded_addr_sk; + ds_key_t wr_returning_customer_sk; + ds_key_t wr_returning_cdemo_sk; + ds_key_t wr_returning_hdemo_sk; + ds_key_t wr_returning_addr_sk; + ds_key_t wr_web_page_sk; + ds_key_t wr_reason_sk; + ds_key_t wr_order_number; + ds_pricing_t wr_pricing; +}; + +/* + * WEB_PAGE table structure + */ +struct W_WEB_PAGE_TBL { + ds_key_t wp_page_sk; + char wp_page_id[RS_BKEY + 1]; + char wp_site_id[RS_BKEY + 1]; + ds_key_t wp_rec_start_date_id; + ds_key_t wp_rec_end_date_id; + ds_key_t wp_creation_date_sk; + ds_key_t wp_access_date_sk; + int wp_autogen_flag; + ds_key_t wp_customer_sk; + char wp_url[RS_WP_URL + 1]; + char* wp_type; + int wp_char_count; + int wp_link_count; + int wp_image_count; + int wp_max_ad_count; +}; + +/* + * ITEM table structure + */ +struct W_ITEM_TBL { + ds_key_t i_item_sk; + char i_item_id[RS_BKEY + 1]; + ds_key_t i_rec_start_date_id; + ds_key_t i_rec_end_date_id; + char i_item_desc[RS_I_ITEM_DESC + 1]; + decimal_t i_current_price; /* list price */ + decimal_t i_wholesale_cost; + ds_key_t i_brand_id; + char i_brand[RS_I_BRAND + 1]; + ds_key_t i_class_id; + char* i_class; + ds_key_t i_category_id; + char* i_category; + ds_key_t i_manufact_id; + char i_manufact[RS_I_MANUFACT + 1]; + char* i_size; + char i_formulation[RS_I_FORMULATION + 1]; + char* i_color; + char* i_units; + char* i_container; + ds_key_t i_manager_id; + char i_product_name[RS_I_PRODUCT_NAME + 1]; + ds_key_t i_promo_sk; +}; + +/* + * WEB_SITE table structure + */ +struct W_WEB_SITE_TBL { + ds_key_t web_site_sk; + char web_site_id[RS_BKEY + 1]; + ds_key_t web_rec_start_date_id; + ds_key_t web_rec_end_date_id; + char web_name[RS_WEB_NAME + 1]; + ds_key_t web_open_date; + ds_key_t web_close_date; + char web_class[RS_WEB_CLASS + 1]; + char web_manager[RS_WEB_MANAGER + 1]; + int web_market_id; + char web_market_class[RS_WEB_MARKET_CLASS + 1]; + char web_market_desc[RS_WEB_MARKET_DESC + 1]; + char web_market_manager[RS_WEB_MARKET_MANAGER + 1]; + int web_company_id; + char web_company_name[RS_WEB_COMPANY_NAME + 1]; + ds_addr_t web_address; + decimal_t web_tax_percentage; +}; + +/* + * general table descriptions. + * NOTE: This table contains the constant elements in the table descriptions; it + * must be kept in sync with the declararions of assocaited functions, found in + * tdef_functions.h + */ + +typedef struct TDEF_T { + const char* name; /* -- name of the table; */ + const char* abreviation; /* -- shorthand name of the table */ + unsigned int flags; /* -- control table options */ + int nFirstColumn; /* -- first column/RNG for this table */ + int nLastColumn; /* -- last column/RNG for this table */ + int nTableIndex; /* used for rowcount calculations */ + int nParam; /* -- additional table param (revision count, child number, + etc.) */ + FILE* outfile; /* -- output destination */ + int nUpdateSize; /* -- percentage of base rowcount in each update set (basis + points) */ + int nNewRowPct; + int nNullPct; /* percentage of rows with nulls (basis points) */ + ds_key_t kNullBitMap; /* colums that should be NULL in the current row */ + ds_key_t kNotNullBitMap; /* columns that are defined NOT NULL */ + ds_key_t* + arSparseKeys; /* sparse key set for table; used if FL_SPARSE is set */ +} tdef; + +int read_file( + const char* param_name, + const char* arg, + DSDGenContext& dsdGenContext); +int usage( + const char* param_name, + const char* msg, + DSDGenContext& dsdGenContext); +int SetScaleIndex( + const char* szName, + const char* szValue, + DSDGenContext& dsdGenContext); +int printReleaseInfo( + const char* param, + const char* val, + DSDGenContext& dsdGenContext); +static void print_options( + struct OPTION_T* o, + int bShowOptional, + DSDGenContext& dsdGenContext); + +static folly::Synchronized> idx_; +static std::once_flag initFlag_; + +// DSDGenContext to access global variables. +struct DSDGenContext { + struct DBGEN_VERSION_TBL g_dbgen_version; + + struct W_STORE_SALES_TBL g_w_store_sales; + int *pStoreSalesItemPermutation, *pCatalogSalesItemPermutation, + *pWebSalesItemPermutation; + int nStoreSalesItemCount, nCatalogSalesItemCount, nWebSalesItemCount; + int nStoreSalesItemIndex, nCatalogSalesItemIndex, nWebSalesItemIndex; + ds_key_t jDate, kNewDateIndex; + int nTicketItemBase = 1; + + struct W_STORE_RETURNS_TBL g_w_store_returns; + struct DIST_T dist; + option_t options[26] = { + {"ABREVIATION", OPT_STR, 0, "build table with abreviation ", NULL, ""}, + {"DELIMITER", + OPT_STR | OPT_ADV, + 1, + "use as output field separator", + NULL, + "|"}, + {"DIR", OPT_STR, 2, "generate tables in directory ", NULL, "."}, + {"DISTRIBUTIONS", + OPT_STR | OPT_ADV, + 3, + "read distributions from file ", + NULL, + "NONE"}, + {"FORCE", + OPT_FLG | OPT_ADV, + 4, + "over-write data files without prompting", + NULL, + "N"}, + {"HELP", OPT_INT, 5, "display this message", usage, "0"}, + {"PARAMS", OPT_STR, 6, "read parameters from file ", read_file, ""}, + {"PROG", + OPT_STR | OPT_HIDE | OPT_SET, + 7, + "DO NOT MODIFY", + NULL, + "dsdgen"}, + {"QUIET", OPT_FLG, 8, "disable all output to stdout/stderr", NULL, "N"}, + {"SCALE", + OPT_STR, + 9, + "volume of data to generate in GB", + SetScaleIndex, + "1"}, + {"SUFFIX", + OPT_STR | OPT_ADV, + 10, + "use as output file suffix", + NULL, + ".dat"}, + {"TABLE", OPT_STR, 11, "build only table ", NULL, "ALL"}, + {"TERMINATE", + OPT_FLG | OPT_ADV, + 12, + "end each record with a field delimiter", + NULL, + "Y"}, + {"UPDATE", OPT_INT, 13, "generate update data set ", NULL, ""}, + {"VERBOSE", OPT_FLG, 14, "enable verbose output", NULL, "N"}, + {"_SCALE_INDEX", + OPT_INT | OPT_HIDE, + 15, + "Scale band; used for dist lookups", + NULL, + "1"}, + {"PARALLEL", OPT_INT, 16, "build data in separate chunks", NULL, ""}, + {"CHILD", + OPT_INT, + 17, + "generate th chunk of the parallelized data", + NULL, + "1"}, + {"CHKSEEDS", + OPT_FLG | OPT_HIDE, + 18, + "validate RNG usage for parallelism", + NULL, + "N"}, + {"RELEASE", + OPT_FLG, + 19, + "display the release information", + printReleaseInfo, + "N"}, + {"_FILTER", OPT_FLG, 20, "output data to stdout", NULL, "N"}, + {"VALIDATE", OPT_FLG, 21, "produce rows for data validation", NULL, "N"}, + {"VCOUNT", + OPT_INT | OPT_ADV, + 22, + "set number of validation rows to be produced", + NULL, + "50"}, + {"VSUFFIX", + OPT_STR | OPT_ADV, + 23, + "set file suffix for data validation", + NULL, + ".vld"}, + {"RNGSEED", OPT_INT | OPT_ADV, 24, "set RNG seed", NULL, "19620718"}}; + + char* params[23 + 2]; + + struct W_DATE_TBL g_w_date; + + struct W_STORE_TBL g_w_store; + + struct CALL_CENTER_TBL g_w_call_center; + + struct W_WEB_PAGE_TBL g_w_web_page; + + struct W_ITEM_TBL g_w_item; + + struct W_WEB_SITE_TBL g_w_web_site; + + struct CATALOG_PAGE_TBL g_w_catalog_page; + + struct W_CATALOG_RETURNS_TBL g_w_catalog_returns; + + struct W_CATALOG_SALES_TBL g_w_catalog_sales; + + struct W_CUSTOMER_TBL g_w_customer; + + struct W_CUSTOMER_ADDRESS_TBL g_w_customer_address; + + struct W_CUSTOMER_DEMOGRAPHICS_TBL g_w_customer_demographics; + + struct W_INVENTORY_TBL g_w_inventory; + + struct W_TIME_TBL g_w_time; + + struct W_INCOME_BAND_TBL g_w_income_band; + + struct W_HOUSEHOLD_DEMOGRAPHICS_TBL g_w_household_demographics; + + struct W_SHIP_MODE_TBL g_w_ship_mode; + + struct W_PROMOTION_TBL g_w_promotion; + + struct W_REASON_TBL g_w_reason; + + struct W_WAREHOUSE_TBL g_w_warehouse; + + struct W_WEB_SALES_TBL g_w_web_sales; + + struct W_WEB_RETURNS_TBL g_w_web_returns; + + SCALING_T arRowcount[MAX_TABLE + 1]; + + int arUpdateDates[6]; + int arInventoryUpdateDates[6]; + + int arScaleVolume[9] = {1, 10, 100, 300, 1000, 3000, 10000, 30000, 100000}; + + int init_rand_init; + int mk_address_init; + int setUpdateDateRange_init; + int mk_dbgen_version_init; + int getCatalogNumberFromPage_init; + int checkSeeds_init; + int dateScaling_init; + int mk_w_call_center_init; + int mk_w_catalog_page_init; + int mk_master_catalog_sales_init; + int dectostr_init; + int date_join_init; + int setSCDKeys_init; + int scd_join_init; + int matchSCDSK_init; + int skipDays_init; + int mk_w_catalog_returns_init; + int mk_detail_catalog_sales_init; + int mk_w_customer_init; + int mk_w_date_init; + int mk_w_inventory_init; + int mk_w_item_init; + int mk_w_promotion_init; + int mk_w_reason_init; + int mk_w_ship_mode_init; + int mk_w_store_returns_init; + int mk_master_store_sales_init; + int mk_master_web_sales_init; + int mk_detail_web_sales_init; + int mk_w_store_init; + int mk_w_web_page_init; + int mk_w_web_returns_init; + int mk_master_init; + int mk_detail_init; + int mk_w_web_site_init; + int mk_cust_init; + int mk_order_init; + int mk_part_init; + int mk_supp_init; + int dbg_text_init; + int find_dist_init; + int cp_join_init; + int web_join_init; + int set_pricing_init; + int init_params_init; + int get_rowcount_init; + + tdef s_tdefs[38] = { + {"s_brand", + "s_br", + FL_NOP | FL_SOURCE_DDL, + S_BRAND_START, + S_BRAND_END, + S_BRAND, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_customer_address", + "s_ca", + FL_SOURCE_DDL | FL_PASSTHRU, + S_CUSTOMER_ADDRESS_START, + S_CUSTOMER_ADDRESS_END, + S_CUSTOMER_ADDRESS, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_call_center", + "s_cc", + FL_SOURCE_DDL, + S_CALL_CENTER_START, + S_CALL_CENTER_END, + S_CALL_CENTER, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x02, + NULL}, + {"s_catalog", + "s_ct", + FL_SOURCE_DDL | FL_NOP, + S_CATALOG_START, + S_CATALOG_END, + S_CATALOG, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_catalog_order", + "s_cord", + FL_SOURCE_DDL | FL_PARENT | FL_DATE_BASED, + S_CATALOG_ORDER_START, + S_CATALOG_ORDER_END, + S_CATALOG_ORDER, + S_CATALOG_ORDER_LINEITEM, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_catalog_order_lineitem", + "s_cl", + FL_SOURCE_DDL | FL_CHILD | FL_PARENT, + S_CATALOG_ORDER_LINEITEM_START, + S_CATALOG_ORDER_LINEITEM_END, + S_CATALOG_ORDER_LINEITEM, + S_CATALOG_RETURNS, + NULL, + 0, + 0, + 0, + 0x0, + 0x07, + NULL}, + {"s_catalog_page", + "s_cp", + FL_SOURCE_DDL | FL_PASSTHRU, + S_CATALOG_PAGE_START, + S_CATALOG_PAGE_END, + S_CATALOG_PAGE, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x033, + NULL}, + {"s_catalog_promotional_item", + "s_ci", + FL_NOP | FL_SOURCE_DDL, + S_CATALOG_PROMOTIONAL_ITEM_START, + S_CATALOG_PROMOTIONAL_ITEM_END, + S_CATALOG_PROMOTIONAL_ITEM, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_catalog_returns", + "s_cr", + FL_SOURCE_DDL | FL_CHILD, + S_CATALOG_RETURNS_START, + S_CATALOG_RETURNS_END, + S_CATALOG_RETURNS, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0E, + NULL}, + {"s_category", + "s_cg", + FL_NOP | FL_SOURCE_DDL, + S_CATEGORY_START, + S_CATEGORY_END, + S_CATEGORY, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_class", + "s_cl", + FL_NOP | FL_SOURCE_DDL, + S_CLASS_START, + S_CLASS_END, + S_CLASS, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_company", + "s_co", + FL_NOP | FL_SOURCE_DDL, + S_COMPANY_START, + S_COMPANY_END, + S_COMPANY, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_customer", + "s_cu", + FL_SOURCE_DDL, + S_CUSTOMER_START, + S_CUSTOMER_END, + S_CUSTOMER, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_division", + "s_di", + FL_NOP | FL_SOURCE_DDL, + S_DIVISION_START, + S_DIVISION_END, + S_DIVISION, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_inventory", + "s_in", + FL_SOURCE_DDL | FL_DATE_BASED, + S_INVENTORY_START, + S_INVENTORY_END, + S_INVENTORY, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x07, + NULL}, + {"s_item", + "s_it", + FL_SOURCE_DDL, + S_ITEM_START, + S_ITEM_END, + S_ITEM, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_manager", + "s_mg", + FL_NOP | FL_SOURCE_DDL, + S_MANAGER_START, + S_MANAGER_END, + S_MANAGER, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_manufacturer", + "s_mn", + FL_NOP | FL_SOURCE_DDL, + S_MANUFACTURER_START, + S_MANUFACTURER_END, + S_MANUFACTURER, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_market", + "s_mk", + FL_NOP | FL_SOURCE_DDL, + S_MARKET_START, + S_MARKET_END, + S_MARKET, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_product", + "s_pr", + FL_NOP | FL_SOURCE_DDL, + S_PRODUCT_START, + S_PRODUCT_END, + S_PRODUCT, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_promotion", + "s_pm", + FL_SOURCE_DDL | FL_PASSTHRU, + S_PROMOTION_START, + S_PROMOTION_END, + S_PROMOTION, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_purchase", + "s_pu", + FL_SOURCE_DDL | FL_PARENT | FL_DATE_BASED, + S_PURCHASE_START, + S_PURCHASE_END, + S_PURCHASE, + S_PURCHASE_LINEITEM, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_purchase_lineitem", + "s_pl", + FL_SOURCE_DDL | FL_CHILD | FL_PARENT, + S_PURCHASE_LINEITEM_START, + S_PURCHASE_LINEITEM_END, + S_PURCHASE_LINEITEM, + S_STORE_RETURNS, + NULL, + 0, + 0, + 0, + 0x0, + 0x07, + NULL}, + {"s_reason", + "s_re", + FL_NOP | FL_SOURCE_DDL, + S_REASON_START, + S_REASON_END, + S_REASON, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_store", + "s_st", + FL_SOURCE_DDL, + S_STORE_START, + S_STORE_END, + S_STORE, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_store_promotional_item", + "s_sp", + FL_NOP | FL_SOURCE_DDL, + S_STORE_PROMOTIONAL_ITEM_START, + S_STORE_PROMOTIONAL_ITEM_END, + S_STORE_PROMOTIONAL_ITEM, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_store_returns", + "s_sr", + FL_SOURCE_DDL | FL_CHILD, + S_STORE_RETURNS_START, + S_STORE_RETURNS_END, + S_STORE_RETURNS, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0E, + NULL}, + {"s_subcategory", + "s_ct", + FL_NOP | FL_SOURCE_DDL, + S_SUBCATEGORY_START, + S_SUBCATEGORY_END, + S_SUBCATEGORY, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_subclass", + "s_sc", + FL_NOP | FL_SOURCE_DDL, + S_SUBCLASS_START, + S_SUBCLASS_END, + S_SUBCLASS, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_warehouse", + "s_.h", + FL_SOURCE_DDL, + S_WAREHOUSE_START, + S_WAREHOUSE_END, + S_WAREHOUSE, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_web_order", + "s_wo", + FL_SOURCE_DDL | FL_PARENT | FL_DATE_BASED, + S_WEB_ORDER_START, + S_WEB_ORDER_END, + S_WEB_ORDER, + S_WEB_ORDER_LINEITEM, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_web_order_lineitem", + "s_wl", + FL_SOURCE_DDL | FL_CHILD | FL_PARENT, + S_WEB_ORDER_LINEITEM_START, + S_WEB_ORDER_LINEITEM_END, + S_WEB_ORDER_LINEITEM, + S_WEB_RETURNS, + NULL, + 0, + 0, + 0, + 0x0, + 0x07, + NULL}, + {"s_web_page", + "s_wp", + FL_SOURCE_DDL | FL_PASSTHRU, + S_WEB_PAGE_START, + S_WEB_PAGE_END, + S_WEB_PAGE, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_web_promotional_item", + "s_wi", + FL_NOP | FL_SOURCE_DDL, + S_WEB_PROMOTIONAL_ITEM_START, + S_WEB_PROMOTIONAL_ITEM_END, + S_WEB_PROMOTIONAL_ITEM, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0, + NULL}, + {"s_web_returns", + "s_wr", + FL_SOURCE_DDL | FL_CHILD, + S_WEB_RETURNS_START, + S_WEB_RETURNS_END, + S_WEB_RETURNS, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x0E, + NULL}, + {"s_web_site", + "s_ws", + FL_SOURCE_DDL, + S_WEB_SITE_START, + S_WEB_SITE_END, + S_WEB_SITE, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x01, + NULL}, + {"s_zip_to_gmt", + "s_zi", + FL_SOURCE_DDL | FL_VPRINT, + S_ZIPG_START, + S_ZIPG_END, + S_ZIPG, + -1, + NULL, + 0, + 0, + 0, + 0x0, + 0x03, + NULL}, + {NULL}}; + + tdef w_tdefs[26] = { + {"call_center", + "cc", + FL_TYPE_2 | FL_SMALL, + CALL_CENTER_START, + CALL_CENTER_END, + CALL_CENTER, + -1, + NULL, + 0, + 0, + 100, + 0, + 0x0B, + NULL}, + {"catalog_page", + "cp", + 0, + CATALOG_PAGE_START, + CATALOG_PAGE_END, + CATALOG_PAGE, + -1, + NULL, + 0, + 0, + 200, + 0, + 0x03, + NULL}, + {"catalog_returns", + "cr", + FL_CHILD, + CATALOG_RETURNS_START, + CATALOG_RETURNS_END, + CATALOG_RETURNS, + -1, + NULL, + 0, + 0, + 400, + 0, + 0x10007, + NULL}, + {"catalog_sales", + "cs", + FL_PARENT | FL_DATE_BASED | FL_VPRINT, + CATALOG_SALES_START, + CATALOG_SALES_END, + CATALOG_SALES, + CATALOG_RETURNS, + NULL, + 0, + 0, + 100, + 0, + 0x28000, + NULL}, + {"customer", + "cu", + 0, + CUSTOMER_START, + CUSTOMER_END, + CUSTOMER, + -1, + NULL, + 0, + 0, + 700, + 0, + 0x13, + NULL}, + {"customer_address", + "ca", + 0, + CUSTOMER_ADDRESS_START, + CUSTOMER_ADDRESS_END, + CUSTOMER_ADDRESS, + -1, + NULL, + 0, + 0, + 600, + 0, + 0x03, + NULL}, + {"customer_demographics", + "cd", + 0, + CUSTOMER_DEMOGRAPHICS_START, + CUSTOMER_DEMOGRAPHICS_END, + CUSTOMER_DEMOGRAPHICS, + 823200, + NULL, + 0, + 0, + 0, + 0, + 0x1, + NULL}, + {"date_dim", + "da", + 0, + DATE_START, + DATE_END, + DATET, + -1, + NULL, + 0, + 0, + 0, + 0, + 0x03, + NULL}, + {"household_demographics", + "hd", + 0, + HOUSEHOLD_DEMOGRAPHICS_START, + HOUSEHOLD_DEMOGRAPHICS_END, + HOUSEHOLD_DEMOGRAPHICS, + 7200, + NULL, + 0, + 0, + 0, + 0, + 0x01, + NULL}, + {"income_band", + "ib", + 0, + INCOME_BAND_START, + INCOME_BAND_END, + INCOME_BAND, + -1, + NULL, + 0, + 0, + 0, + 0, + 0x1, + NULL}, + {"inventory", + "inv", + FL_DATE_BASED, + INVENTORY_START, + INVENTORY_END, + INVENTORY, + -1, + NULL, + 0, + 0, + 1000, + 0, + 0x07, + NULL}, + {"item", + "it", + FL_TYPE_2, + ITEM_START, + ITEM_END, + ITEM, + -1, + NULL, + 0, + 0, + 50, + 0, + 0x0B, + NULL}, + {"promotion", + "pr", + 0, + PROMOTION_START, + PROMOTION_END, + PROMOTION, + -1, + NULL, + 0, + 0, + 200, + 0, + 0x03, + NULL}, + {"reason", + "re", + 0, + REASON_START, + REASON_END, + REASON, + -1, + NULL, + 0, + 0, + 0, + 0, + 0x03, + NULL}, + {"ship_mode", + "sm", + 0, + SHIP_MODE_START, + SHIP_MODE_END, + SHIP_MODE, + -1, + NULL, + 0, + 0, + 0, + 0, + 0x03, + NULL}, + {"store", + "st", + FL_TYPE_2 | FL_SMALL, + STORE_START, + STORE_END, + STORE, + -1, + NULL, + 0, + 0, + 100, + 0, + 0xB, + NULL}, + {"store_returns", + "sr", + FL_CHILD, + STORE_RETURNS_START, + STORE_RETURNS_END, + STORE_RETURNS, + -1, + NULL, + 0, + 0, + 700, + 0, + 0x204, + NULL}, + {"store_sales", + "ss", + FL_PARENT | FL_DATE_BASED | FL_VPRINT, + STORE_SALES_START, + STORE_SALES_END, + STORE_SALES, + STORE_RETURNS, + NULL, + 0, + 0, + 900, + 0, + 0x204, + NULL}, + {"time_dim", + "ti", + 0, + TIME_START, + TIME_END, + TIME, + -1, + NULL, + 0, + 0, + 0, + 0, + 0x03, + NULL}, + {"warehouse", + "wa", + FL_SMALL, + WAREHOUSE_START, + WAREHOUSE_END, + WAREHOUSE, + -1, + NULL, + 0, + 0, + 200, + 0, + 0x03, + NULL}, + {"web_page", + "wp", + FL_TYPE_2, + WEB_PAGE_START, + WEB_PAGE_END, + WEB_PAGE, + -1, + NULL, + 0, + 0, + 250, + 0, + 0x0B, + NULL}, + {"web_returns", + "wr", + FL_CHILD, + WEB_RETURNS_START, + WEB_RETURNS_END, + WEB_RETURNS, + -1, + NULL, + 0, + 0, + 900, + 0, + 0x2004, + NULL}, + {"web_sales", + "ws", + FL_VPRINT | FL_PARENT | FL_DATE_BASED, + WEB_SALES_START, + WEB_SALES_END, + WEB_SALES, + WEB_RETURNS, + NULL, + 0, + 0, + 5, + 1100, + 0x20008, + NULL}, + {"web_site", + "web", + FL_TYPE_2 | FL_SMALL, + WEB_SITE_START, + WEB_SITE_END, + WEB_SITE, + -1, + NULL, + 0, + 0, + 100, + 0, + 0x0B, + NULL}, + {"dbgen_version", + "dv", + 0, + DBGEN_VERSION_START, + DBGEN_VERSION_END, + DBGEN_VERSION, + -1, + NULL, + 0, + 0, + 0, + 0, + 0, + NULL}, + {NULL}}; + + rng_t Streams[MAX_STREAM + 1] = { + {0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, CC_CALL_CENTER_SK, CALL_CENTER, CC_CALL_CENTER_SK, 0}, + {0, 15, 0, 0, CC_CALL_CENTER_ID, CALL_CENTER, CC_CALL_CENTER_ID, 0}, + {0, 10, 0, 0, CC_REC_START_DATE_ID, CALL_CENTER, CC_REC_START_DATE_ID, 0}, + {0, 1, 0, 0, CC_REC_END_DATE_ID, CALL_CENTER, CC_REC_END_DATE_ID, 0}, + {0, 4, 0, 0, CC_CLOSED_DATE_ID, CALL_CENTER, CC_CLOSED_DATE_ID, 0}, + {0, 10, 0, 0, CC_OPEN_DATE_ID, CALL_CENTER, CC_OPEN_DATE_ID, 0}, + {0, 0, 0, 0, CC_NAME, CALL_CENTER, CC_NAME, 0}, + {0, 2, 0, 0, CC_CLASS, CALL_CENTER, CC_CLASS, 0}, + {0, 1, 0, 0, CC_EMPLOYEES, CALL_CENTER, CC_EMPLOYEES, 0}, + {0, 1, 0, 0, CC_SQ_FT, CALL_CENTER, CC_SQ_FT, 0}, + {0, 1, 0, 0, CC_HOURS, CALL_CENTER, CC_HOURS, 0}, + {0, 2, 0, 0, CC_MANAGER, CALL_CENTER, CC_MANAGER, 0}, + {0, 1, 0, 0, CC_MARKET_ID, CALL_CENTER, CC_MARKET_ID, 0}, + {0, 50, 0, 0, CC_MARKET_CLASS, CALL_CENTER, CC_MARKET_CLASS, 0}, + {0, 50, 0, 0, CC_MARKET_DESC, CALL_CENTER, CC_MARKET_DESC, 0}, + {0, 2, 0, 0, CC_MARKET_MANAGER, CALL_CENTER, CC_MARKET_MANAGER, 0}, + {0, 2, 0, 0, CC_DIVISION, CALL_CENTER, CC_DIVISION, 0}, + {0, 2, 0, 0, CC_DIVISION_NAME, CALL_CENTER, CC_DIVISION_NAME, 0}, + {0, 2, 0, 0, CC_COMPANY, CALL_CENTER, CC_COMPANY, 0}, + {0, 2, 0, 0, CC_COMPANY_NAME, CALL_CENTER, CC_COMPANY_NAME, 0}, + {0, 0, 0, 0, CC_STREET_NUMBER, CALL_CENTER, CC_STREET_NUMBER, 0}, + {0, 0, 0, 0, CC_STREET_NAME, CALL_CENTER, CC_STREET_NAME, 0}, + {0, 0, 0, 0, CC_STREET_TYPE, CALL_CENTER, CC_STREET_TYPE, 0}, + {0, 0, 0, 0, CC_SUITE_NUMBER, CALL_CENTER, CC_SUITE_NUMBER, 0}, + {0, 0, 0, 0, CC_CITY, CALL_CENTER, CC_CITY, 0}, + {0, 0, 0, 0, CC_COUNTY, CALL_CENTER, CC_COUNTY, 0}, + {0, 0, 0, 0, CC_STATE, CALL_CENTER, CC_STATE, 0}, + {0, 0, 0, 0, CC_ZIP, CALL_CENTER, CC_ZIP, 0}, + {0, 0, 0, 0, CC_COUNTRY, CALL_CENTER, CC_COUNTRY, 0}, + {0, 0, 0, 0, CC_GMT_OFFSET, CALL_CENTER, CC_GMT_OFFSET, 0}, + {0, 15, 0, 0, CC_ADDRESS, CALL_CENTER, CC_ADDRESS, 0}, + {0, 1, 0, 0, CC_TAX_PERCENTAGE, CALL_CENTER, CC_TAX_PERCENTAGE, 0}, + {0, 1, 0, 0, CC_SCD, CALL_CENTER, CC_SCD, 0}, + {0, 2, 0, 0, CC_NULLS, CALL_CENTER, CC_NULLS, 0}, + {0, 1, 0, 0, CP_CATALOG_PAGE_SK, CATALOG_PAGE, CP_CATALOG_PAGE_SK, 0}, + {0, 1, 0, 0, CP_CATALOG_PAGE_ID, CATALOG_PAGE, CP_CATALOG_PAGE_ID, 0}, + {0, 1, 0, 0, CP_START_DATE_ID, CATALOG_PAGE, CP_START_DATE_ID, 0}, + {0, 1, 0, 0, CP_END_DATE_ID, CATALOG_PAGE, CP_END_DATE_ID, 0}, + {0, 1, 0, 0, CP_PROMO_ID, CATALOG_PAGE, CP_PROMO_ID, 0}, + {0, 1, 0, 0, CP_DEPARTMENT, CATALOG_PAGE, CP_DEPARTMENT, 0}, + {0, 1, 0, 0, CP_CATALOG_NUMBER, CATALOG_PAGE, CP_CATALOG_NUMBER, 0}, + {0, + 1, + 0, + 0, + CP_CATALOG_PAGE_NUMBER, + CATALOG_PAGE, + CP_CATALOG_PAGE_NUMBER, + 0}, + {0, 100, 0, 0, CP_DESCRIPTION, CATALOG_PAGE, S_CP_DESCRIPTION, 0}, + {0, 1, 0, 0, CP_TYPE, CATALOG_PAGE, CP_TYPE, 0}, + {0, 2, 0, 0, CP_NULLS, CATALOG_PAGE, CP_NULLS, 0}, + {0, + 28, + 0, + 0, + CR_RETURNED_DATE_SK, + CATALOG_RETURNS, + CR_RETURNED_DATE_SK, + 0}, + {0, + 28, + 0, + 0, + CR_RETURNED_TIME_SK, + CATALOG_RETURNS, + CR_RETURNED_TIME_SK, + 0}, + {0, 14, 0, 0, CR_ITEM_SK, CATALOG_RETURNS, CR_ITEM_SK, 0}, + {0, + 14, + 0, + 0, + CR_REFUNDED_CUSTOMER_SK, + CATALOG_RETURNS, + CR_REFUNDED_CUSTOMER_SK, + 0}, + {0, + 14, + 0, + 0, + CR_REFUNDED_CDEMO_SK, + CATALOG_RETURNS, + CR_REFUNDED_CDEMO_SK, + 0}, + {0, + 14, + 0, + 0, + CR_REFUNDED_HDEMO_SK, + CATALOG_RETURNS, + CR_REFUNDED_HDEMO_SK, + 0}, + {0, + 14, + 0, + 0, + CR_REFUNDED_ADDR_SK, + CATALOG_RETURNS, + CR_REFUNDED_ADDR_SK, + 0}, + {0, + 28, + 0, + 0, + CR_RETURNING_CUSTOMER_SK, + CATALOG_RETURNS, + CR_RETURNING_CUSTOMER_SK, + 0}, + {0, + 14, + 0, + 0, + CR_RETURNING_CDEMO_SK, + CATALOG_RETURNS, + CR_RETURNING_CDEMO_SK, + 0}, + {0, + 14, + 0, + 0, + CR_RETURNING_HDEMO_SK, + CATALOG_RETURNS, + CR_RETURNING_HDEMO_SK, + 0}, + {0, + 14, + 0, + 0, + CR_RETURNING_ADDR_SK, + CATALOG_RETURNS, + CR_RETURNING_ADDR_SK, + 0}, + {0, 0, 0, 0, CR_CALL_CENTER_SK, CATALOG_RETURNS, CR_CALL_CENTER_SK, 0}, + {0, 14, 0, 0, CR_CATALOG_PAGE_SK, CATALOG_RETURNS, CR_CATALOG_PAGE_SK, 0}, + {0, 14, 0, 0, CR_SHIP_MODE_SK, CATALOG_RETURNS, CR_SHIP_MODE_SK, 0}, + {0, 14, 0, 0, CR_WAREHOUSE_SK, CATALOG_RETURNS, CR_WAREHOUSE_SK, 0}, + {0, 14, 0, 0, CR_REASON_SK, CATALOG_RETURNS, CR_REASON_SK, 0}, + {0, 0, 0, 0, CR_ORDER_NUMBER, CATALOG_RETURNS, CR_ORDER_NUMBER, 0}, + {0, + 0, + 0, + 0, + CR_PRICING_QUANTITY, + CATALOG_RETURNS, + CR_PRICING_QUANTITY, + 0}, + {0, + 0, + 0, + 0, + CR_PRICING_NET_PAID, + CATALOG_RETURNS, + CR_PRICING_NET_PAID, + 0}, + {0, 0, 0, 0, CR_PRICING_EXT_TAX, CATALOG_RETURNS, CR_PRICING_EXT_TAX, 0}, + {0, + 0, + 0, + 0, + CR_PRICING_NET_PAID_INC_TAX, + CATALOG_RETURNS, + CR_PRICING_NET_PAID_INC_TAX, + 0}, + {0, 0, 0, 0, CR_PRICING_FEE, CATALOG_RETURNS, CR_PRICING_FEE, 0}, + {0, + 0, + 0, + 0, + CR_PRICING_EXT_SHIP_COST, + CATALOG_RETURNS, + CR_PRICING_EXT_SHIP_COST, + 0}, + {0, + 0, + 0, + 0, + CR_PRICING_REFUNDED_CASH, + CATALOG_RETURNS, + CR_PRICING_REFUNDED_CASH, + 0}, + {0, + 0, + 0, + 0, + CR_PRICING_REVERSED_CHARGE, + CATALOG_RETURNS, + CR_PRICING_REVERSED_CHARGE, + 0}, + {0, + 0, + 0, + 0, + CR_PRICING_STORE_CREDIT, + CATALOG_RETURNS, + CR_PRICING_STORE_CREDIT, + 0}, + {0, + 0, + 0, + 0, + CR_PRICING_NET_LOSS, + CATALOG_RETURNS, + CR_PRICING_NET_LOSS, + 0}, + {0, 28, 0, 0, CR_NULLS, CATALOG_RETURNS, CR_NULLS, 0}, + {0, 70, 0, 0, CR_PRICING, CATALOG_RETURNS, CR_PRICING, 0}, + {0, 1, 0, 0, CS_SOLD_DATE_SK, CATALOG_SALES, CS_SOLD_DATE_SK, 0}, + {0, 2, 0, 0, CS_SOLD_TIME_SK, CATALOG_SALES, CS_SOLD_TIME_SK, 0}, + {0, 14, 0, 0, CS_SHIP_DATE_SK, CATALOG_SALES, CS_SHIP_DATE_SK, 0}, + {0, 1, 0, 0, CS_BILL_CUSTOMER_SK, CATALOG_SALES, CS_BILL_CUSTOMER_SK, 0}, + {0, 1, 0, 0, CS_BILL_CDEMO_SK, CATALOG_SALES, CS_BILL_CDEMO_SK, 0}, + {0, 1, 0, 0, CS_BILL_HDEMO_SK, CATALOG_SALES, CS_BILL_HDEMO_SK, 0}, + {0, 1, 0, 0, CS_BILL_ADDR_SK, CATALOG_SALES, CS_BILL_ADDR_SK, 0}, + {0, 2, 0, 0, CS_SHIP_CUSTOMER_SK, CATALOG_SALES, CS_SHIP_CUSTOMER_SK, 0}, + {0, 1, 0, 0, CS_SHIP_CDEMO_SK, CATALOG_SALES, CS_SHIP_CDEMO_SK, 0}, + {0, 1, 0, 0, CS_SHIP_HDEMO_SK, CATALOG_SALES, CS_SHIP_HDEMO_SK, 0}, + {0, 1, 0, 0, CS_SHIP_ADDR_SK, CATALOG_SALES, CS_SHIP_ADDR_SK, 0}, + {0, 1, 0, 0, CS_CALL_CENTER_SK, CATALOG_SALES, CS_CALL_CENTER_SK, 0}, + {0, 42, 0, 0, CS_CATALOG_PAGE_SK, CATALOG_SALES, CS_CATALOG_PAGE_SK, 0}, + {0, 14, 0, 0, CS_SHIP_MODE_SK, CATALOG_SALES, CS_SHIP_MODE_SK, 0}, + {0, 14, 0, 0, CS_WAREHOUSE_SK, CATALOG_SALES, CS_WAREHOUSE_SK, 0}, + {0, 1, 0, 0, CS_SOLD_ITEM_SK, CATALOG_SALES, CS_SOLD_ITEM_SK, 0}, + {0, 14, 0, 0, CS_PROMO_SK, CATALOG_SALES, CS_PROMO_SK, 0}, + {0, 1, 0, 0, CS_ORDER_NUMBER, CATALOG_SALES, CS_ORDER_NUMBER, 0}, + {0, 0, 0, 0, CS_PRICING_QUANTITY, CATALOG_SALES, CS_PRICING_QUANTITY, 0}, + {0, + 0, + 0, + 0, + CS_PRICING_WHOLESALE_COST, + CATALOG_SALES, + CS_PRICING_WHOLESALE_COST, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_LIST_PRICE, + CATALOG_SALES, + CS_PRICING_LIST_PRICE, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_SALES_PRICE, + CATALOG_SALES, + CS_PRICING_SALES_PRICE, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_COUPON_AMT, + CATALOG_SALES, + CS_PRICING_COUPON_AMT, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_EXT_SALES_PRICE, + CATALOG_SALES, + CS_PRICING_EXT_SALES_PRICE, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_EXT_DISCOUNT_AMOUNT, + CATALOG_SALES, + CS_PRICING_EXT_DISCOUNT_AMOUNT, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_EXT_WHOLESALE_COST, + CATALOG_SALES, + CS_PRICING_EXT_WHOLESALE_COST, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_EXT_LIST_PRICE, + CATALOG_SALES, + CS_PRICING_EXT_LIST_PRICE, + 0}, + {0, 0, 0, 0, CS_PRICING_EXT_TAX, CATALOG_SALES, CS_PRICING_EXT_TAX, 0}, + {0, + 0, + 0, + 0, + CS_PRICING_EXT_SHIP_COST, + CATALOG_SALES, + CS_PRICING_EXT_SHIP_COST, + 0}, + {0, 0, 0, 0, CS_PRICING_NET_PAID, CATALOG_SALES, CS_PRICING_NET_PAID, 0}, + {0, + 0, + 0, + 0, + CS_PRICING_NET_PAID_INC_TAX, + CATALOG_SALES, + CS_PRICING_NET_PAID_INC_TAX, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_NET_PAID_INC_SHIP, + CATALOG_SALES, + CS_PRICING_NET_PAID_INC_SHIP, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_NET_PAID_INC_SHIP_TAX, + CATALOG_SALES, + CS_PRICING_NET_PAID_INC_SHIP_TAX, + 0}, + {0, + 0, + 0, + 0, + CS_PRICING_NET_PROFIT, + CATALOG_SALES, + CS_PRICING_NET_PROFIT, + 0}, + {0, 112, 0, 0, CS_PRICING, CATALOG_SALES, CS_PRICING, 0}, + {0, 0, 0, 0, CS_PERMUTE, CATALOG_SALES, CS_PERMUTE, 0}, + {0, 28, 0, 0, CS_NULLS, CATALOG_SALES, CS_NULLS, 0}, + {0, 14, 0, 0, CR_IS_RETURNED, CATALOG_SALES, CR_IS_RETURNED, 0}, + {0, 0, 0, 0, CS_PERMUTATION, CATALOG_SALES, CS_PERMUTATION, 0}, + {0, 1, 0, 0, C_CUSTOMER_SK, CUSTOMER, C_CUSTOMER_SK, 0}, + {0, 1, 0, 0, C_CUSTOMER_ID, CUSTOMER, C_CUSTOMER_ID, 0}, + {0, 1, 0, 0, C_CURRENT_CDEMO_SK, CUSTOMER, C_CURRENT_CDEMO_SK, 0}, + {0, 1, 0, 0, C_CURRENT_HDEMO_SK, CUSTOMER, C_CURRENT_HDEMO_SK, 0}, + {0, 1, 0, 0, C_CURRENT_ADDR_SK, CUSTOMER, C_CURRENT_ADDR_SK, 0}, + {0, 0, 0, 0, C_FIRST_SHIPTO_DATE_ID, CUSTOMER, C_FIRST_SHIPTO_DATE_ID, 0}, + {0, 1, 0, 0, C_FIRST_SALES_DATE_ID, CUSTOMER, C_FIRST_SALES_DATE_ID, 0}, + {0, 1, 0, 0, C_SALUTATION, CUSTOMER, C_SALUTATION, 0}, + {0, 1, 0, 0, C_FIRST_NAME, CUSTOMER, C_FIRST_NAME, 0}, + {0, 1, 0, 0, C_LAST_NAME, CUSTOMER, C_LAST_NAME, 0}, + {0, 2, 0, 0, C_PREFERRED_CUST_FLAG, CUSTOMER, C_PREFERRED_CUST_FLAG, 0}, + {0, 1, 0, 0, C_BIRTH_DAY, CUSTOMER, C_BIRTH_DAY, 0}, + {0, 0, 0, 0, C_BIRTH_MONTH, CUSTOMER, C_BIRTH_MONTH, 0}, + {0, 0, 0, 0, C_BIRTH_YEAR, CUSTOMER, C_BIRTH_YEAR, 0}, + {0, 1, 0, 0, C_BIRTH_COUNTRY, CUSTOMER, C_BIRTH_COUNTRY, 0}, + {0, 1, 0, 0, C_LOGIN, CUSTOMER, C_LOGIN, 0}, + {0, 23, 0, 0, C_EMAIL_ADDRESS, CUSTOMER, C_EMAIL_ADDRESS, 0}, + {0, 1, 0, 0, C_LAST_REVIEW_DATE, CUSTOMER, C_LAST_REVIEW_DATE, 0}, + {0, 2, 0, 0, C_NULLS, CUSTOMER, C_NULLS, 0}, + {0, 1, 0, 0, CA_ADDRESS_SK, CUSTOMER_ADDRESS, CA_ADDRESS_SK, 0}, + {0, 1, 0, 0, CA_ADDRESS_ID, CUSTOMER_ADDRESS, CA_ADDRESS_ID, 0}, + {0, + 1, + 0, + 0, + CA_ADDRESS_STREET_NUM, + CUSTOMER_ADDRESS, + CA_ADDRESS_STREET_NUM, + 0}, + {0, + 1, + 0, + 0, + CA_ADDRESS_STREET_NAME1, + CUSTOMER_ADDRESS, + CA_ADDRESS_STREET_NAME1, + 0}, + {0, + 1, + 0, + 0, + CA_ADDRESS_STREET_TYPE, + CUSTOMER_ADDRESS, + CA_ADDRESS_STREET_TYPE, + 0}, + {0, + 1, + 0, + 0, + CA_ADDRESS_SUITE_NUM, + CUSTOMER_ADDRESS, + CA_ADDRESS_SUITE_NUM, + 0}, + {0, 1, 0, 0, CA_ADDRESS_CITY, CUSTOMER_ADDRESS, CA_ADDRESS_CITY, 0}, + {0, 1, 0, 0, CA_ADDRESS_COUNTY, CUSTOMER_ADDRESS, CA_ADDRESS_COUNTY, 0}, + {0, 1, 0, 0, CA_ADDRESS_STATE, CUSTOMER_ADDRESS, CA_ADDRESS_STATE, 0}, + {0, 1, 0, 0, CA_ADDRESS_ZIP, CUSTOMER_ADDRESS, CA_ADDRESS_ZIP, 0}, + {0, 1, 0, 0, CA_ADDRESS_COUNTRY, CUSTOMER_ADDRESS, CA_ADDRESS_COUNTRY, 0}, + {0, + 1, + 0, + 0, + CA_ADDRESS_GMT_OFFSET, + CUSTOMER_ADDRESS, + CA_ADDRESS_GMT_OFFSET, + 0}, + {0, 1, 0, 0, CA_LOCATION_TYPE, CUSTOMER_ADDRESS, CA_LOCATION_TYPE, 0}, + {0, 2, 0, 0, CA_NULLS, CUSTOMER_ADDRESS, CA_NULLS, 0}, + {0, 7, 0, 0, CA_ADDRESS, CUSTOMER_ADDRESS, CA_ADDRESS, 0}, + {0, + 1, + 0, + 0, + CA_ADDRESS_STREET_NAME2, + CUSTOMER_ADDRESS, + CA_ADDRESS_STREET_NAME2, + 0}, + {0, 1, 0, 0, CD_DEMO_SK, CUSTOMER_DEMOGRAPHICS, CD_DEMO_SK, 0}, + {0, 1, 0, 0, CD_GENDER, CUSTOMER_DEMOGRAPHICS, CD_GENDER, 0}, + {0, + 1, + 0, + 0, + CD_MARITAL_STATUS, + CUSTOMER_DEMOGRAPHICS, + CD_MARITAL_STATUS, + 0}, + {0, + 1, + 0, + 0, + CD_EDUCATION_STATUS, + CUSTOMER_DEMOGRAPHICS, + CD_EDUCATION_STATUS, + 0}, + {0, + 1, + 0, + 0, + CD_PURCHASE_ESTIMATE, + CUSTOMER_DEMOGRAPHICS, + CD_PURCHASE_ESTIMATE, + 0}, + {0, + 1, + 0, + 0, + CD_CREDIT_RATING, + CUSTOMER_DEMOGRAPHICS, + CD_CREDIT_RATING, + 0}, + {0, 1, 0, 0, CD_DEP_COUNT, CUSTOMER_DEMOGRAPHICS, CD_DEP_COUNT, 0}, + {0, + 1, + 0, + 0, + CD_DEP_EMPLOYED_COUNT, + CUSTOMER_DEMOGRAPHICS, + CD_DEP_EMPLOYED_COUNT, + 0}, + {0, + 1, + 0, + 0, + CD_DEP_COLLEGE_COUNT, + CUSTOMER_DEMOGRAPHICS, + CD_DEP_COLLEGE_COUNT, + 0}, + {0, 2, 0, 0, CD_NULLS, CUSTOMER_DEMOGRAPHICS, CD_NULLS, 0}, + {0, 0, 0, 0, D_DATE_SK, DATET, D_DATE_SK, 0}, + {0, 0, 0, 0, D_DATE_ID, DATET, D_DATE_ID, 0}, + {0, 0, 0, 0, D_DATE, DATET, D_DATE, 0}, + {0, 0, 0, 0, D_MONTH_SEQ, DATET, D_MONTH_SEQ, 0}, + {0, 0, 0, 0, D_WEEK_SEQ, DATET, D_WEEK_SEQ, 0}, + {0, 0, 0, 0, D_QUARTER_SEQ, DATET, D_QUARTER_SEQ, 0}, + {0, 0, 0, 0, D_YEAR, DATET, D_YEAR, 0}, + {0, 0, 0, 0, D_DOW, DATET, D_DOW, 0}, + {0, 0, 0, 0, D_MOY, DATET, D_MOY, 0}, + {0, 0, 0, 0, D_DOM, DATET, D_DOM, 0}, + {0, 0, 0, 0, D_QOY, DATET, D_QOY, 0}, + {0, 0, 0, 0, D_FY_YEAR, DATET, D_FY_YEAR, 0}, + {0, 0, 0, 0, D_FY_QUARTER_SEQ, DATET, D_FY_QUARTER_SEQ, 0}, + {0, 0, 0, 0, D_FY_WEEK_SEQ, DATET, D_FY_WEEK_SEQ, 0}, + {0, 0, 0, 0, D_DAY_NAME, DATET, D_DAY_NAME, 0}, + {0, 0, 0, 0, D_QUARTER_NAME, DATET, D_QUARTER_NAME, 0}, + {0, 0, 0, 0, D_HOLIDAY, DATET, D_HOLIDAY, 0}, + {0, 0, 0, 0, D_WEEKEND, DATET, D_WEEKEND, 0}, + {0, 0, 0, 0, D_FOLLOWING_HOLIDAY, DATET, D_FOLLOWING_HOLIDAY, 0}, + {0, 0, 0, 0, D_FIRST_DOM, DATET, D_FIRST_DOM, 0}, + {0, 0, 0, 0, D_LAST_DOM, DATET, D_LAST_DOM, 0}, + {0, 0, 0, 0, D_SAME_DAY_LY, DATET, D_SAME_DAY_LY, 0}, + {0, 0, 0, 0, D_SAME_DAY_LQ, DATET, D_SAME_DAY_LQ, 0}, + {0, 0, 0, 0, D_CURRENT_DAY, DATET, D_CURRENT_DAY, 0}, + {0, 0, 0, 0, D_CURRENT_WEEK, DATET, D_CURRENT_WEEK, 0}, + {0, 0, 0, 0, D_CURRENT_MONTH, DATET, D_CURRENT_MONTH, 0}, + {0, 0, 0, 0, D_CURRENT_QUARTER, DATET, D_CURRENT_QUARTER, 0}, + {0, 0, 0, 0, D_CURRENT_YEAR, DATET, D_CURRENT_YEAR, 0}, + {0, 2, 0, 0, D_NULLS, DATET, D_NULLS, 0}, + {0, 1, 0, 0, HD_DEMO_SK, HOUSEHOLD_DEMOGRAPHICS, HD_DEMO_SK, 0}, + {0, + 1, + 0, + 0, + HD_INCOME_BAND_ID, + HOUSEHOLD_DEMOGRAPHICS, + HD_INCOME_BAND_ID, + 0}, + {0, + 1, + 0, + 0, + HD_BUY_POTENTIAL, + HOUSEHOLD_DEMOGRAPHICS, + HD_BUY_POTENTIAL, + 0}, + {0, 1, 0, 0, HD_DEP_COUNT, HOUSEHOLD_DEMOGRAPHICS, HD_DEP_COUNT, 0}, + {0, + 1, + 0, + 0, + HD_VEHICLE_COUNT, + HOUSEHOLD_DEMOGRAPHICS, + HD_VEHICLE_COUNT, + 0}, + {0, 2, 0, 0, HD_NULLS, HOUSEHOLD_DEMOGRAPHICS, HD_NULLS, 0}, + {0, 1, 0, 0, IB_INCOME_BAND_ID, INCOME_BAND, IB_INCOME_BAND_ID, 0}, + {0, 1, 0, 0, IB_LOWER_BOUND, INCOME_BAND, IB_LOWER_BOUND, 0}, + {0, 1, 0, 0, IB_UPPER_BOUND, INCOME_BAND, IB_UPPER_BOUND, 0}, + {0, 2, 0, 0, IB_NULLS, INCOME_BAND, IB_NULLS, 0}, + {0, 1, 0, 0, INV_DATE_SK, INVENTORY, INV_DATE_SK, 0}, + {0, 1, 0, 0, INV_ITEM_SK, INVENTORY, INV_ITEM_SK, 0}, + {0, 1, 0, 0, INV_WAREHOUSE_SK, INVENTORY, INV_WAREHOUSE_SK, 0}, + {0, 1, 0, 0, INV_QUANTITY_ON_HAND, INVENTORY, INV_QUANTITY_ON_HAND, 0}, + {0, 2, 0, 0, INV_NULLS, INVENTORY, INV_NULLS, 0}, + {0, 1, 0, 0, I_ITEM_SK, ITEM, I_ITEM_SK, 0}, + {0, 1, 0, 0, I_ITEM_ID, ITEM, I_ITEM_ID, 0}, + {0, 1, 0, 0, I_REC_START_DATE_ID, ITEM, I_REC_START_DATE_ID, 0}, + {0, 2, 0, 0, I_REC_END_DATE_ID, ITEM, I_REC_END_DATE_ID, 0}, + {0, 200, 0, 0, I_ITEM_DESC, ITEM, S_ITEM_DESC, 0}, + {0, 2, 0, 0, I_CURRENT_PRICE, ITEM, I_CURRENT_PRICE, 0}, + {0, 1, 0, 0, I_WHOLESALE_COST, ITEM, I_WHOLESALE_COST, 0}, + {0, 1, 0, 0, I_BRAND_ID, ITEM, I_BRAND_ID, 0}, + {0, 1, 0, 0, I_BRAND, ITEM, I_BRAND, 0}, + {0, 1, 0, 0, I_CLASS_ID, ITEM, I_CLASS_ID, 0}, + {0, 1, 0, 0, I_CLASS, ITEM, I_CLASS, 0}, + {0, 1, 0, 0, I_CATEGORY_ID, ITEM, I_CATEGORY_ID, 0}, + {0, 1, 0, 0, I_CATEGORY, ITEM, I_CATEGORY, 0}, + {0, 2, 0, 0, I_MANUFACT_ID, ITEM, I_MANUFACT_ID, 0}, + {0, 1, 0, 0, I_MANUFACT, ITEM, I_MANUFACT, 0}, + {0, 1, 0, 0, I_SIZE, ITEM, I_SIZE, 0}, + {0, 50, 0, 0, I_FORMULATION, ITEM, I_FORMULATION, 0}, + {0, 1, 0, 0, I_COLOR, ITEM, I_COLOR, 0}, + {0, 1, 0, 0, I_UNITS, ITEM, I_UNITS, 0}, + {0, 1, 0, 0, I_CONTAINER, ITEM, I_CONTAINER, 0}, + {0, 2, 0, 0, I_MANAGER_ID, ITEM, I_MANAGER_ID, 0}, + {0, 1, 0, 0, I_PRODUCT_NAME, ITEM, I_PRODUCT_NAME, 0}, + {0, 2, 0, 0, I_NULLS, ITEM, I_NULLS, 0}, + {0, 1, 0, 0, I_SCD, ITEM, I_SCD, 0}, + {0, 2, 0, 0, I_PROMO_SK, ITEM, I_PROMO_SK, 0}, + {0, 1, 0, 0, P_PROMO_SK, PROMOTION, P_PROMO_SK, 0}, + {0, 1, 0, 0, P_PROMO_ID, PROMOTION, P_PROMO_ID, 0}, + {0, 1, 0, 0, P_START_DATE_ID, PROMOTION, P_START_DATE_ID, 0}, + {0, 1, 0, 0, P_END_DATE_ID, PROMOTION, P_END_DATE_ID, 0}, + {0, 1, 0, 0, P_ITEM_SK, PROMOTION, P_ITEM_SK, 0}, + {0, 1, 0, 0, P_COST, PROMOTION, P_COST, 0}, + {0, 1, 0, 0, P_RESPONSE_TARGET, PROMOTION, P_RESPONSE_TARGET, 0}, + {0, 1, 0, 0, P_PROMO_NAME, PROMOTION, P_PROMO_NAME, 0}, + {0, 1, 0, 0, P_CHANNEL_DMAIL, PROMOTION, P_CHANNEL_DMAIL, 0}, + {0, 1, 0, 0, P_CHANNEL_EMAIL, PROMOTION, P_CHANNEL_EMAIL, 0}, + {0, 1, 0, 0, P_CHANNEL_CATALOG, PROMOTION, P_CHANNEL_CATALOG, 0}, + {0, 1, 0, 0, P_CHANNEL_TV, PROMOTION, P_CHANNEL_TV, 0}, + {0, 1, 0, 0, P_CHANNEL_RADIO, PROMOTION, P_CHANNEL_RADIO, 0}, + {0, 1, 0, 0, P_CHANNEL_PRESS, PROMOTION, P_CHANNEL_PRESS, 0}, + {0, 1, 0, 0, P_CHANNEL_EVENT, PROMOTION, P_CHANNEL_EVENT, 0}, + {0, 1, 0, 0, P_CHANNEL_DEMO, PROMOTION, P_CHANNEL_DEMO, 0}, + {0, 100, 0, 0, P_CHANNEL_DETAILS, PROMOTION, P_CHANNEL_DETAILS, 0}, + {0, 1, 0, 0, P_PURPOSE, PROMOTION, P_PURPOSE, 0}, + {0, 1, 0, 0, P_DISCOUNT_ACTIVE, PROMOTION, P_DISCOUNT_ACTIVE, 0}, + {0, 2, 0, 0, P_NULLS, PROMOTION, P_NULLS, 0}, + {0, 1, 0, 0, R_REASON_SK, REASON, R_REASON_SK, 0}, + {0, 1, 0, 0, R_REASON_ID, REASON, R_REASON_ID, 0}, + {0, 1, 0, 0, R_REASON_DESCRIPTION, REASON, R_REASON_DESCRIPTION, 0}, + {0, 2, 0, 0, R_NULLS, REASON, R_NULLS, 0}, + {0, 1, 0, 0, SM_SHIP_MODE_SK, SHIP_MODE, SM_SHIP_MODE_SK, 0}, + {0, 1, 0, 0, SM_SHIP_MODE_ID, SHIP_MODE, SM_SHIP_MODE_ID, 0}, + {0, 1, 0, 0, SM_TYPE, SHIP_MODE, SM_TYPE, 0}, + {0, 1, 0, 0, SM_CODE, SHIP_MODE, SM_CODE, 0}, + {0, 21, 0, 0, SM_CONTRACT, SHIP_MODE, SM_CONTRACT, 0}, + {0, 1, 0, 0, SM_CARRIER, SHIP_MODE, SM_CARRIER, 0}, + {0, 2, 0, 0, SM_NULLS, SHIP_MODE, SM_NULLS, 0}, + {0, 1, 0, 0, W_STORE_SK, STORE, W_STORE_SK, 0}, + {0, 1, 0, 0, W_STORE_ID, STORE, W_STORE_ID, 0}, + {0, + 1, + 0, + 0, + W_STORE_REC_START_DATE_ID, + STORE, + W_STORE_REC_START_DATE_ID, + 0}, + {0, 2, 0, 0, W_STORE_REC_END_DATE_ID, STORE, W_STORE_REC_END_DATE_ID, 0}, + {0, 2, 0, 0, W_STORE_CLOSED_DATE_ID, STORE, W_STORE_CLOSED_DATE_ID, 0}, + {0, 0, 0, 0, W_STORE_NAME, STORE, W_STORE_NAME, 0}, + {0, 1, 0, 0, W_STORE_EMPLOYEES, STORE, W_STORE_EMPLOYEES, 0}, + {0, 1, 0, 0, W_STORE_FLOOR_SPACE, STORE, W_STORE_FLOOR_SPACE, 0}, + {0, 1, 0, 0, W_STORE_HOURS, STORE, W_STORE_HOURS, 0}, + {0, 2, 0, 0, W_STORE_MANAGER, STORE, W_STORE_MANAGER, 0}, + {0, 1, 0, 0, W_STORE_MARKET_ID, STORE, W_STORE_MARKET_ID, 0}, + {0, 1, 0, 0, W_STORE_TAX_PERCENTAGE, STORE, W_STORE_TAX_PERCENTAGE, 0}, + {0, 1, 0, 0, W_STORE_GEOGRAPHY_CLASS, STORE, W_STORE_GEOGRAPHY_CLASS, 0}, + {0, 100, 0, 0, W_STORE_MARKET_DESC, STORE, W_STORE_MARKET_DESC, 0}, + {0, 2, 0, 0, W_STORE_MARKET_MANAGER, STORE, W_STORE_MARKET_MANAGER, 0}, + {0, 1, 0, 0, W_STORE_DIVISION_ID, STORE, W_STORE_DIVISION_ID, 0}, + {0, 1, 0, 0, W_STORE_DIVISION_NAME, STORE, W_STORE_DIVISION_NAME, 0}, + {0, 1, 0, 0, W_STORE_COMPANY_ID, STORE, W_STORE_COMPANY_ID, 0}, + {0, 1, 0, 0, W_STORE_COMPANY_NAME, STORE, W_STORE_COMPANY_NAME, 0}, + {0, + 1, + 0, + 0, + W_STORE_ADDRESS_STREET_NUM, + STORE, + W_STORE_ADDRESS_STREET_NUM, + 0}, + {0, + 1, + 0, + 0, + W_STORE_ADDRESS_STREET_NAME1, + STORE, + W_STORE_ADDRESS_STREET_NAME1, + 0}, + {0, + 1, + 0, + 0, + W_STORE_ADDRESS_STREET_TYPE, + STORE, + W_STORE_ADDRESS_STREET_TYPE, + 0}, + {0, + 1, + 0, + 0, + W_STORE_ADDRESS_SUITE_NUM, + STORE, + W_STORE_ADDRESS_SUITE_NUM, + 0}, + {0, 1, 0, 0, W_STORE_ADDRESS_CITY, STORE, W_STORE_ADDRESS_CITY, 0}, + {0, 1, 0, 0, W_STORE_ADDRESS_COUNTY, STORE, W_STORE_ADDRESS_COUNTY, 0}, + {0, 1, 0, 0, W_STORE_ADDRESS_STATE, STORE, W_STORE_ADDRESS_STATE, 0}, + {0, 1, 0, 0, W_STORE_ADDRESS_ZIP, STORE, W_STORE_ADDRESS_ZIP, 0}, + {0, 1, 0, 0, W_STORE_ADDRESS_COUNTRY, STORE, W_STORE_ADDRESS_COUNTRY, 0}, + {0, + 1, + 0, + 0, + W_STORE_ADDRESS_GMT_OFFSET, + STORE, + W_STORE_ADDRESS_GMT_OFFSET, + 0}, + {0, 2, 0, 0, W_STORE_NULLS, STORE, W_STORE_NULLS, 0}, + {0, 1, 0, 0, W_STORE_TYPE, STORE, W_STORE_TYPE, 0}, + {0, 1, 0, 0, W_STORE_SCD, STORE, W_STORE_SCD, 0}, + {0, 7, 0, 0, W_STORE_ADDRESS, STORE, W_STORE_ADDRESS, 0}, + {0, 32, 0, 0, SR_RETURNED_DATE_SK, STORE_RETURNS, SR_RETURNED_DATE_SK, 0}, + {0, 32, 0, 0, SR_RETURNED_TIME_SK, STORE_RETURNS, SR_RETURNED_TIME_SK, 0}, + {0, 16, 0, 0, SR_ITEM_SK, STORE_RETURNS, SR_ITEM_SK, 0}, + {0, 16, 0, 0, SR_CUSTOMER_SK, STORE_RETURNS, SR_CUSTOMER_SK, 0}, + {0, 16, 0, 0, SR_CDEMO_SK, STORE_RETURNS, SR_CDEMO_SK, 0}, + {0, 16, 0, 0, SR_HDEMO_SK, STORE_RETURNS, SR_HDEMO_SK, 0}, + {0, 16, 0, 0, SR_ADDR_SK, STORE_RETURNS, SR_ADDR_SK, 0}, + {0, 16, 0, 0, SR_STORE_SK, STORE_RETURNS, SR_STORE_SK, 0}, + {0, 16, 0, 0, SR_REASON_SK, STORE_RETURNS, SR_REASON_SK, 0}, + {0, 16, 0, 0, SR_TICKET_NUMBER, STORE_RETURNS, SR_TICKET_NUMBER, 0}, + {0, 0, 0, 0, SR_PRICING_QUANTITY, STORE_RETURNS, SR_PRICING_QUANTITY, 0}, + {0, 0, 0, 0, SR_PRICING_NET_PAID, STORE_RETURNS, SR_PRICING_NET_PAID, 0}, + {0, 0, 0, 0, SR_PRICING_EXT_TAX, STORE_RETURNS, SR_PRICING_EXT_TAX, 0}, + {0, + 0, + 0, + 0, + SR_PRICING_NET_PAID_INC_TAX, + STORE_RETURNS, + SR_PRICING_NET_PAID_INC_TAX, + 0}, + {0, 0, 0, 0, SR_PRICING_FEE, STORE_RETURNS, SR_PRICING_FEE, 0}, + {0, + 0, + 0, + 0, + SR_PRICING_EXT_SHIP_COST, + STORE_RETURNS, + SR_PRICING_EXT_SHIP_COST, + 0}, + {0, + 0, + 0, + 0, + SR_PRICING_REFUNDED_CASH, + STORE_RETURNS, + SR_PRICING_REFUNDED_CASH, + 0}, + {0, + 0, + 0, + 0, + SR_PRICING_REVERSED_CHARGE, + STORE_RETURNS, + SR_PRICING_REVERSED_CHARGE, + 0}, + {0, + 0, + 0, + 0, + SR_PRICING_STORE_CREDIT, + STORE_RETURNS, + SR_PRICING_STORE_CREDIT, + 0}, + {0, 0, 0, 0, SR_PRICING_NET_LOSS, STORE_RETURNS, SR_PRICING_NET_LOSS, 0}, + {0, 80, 0, 0, SR_PRICING, STORE_RETURNS, SR_PRICING, 0}, + {0, 32, 0, 0, SR_NULLS, STORE_RETURNS, SR_NULLS, 0}, + {0, 2, 0, 0, SS_SOLD_DATE_SK, STORE_SALES, SS_SOLD_DATE_SK, 0}, + {0, 2, 0, 0, SS_SOLD_TIME_SK, STORE_SALES, SS_SOLD_TIME_SK, 0}, + {0, 1, 0, 0, SS_SOLD_ITEM_SK, STORE_SALES, SS_SOLD_ITEM_SK, 0}, + {0, 1, 0, 0, SS_SOLD_CUSTOMER_SK, STORE_SALES, SS_SOLD_CUSTOMER_SK, 0}, + {0, 1, 0, 0, SS_SOLD_CDEMO_SK, STORE_SALES, SS_SOLD_CDEMO_SK, 0}, + {0, 1, 0, 0, SS_SOLD_HDEMO_SK, STORE_SALES, SS_SOLD_HDEMO_SK, 0}, + {0, 1, 0, 0, SS_SOLD_ADDR_SK, STORE_SALES, SS_SOLD_ADDR_SK, 0}, + {0, 1, 0, 0, SS_SOLD_STORE_SK, STORE_SALES, SS_SOLD_STORE_SK, 0}, + {0, 16, 0, 0, SS_SOLD_PROMO_SK, STORE_SALES, SS_SOLD_PROMO_SK, 0}, + {0, 1, 0, 0, SS_TICKET_NUMBER, STORE_SALES, SS_TICKET_NUMBER, 0}, + {0, 1, 0, 0, SS_PRICING_QUANTITY, STORE_SALES, SS_PRICING_QUANTITY, 0}, + {0, + 0, + 0, + 0, + SS_PRICING_WHOLESALE_COST, + STORE_SALES, + SS_PRICING_WHOLESALE_COST, + 0}, + {0, + 0, + 0, + 0, + SS_PRICING_LIST_PRICE, + STORE_SALES, + SS_PRICING_LIST_PRICE, + 0}, + {0, + 0, + 0, + 0, + SS_PRICING_SALES_PRICE, + STORE_SALES, + SS_PRICING_SALES_PRICE, + 0}, + {0, + 0, + 0, + 0, + SS_PRICING_COUPON_AMT, + STORE_SALES, + SS_PRICING_COUPON_AMT, + 0}, + {0, + 0, + 0, + 0, + SS_PRICING_EXT_SALES_PRICE, + STORE_SALES, + SS_PRICING_EXT_SALES_PRICE, + 0}, + {0, + 0, + 0, + 0, + SS_PRICING_EXT_WHOLESALE_COST, + STORE_SALES, + SS_PRICING_EXT_WHOLESALE_COST, + 0}, + {0, + 0, + 0, + 0, + SS_PRICING_EXT_LIST_PRICE, + STORE_SALES, + SS_PRICING_EXT_LIST_PRICE, + 0}, + {0, 0, 0, 0, SS_PRICING_EXT_TAX, STORE_SALES, SS_PRICING_EXT_TAX, 0}, + {0, 0, 0, 0, SS_PRICING_NET_PAID, STORE_SALES, SS_PRICING_NET_PAID, 0}, + {0, + 0, + 0, + 0, + SS_PRICING_NET_PAID_INC_TAX, + STORE_SALES, + SS_PRICING_NET_PAID_INC_TAX, + 0}, + {0, + 0, + 0, + 0, + SS_PRICING_NET_PROFIT, + STORE_SALES, + SS_PRICING_NET_PROFIT, + 0}, + {0, 16, 0, 0, SR_IS_RETURNED, STORE_SALES, SR_IS_RETURNED, 0}, + {0, 128, 0, 0, SS_PRICING, STORE_SALES, SS_PRICING, 0}, + {0, 32, 0, 0, SS_NULLS, STORE_SALES, SS_NULLS, 0}, + {0, 0, 0, 0, SS_PERMUTATION, STORE_SALES, SS_PERMUTATION, 0}, + {0, 1, 0, 0, T_TIME_SK, TIME, T_TIME_SK, 0}, + {0, 1, 0, 0, T_TIME_ID, TIME, T_TIME_ID, 0}, + {0, 1, 0, 0, T_TIME, TIME, T_TIME, 0}, + {0, 1, 0, 0, T_HOUR, TIME, T_HOUR, 0}, + {0, 1, 0, 0, T_MINUTE, TIME, T_MINUTE, 0}, + {0, 1, 0, 0, T_SECOND, TIME, T_SECOND, 0}, + {0, 1, 0, 0, T_AM_PM, TIME, T_AM_PM, 0}, + {0, 1, 0, 0, T_SHIFT, TIME, T_SHIFT, 0}, + {0, 1, 0, 0, T_SUB_SHIFT, TIME, T_SUB_SHIFT, 0}, + {0, 1, 0, 0, T_MEAL_TIME, TIME, T_MEAL_TIME, 0}, + {0, 2, 0, 0, T_NULLS, TIME, T_NULLS, 0}, + {0, 1, 0, 0, W_WAREHOUSE_SK, WAREHOUSE, W_WAREHOUSE_SK, 0}, + {0, 1, 0, 0, W_WAREHOUSE_ID, WAREHOUSE, W_WAREHOUSE_ID, 0}, + {0, 80, 0, 0, W_WAREHOUSE_NAME, WAREHOUSE, W_WAREHOUSE_NAME, 0}, + {0, 1, 0, 0, W_WAREHOUSE_SQ_FT, WAREHOUSE, W_WAREHOUSE_SQ_FT, 0}, + {0, 1, 0, 0, W_ADDRESS_STREET_NUM, WAREHOUSE, W_ADDRESS_STREET_NUM, 0}, + {0, + 1, + 0, + 0, + W_ADDRESS_STREET_NAME1, + WAREHOUSE, + W_ADDRESS_STREET_NAME1, + 0}, + {0, 1, 0, 0, W_ADDRESS_STREET_TYPE, WAREHOUSE, W_ADDRESS_STREET_TYPE, 0}, + {0, 1, 0, 0, W_ADDRESS_SUITE_NUM, WAREHOUSE, W_ADDRESS_SUITE_NUM, 0}, + {0, 1, 0, 0, W_ADDRESS_CITY, WAREHOUSE, W_ADDRESS_CITY, 0}, + {0, 1, 0, 0, W_ADDRESS_COUNTY, WAREHOUSE, W_ADDRESS_COUNTY, 0}, + {0, 1, 0, 0, W_ADDRESS_STATE, WAREHOUSE, W_ADDRESS_STATE, 0}, + {0, 1, 0, 0, W_ADDRESS_ZIP, WAREHOUSE, W_ADDRESS_ZIP, 0}, + {0, 1, 0, 0, W_ADDRESS_COUNTRY, WAREHOUSE, W_ADDRESS_COUNTRY, 0}, + {0, 1, 0, 0, W_ADDRESS_GMT_OFFSET, WAREHOUSE, W_ADDRESS_GMT_OFFSET, 0}, + {0, 2, 0, 0, W_NULLS, WAREHOUSE, W_NULLS, 0}, + {0, 7, 0, 0, W_WAREHOUSE_ADDRESS, WAREHOUSE, W_WAREHOUSE_ADDRESS, 0}, + {0, 1, 0, 0, WP_PAGE_SK, WEB_PAGE, WP_PAGE_SK, 0}, + {0, 1, 0, 0, WP_PAGE_ID, WEB_PAGE, WP_PAGE_ID, 0}, + {0, 1, 0, 0, WP_REC_START_DATE_ID, WEB_PAGE, WP_REC_START_DATE_ID, 0}, + {0, 1, 0, 0, WP_REC_END_DATE_ID, WEB_PAGE, WP_REC_END_DATE_ID, 0}, + {0, 2, 0, 0, WP_CREATION_DATE_SK, WEB_PAGE, WP_CREATION_DATE_SK, 0}, + {0, 1, 0, 0, WP_ACCESS_DATE_SK, WEB_PAGE, WP_ACCESS_DATE_SK, 0}, + {0, 1, 0, 0, WP_AUTOGEN_FLAG, WEB_PAGE, WP_AUTOGEN_FLAG, 0}, + {0, 1, 0, 0, WP_CUSTOMER_SK, WEB_PAGE, WP_CUSTOMER_SK, 0}, + {0, 1, 0, 0, WP_URL, WEB_PAGE, WP_URL, 0}, + {0, 1, 0, 0, WP_TYPE, WEB_PAGE, WP_TYPE, 0}, + {0, 1, 0, 0, WP_CHAR_COUNT, WEB_PAGE, WP_CHAR_COUNT, 0}, + {0, 1, 0, 0, WP_LINK_COUNT, WEB_PAGE, WP_LINK_COUNT, 0}, + {0, 1, 0, 0, WP_IMAGE_COUNT, WEB_PAGE, WP_IMAGE_COUNT, 0}, + {0, 1, 0, 0, WP_MAX_AD_COUNT, WEB_PAGE, WP_MAX_AD_COUNT, 0}, + {0, 2, 0, 0, WP_NULLS, WEB_PAGE, WP_NULLS, 0}, + {0, 1, 0, 0, WP_SCD, WEB_PAGE, WP_SCD, 0}, + {0, 32, 0, 0, WR_RETURNED_DATE_SK, WEB_RETURNS, WR_RETURNED_DATE_SK, 0}, + {0, 32, 0, 0, WR_RETURNED_TIME_SK, WEB_RETURNS, WR_RETURNED_TIME_SK, 0}, + {0, 16, 0, 0, WR_ITEM_SK, WEB_RETURNS, WR_ITEM_SK, 0}, + {0, + 16, + 0, + 0, + WR_REFUNDED_CUSTOMER_SK, + WEB_RETURNS, + WR_REFUNDED_CUSTOMER_SK, + 0}, + {0, 16, 0, 0, WR_REFUNDED_CDEMO_SK, WEB_RETURNS, WR_REFUNDED_CDEMO_SK, 0}, + {0, 16, 0, 0, WR_REFUNDED_HDEMO_SK, WEB_RETURNS, WR_REFUNDED_HDEMO_SK, 0}, + {0, 16, 0, 0, WR_REFUNDED_ADDR_SK, WEB_RETURNS, WR_REFUNDED_ADDR_SK, 0}, + {0, + 16, + 0, + 0, + WR_RETURNING_CUSTOMER_SK, + WEB_RETURNS, + WR_RETURNING_CUSTOMER_SK, + 0}, + {0, + 16, + 0, + 0, + WR_RETURNING_CDEMO_SK, + WEB_RETURNS, + WR_RETURNING_CDEMO_SK, + 0}, + {0, + 16, + 0, + 0, + WR_RETURNING_HDEMO_SK, + WEB_RETURNS, + WR_RETURNING_HDEMO_SK, + 0}, + {0, 16, 0, 0, WR_RETURNING_ADDR_SK, WEB_RETURNS, WR_RETURNING_ADDR_SK, 0}, + {0, 16, 0, 0, WR_WEB_PAGE_SK, WEB_RETURNS, WR_WEB_PAGE_SK, 0}, + {0, 16, 0, 0, WR_REASON_SK, WEB_RETURNS, WR_REASON_SK, 0}, + {0, 0, 0, 0, WR_ORDER_NUMBER, WEB_RETURNS, WR_ORDER_NUMBER, 0}, + {0, 0, 0, 0, WR_PRICING_QUANTITY, WEB_RETURNS, WR_PRICING_QUANTITY, 0}, + {0, 0, 0, 0, WR_PRICING_NET_PAID, WEB_RETURNS, WR_PRICING_NET_PAID, 0}, + {0, 0, 0, 0, WR_PRICING_EXT_TAX, WEB_RETURNS, WR_PRICING_EXT_TAX, 0}, + {0, + 0, + 0, + 0, + WR_PRICING_NET_PAID_INC_TAX, + WEB_RETURNS, + WR_PRICING_NET_PAID_INC_TAX, + 0}, + {0, 0, 0, 0, WR_PRICING_FEE, WEB_RETURNS, WR_PRICING_FEE, 0}, + {0, + 0, + 0, + 0, + WR_PRICING_EXT_SHIP_COST, + WEB_RETURNS, + WR_PRICING_EXT_SHIP_COST, + 0}, + {0, + 0, + 0, + 0, + WR_PRICING_REFUNDED_CASH, + WEB_RETURNS, + WR_PRICING_REFUNDED_CASH, + 0}, + {0, + 0, + 0, + 0, + WR_PRICING_REVERSED_CHARGE, + WEB_RETURNS, + WR_PRICING_REVERSED_CHARGE, + 0}, + {0, + 0, + 0, + 0, + WR_PRICING_STORE_CREDIT, + WEB_RETURNS, + WR_PRICING_STORE_CREDIT, + 0}, + {0, 0, 0, 0, WR_PRICING_NET_LOSS, WEB_RETURNS, WR_PRICING_NET_LOSS, 0}, + {0, 80, 0, 0, WR_PRICING, WEB_RETURNS, WR_PRICING, 0}, + {0, 32, 0, 0, WR_NULLS, WEB_RETURNS, WR_NULLS, 0}, + {0, 2, 0, 0, WS_SOLD_DATE_SK, WEB_SALES, WS_SOLD_DATE_SK, 0}, + {0, 2, 0, 0, WS_SOLD_TIME_SK, WEB_SALES, WS_SOLD_TIME_SK, 0}, + {0, 16, 0, 0, WS_SHIP_DATE_SK, WEB_SALES, WS_SHIP_DATE_SK, 0}, + {0, 1, 0, 0, WS_ITEM_SK, WEB_SALES, WS_ITEM_SK, 0}, + {0, 1, 0, 0, WS_BILL_CUSTOMER_SK, WEB_SALES, WS_BILL_CUSTOMER_SK, 0}, + {0, 1, 0, 0, WS_BILL_CDEMO_SK, WEB_SALES, WS_BILL_CDEMO_SK, 0}, + {0, 1, 0, 0, WS_BILL_HDEMO_SK, WEB_SALES, WS_BILL_HDEMO_SK, 0}, + {0, 1, 0, 0, WS_BILL_ADDR_SK, WEB_SALES, WS_BILL_ADDR_SK, 0}, + {0, 2, 0, 0, WS_SHIP_CUSTOMER_SK, WEB_SALES, WS_SHIP_CUSTOMER_SK, 0}, + {0, 2, 0, 0, WS_SHIP_CDEMO_SK, WEB_SALES, WS_SHIP_CDEMO_SK, 0}, + {0, 1, 0, 0, WS_SHIP_HDEMO_SK, WEB_SALES, WS_SHIP_HDEMO_SK, 0}, + {0, 1, 0, 0, WS_SHIP_ADDR_SK, WEB_SALES, WS_SHIP_ADDR_SK, 0}, + {0, 16, 0, 0, WS_WEB_PAGE_SK, WEB_SALES, WS_WEB_PAGE_SK, 0}, + {0, 16, 0, 0, WS_WEB_SITE_SK, WEB_SALES, WS_WEB_SITE_SK, 0}, + {0, 16, 0, 0, WS_SHIP_MODE_SK, WEB_SALES, WS_SHIP_MODE_SK, 0}, + {0, 16, 0, 0, WS_WAREHOUSE_SK, WEB_SALES, WS_WAREHOUSE_SK, 0}, + {0, 16, 0, 0, WS_PROMO_SK, WEB_SALES, WS_PROMO_SK, 0}, + {0, 1, 0, 0, WS_ORDER_NUMBER, WEB_SALES, WS_ORDER_NUMBER, 0}, + {0, 1, 0, 0, WS_PRICING_QUANTITY, WEB_SALES, WS_PRICING_QUANTITY, 0}, + {0, + 1, + 0, + 0, + WS_PRICING_WHOLESALE_COST, + WEB_SALES, + WS_PRICING_WHOLESALE_COST, + 0}, + {0, 0, 0, 0, WS_PRICING_LIST_PRICE, WEB_SALES, WS_PRICING_LIST_PRICE, 0}, + {0, + 0, + 0, + 0, + WS_PRICING_SALES_PRICE, + WEB_SALES, + WS_PRICING_SALES_PRICE, + 0}, + {0, + 0, + 0, + 0, + WS_PRICING_EXT_DISCOUNT_AMT, + WEB_SALES, + WS_PRICING_EXT_DISCOUNT_AMT, + 0}, + {0, + 0, + 0, + 0, + WS_PRICING_EXT_SALES_PRICE, + WEB_SALES, + WS_PRICING_EXT_SALES_PRICE, + 0}, + {0, + 0, + 0, + 0, + WS_PRICING_EXT_WHOLESALE_COST, + WEB_SALES, + WS_PRICING_EXT_WHOLESALE_COST, + 0}, + {0, + 0, + 0, + 0, + WS_PRICING_EXT_LIST_PRICE, + WEB_SALES, + WS_PRICING_EXT_LIST_PRICE, + 0}, + {0, 0, 0, 0, WS_PRICING_EXT_TAX, WEB_SALES, WS_PRICING_EXT_TAX, 0}, + {0, 0, 0, 0, WS_PRICING_COUPON_AMT, WEB_SALES, WS_PRICING_COUPON_AMT, 0}, + {0, + 0, + 0, + 0, + WS_PRICING_EXT_SHIP_COST, + WEB_SALES, + WS_PRICING_EXT_SHIP_COST, + 0}, + {0, 0, 0, 0, WS_PRICING_NET_PAID, WEB_SALES, WS_PRICING_NET_PAID, 0}, + {0, + 0, + 0, + 0, + WS_PRICING_NET_PAID_INC_TAX, + WEB_SALES, + WS_PRICING_NET_PAID_INC_TAX, + 0}, + {0, + 0, + 0, + 0, + WS_PRICING_NET_PAID_INC_SHIP, + WEB_SALES, + WS_PRICING_NET_PAID_INC_SHIP, + 0}, + {0, + 0, + 0, + 0, + WS_PRICING_NET_PAID_INC_SHIP_TAX, + WEB_SALES, + WS_PRICING_NET_PAID_INC_SHIP_TAX, + 0}, + {0, 0, 0, 0, WS_PRICING_NET_PROFIT, WEB_SALES, WS_PRICING_NET_PROFIT, 0}, + {0, 128, 0, 0, WS_PRICING, WEB_SALES, WS_PRICING, 0}, + {0, 32, 0, 0, WS_NULLS, WEB_SALES, WS_NULLS, 0}, + {0, 16, 0, 0, WR_IS_RETURNED, WEB_SALES, WR_IS_RETURNED, 0}, + {0, 0, 0, 0, WS_PERMUTATION, WEB_SALES, WS_PERMUTATION, 0}, + {0, 1, 0, 0, WEB_SITE_SK, WEB_SITE, WEB_SITE_SK, 0}, + {0, 1, 0, 0, WEB_SITE_ID, WEB_SITE, WEB_SITE_ID, 0}, + {0, 1, 0, 0, WEB_REC_START_DATE_ID, WEB_SITE, WEB_REC_START_DATE_ID, 0}, + {0, 1, 0, 0, WEB_REC_END_DATE_ID, WEB_SITE, WEB_REC_END_DATE_ID, 0}, + {0, 1, 0, 0, WEB_NAME, WEB_SITE, WEB_NAME, 0}, + {0, 1, 0, 0, WEB_OPEN_DATE, WEB_SITE, WEB_OPEN_DATE, 0}, + {0, 1, 0, 0, WEB_CLOSE_DATE, WEB_SITE, WEB_CLOSE_DATE, 0}, + {0, 1, 0, 0, WEB_CLASS, WEB_SITE, WEB_CLASS, 0}, + {0, 2, 0, 0, WEB_MANAGER, WEB_SITE, WEB_MANAGER, 0}, + {0, 1, 0, 0, WEB_MARKET_ID, WEB_SITE, WEB_MARKET_ID, 0}, + {0, 20, 0, 0, WEB_MARKET_CLASS, WEB_SITE, WEB_MARKET_CLASS, 0}, + {0, 100, 0, 0, WEB_MARKET_DESC, WEB_SITE, WEB_MARKET_DESC, 0}, + {0, 2, 0, 0, WEB_MARKET_MANAGER, WEB_SITE, WEB_MARKET_MANAGER, 0}, + {0, 1, 0, 0, WEB_COMPANY_ID, WEB_SITE, WEB_COMPANY_ID, 0}, + {0, 1, 0, 0, WEB_COMPANY_NAME, WEB_SITE, WEB_COMPANY_NAME, 0}, + {0, 1, 0, 0, WEB_ADDRESS_STREET_NUM, WEB_SITE, WEB_ADDRESS_STREET_NUM, 0}, + {0, + 1, + 0, + 0, + WEB_ADDRESS_STREET_NAME1, + WEB_SITE, + WEB_ADDRESS_STREET_NAME1, + 0}, + {0, + 1, + 0, + 0, + WEB_ADDRESS_STREET_TYPE, + WEB_SITE, + WEB_ADDRESS_STREET_TYPE, + 0}, + {0, 1, 0, 0, WEB_ADDRESS_SUITE_NUM, WEB_SITE, WEB_ADDRESS_SUITE_NUM, 0}, + {0, 1, 0, 0, WEB_ADDRESS_CITY, WEB_SITE, WEB_ADDRESS_CITY, 0}, + {0, 1, 0, 0, WEB_ADDRESS_COUNTY, WEB_SITE, WEB_ADDRESS_COUNTY, 0}, + {0, 1, 0, 0, WEB_ADDRESS_STATE, WEB_SITE, WEB_ADDRESS_STATE, 0}, + {0, 1, 0, 0, WEB_ADDRESS_ZIP, WEB_SITE, WEB_ADDRESS_ZIP, 0}, + {0, 1, 0, 0, WEB_ADDRESS_COUNTRY, WEB_SITE, WEB_ADDRESS_COUNTRY, 0}, + {0, 1, 0, 0, WEB_ADDRESS_GMT_OFFSET, WEB_SITE, WEB_ADDRESS_GMT_OFFSET, 0}, + {0, 1, 0, 0, WEB_TAX_PERCENTAGE, WEB_SITE, WEB_TAX_PERCENTAGE, 0}, + {0, 2, 0, 0, WEB_NULLS, WEB_SITE, WEB_NULLS, 0}, + {0, 7, 0, 0, WEB_ADDRESS, WEB_SITE, WEB_ADDRESS, 0}, + {0, 70, 0, 0, WEB_SCD, WEB_SITE, WEB_SCD, 0}, + {0, 0, 0, 0, DV_VERSION, DBGEN_VERSION, DV_VERSION, 0}, + {0, 0, 0, 0, DV_CREATE_DATE, DBGEN_VERSION, DV_CREATE_DATE, 0}, + {0, 0, 0, 0, DV_CREATE_TIME, DBGEN_VERSION, DV_CREATE_TIME, 0}, + {0, 0, 0, 0, DV_CMDLINE_ARGS, DBGEN_VERSION, DV_CMDLINE_ARGS, 0}, + {0, 0, 0, 0, VALIDATE_STREAM, DBGEN_VERSION, VALIDATE_STREAM, 0}, + {0, 0, 0, 0, S_BRAND_ID, S_BRAND, S_BRAND_ID, 0}, + {0, 0, 0, 0, S_BRAND_SUBCLASS_ID, S_BRAND, S_BRAND_SUBCLASS_ID, 0}, + {0, 1, 0, 0, S_BRAND_MANAGER_ID, S_BRAND, S_BRAND_MANAGER_ID, 0}, + {0, + 1, + 0, + 0, + S_BRAND_MANUFACTURER_ID, + S_BRAND, + S_BRAND_MANUFACTURER_ID, + 0}, + {0, 6, 0, 0, S_BRAND_NAME, S_BRAND, S_BRAND_NAME, 0}, + {0, 0, 0, 0, S_CADR_ID, S_CUSTOMER_ADDRESS, S_CADR_ID, 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_STREET_NUMBER, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_STREET_NUMBER, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_STREET_NAME1, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_STREET_NAME1, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_STREET_NAME2, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_STREET_NAME2, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_STREET_TYPE, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_STREET_TYPE, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_SUITE_NUM, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_SUITE_NUM, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_CITY, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_CITY, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_COUNTY, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_COUNTY, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_STATE, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_STATE, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_ZIP, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_ZIP, + 0}, + {0, + 1, + 0, + 0, + S_CADR_ADDRESS_COUNTRY, + S_CUSTOMER_ADDRESS, + S_CADR_ADDRESS_COUNTRY, + 0}, + {0, 7, 0, 0, S_BADDR_ADDRESS, S_CUSTOMER_ADDRESS, CA_ADDRESS, 0}, + {0, 1, 0, 0, S_CALL_CENTER_ID, S_CALL_CENTER, S_CALL_CENTER_ID, 0}, + {0, + 1, + 0, + 0, + S_CALL_CENTER_DIVISION_ID, + S_CALL_CENTER, + S_CALL_CENTER_DIVISION_ID, + 0}, + {0, + 1, + 0, + 0, + S_CALL_CENTER_OPEN_DATE, + S_CALL_CENTER, + S_CALL_CENTER_OPEN_DATE, + 0}, + {0, + 0, + 0, + 0, + S_CALL_CENTER_CLOSED_DATE, + S_CALL_CENTER, + S_CALL_CENTER_CLOSED_DATE, + 0}, + {0, 0, 0, 0, S_CALL_CENTER_NAME, S_CALL_CENTER, S_CALL_CENTER_NAME, 0}, + {0, 0, 0, 0, S_CALL_CENTER_CLASS, S_CALL_CENTER, S_CALL_CENTER_CLASS, 0}, + {0, + 1, + 0, + 0, + S_CALL_CENTER_EMPLOYEES, + S_CALL_CENTER, + S_CALL_CENTER_EMPLOYEES, + 0}, + {0, 1, 0, 0, S_CALL_CENTER_SQFT, S_CALL_CENTER, S_CALL_CENTER_SQFT, 0}, + {0, 1, 0, 0, S_CALL_CENTER_HOURS, S_CALL_CENTER, S_CALL_CENTER_HOURS, 0}, + {0, + 1, + 0, + 0, + S_CALL_CENTER_MANAGER_ID, + S_CALL_CENTER, + S_CALL_CENTER_MANAGER_ID, + 0}, + {0, + 1, + 0, + 0, + S_CALL_CENTER_MARKET_ID, + S_CALL_CENTER, + S_CALL_CENTER_MARKET_ID, + 0}, + {0, + 1, + 0, + 0, + S_CALL_CENTER_ADDRESS_ID, + S_CALL_CENTER, + S_CALL_CENTER_ADDRESS_ID, + 0}, + {0, + 1, + 0, + 0, + S_CALL_CENTER_TAX_PERCENTAGE, + S_CALL_CENTER, + S_CALL_CENTER_TAX_PERCENTAGE, + 0}, + {0, 1, 0, 0, S_CALL_CENTER_SCD, S_CALL_CENTER, S_CALL_CENTER_SCD, 0}, + {0, 0, 0, 0, S_CATALOG_NUMBER, S_CATALOG, S_CATALOG_NUMBER, 0}, + {0, 1, 0, 0, S_CATALOG_START_DATE, S_CATALOG, S_CATALOG_START_DATE, 0}, + {0, 1, 0, 0, S_CATALOG_END_DATE, S_CATALOG, S_CATALOG_END_DATE, 0}, + {0, 10, 0, 0, S_CATALOG_DESC, S_CATALOG, S_CATALOG_DESC, 0}, + {0, 1, 0, 0, S_CATALOG_TYPE, S_CATALOG, S_CATALOG_TYPE, 0}, + {0, 0, 0, 0, S_CORD_ID, S_CATALOG_ORDER, S_CORD_ID, 0}, + {0, + 1, + 0, + 0, + S_CORD_BILL_CUSTOMER_ID, + S_CATALOG_ORDER, + S_CORD_BILL_CUSTOMER_ID, + 0}, + {0, + 2, + 0, + 0, + S_CORD_SHIP_CUSTOMER_ID, + S_CATALOG_ORDER, + S_CORD_SHIP_CUSTOMER_ID, + 0}, + {0, 1, 0, 0, S_CORD_ORDER_DATE, S_CATALOG_ORDER, S_CORD_ORDER_DATE, 0}, + {0, 1, 0, 0, S_CORD_ORDER_TIME, S_CATALOG_ORDER, S_CORD_ORDER_TIME, 0}, + {0, + 1, + 0, + 0, + S_CORD_SHIP_MODE_ID, + S_CATALOG_ORDER, + S_CORD_SHIP_MODE_ID, + 0}, + {0, + 1, + 0, + 0, + S_CORD_CALL_CENTER_ID, + S_CATALOG_ORDER, + S_CORD_CALL_CENTER_ID, + 0}, + {0, 1, 0, 0, S_CLIN_ITEM_ID, S_CATALOG_ORDER, S_CLIN_ITEM_ID, 0}, + {0, 100, 0, 0, S_CORD_COMMENT, S_CATALOG_ORDER, S_CORD_COMMENT, 0}, + {0, + 1, + 0, + 0, + S_CLIN_ORDER_ID, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_ORDER_ID, + 0}, + {0, + 0, + 0, + 0, + S_CLIN_LINE_NUMBER, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_LINE_NUMBER, + 0}, + {0, + 1, + 0, + 0, + S_CLIN_PROMOTION_ID, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_PROMOTION_ID, + 0}, + {0, + 1, + 0, + 0, + S_CLIN_QUANTITY, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_QUANTITY, + 0}, + {0, + 1, + 0, + 0, + S_CLIN_COUPON_AMT, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_COUPON_AMT, + 0}, + {0, + 1, + 0, + 0, + S_CLIN_WAREHOUSE_ID, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_WAREHOUSE_ID, + 0}, + {0, + 1, + 0, + 0, + S_CLIN_SHIP_DATE, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_SHIP_DATE, + 0}, + {0, + 1, + 0, + 0, + S_CLIN_CATALOG_ID, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_CATALOG_ID, + 0}, + {0, + 2, + 0, + 0, + S_CLIN_CATALOG_PAGE_ID, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_CATALOG_PAGE_ID, + 0}, + {0, 8, 0, 0, S_CLIN_PRICING, S_CATALOG_ORDER_LINEITEM, S_CLIN_PRICING, 0}, + {0, + 0, + 0, + 0, + S_CLIN_SHIP_COST, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_SHIP_COST, + 0}, + {0, + 1, + 0, + 0, + S_CLIN_IS_RETURNED, + S_CATALOG_ORDER_LINEITEM, + S_CLIN_IS_RETURNED, + 0}, + {0, 0, 0, 0, S_CLIN_PERMUTE, S_CATALOG_ORDER_LINEITEM, S_CLIN_PERMUTE, 0}, + {0, + 0, + 0, + 0, + S_CATALOG_PAGE_CATALOG_NUMBER, + S_CATALOG_PAGE, + S_CATALOG_PAGE_CATALOG_NUMBER, + 0}, + {0, + 0, + 0, + 0, + S_CATALOG_PAGE_NUMBER, + S_CATALOG_PAGE, + S_CATALOG_PAGE_NUMBER, + 0}, + {0, + 1, + 0, + 0, + S_CATALOG_PAGE_DEPARTMENT, + S_CATALOG_PAGE, + S_CATALOG_PAGE_DEPARTMENT, + 0}, + {0, 1, 0, 0, S_CP_ID, S_CATALOG_PAGE, S_CP_ID, 0}, + {0, 1, 0, 0, S_CP_START_DATE, S_CATALOG_PAGE, S_CP_START_DATE, 0}, + {0, 1, 0, 0, S_CP_END_DATE, S_CATALOG_PAGE, S_CP_END_DATE, 0}, + {0, 100, 0, 0, S_CP_DESCRIPTION, S_CATALOG_PAGE, CP_DESCRIPTION, 0}, + {0, 1, 0, 0, S_CP_TYPE, S_CATALOG_PAGE, S_CP_TYPE, 0}, + {0, + 1, + 0, + 0, + S_CATALOG_PROMOTIONAL_ITEM_CATALOG_NUMBER, + S_CATALOG_PROMOTIONAL_ITEM, + S_CATALOG_PROMOTIONAL_ITEM_CATALOG_NUMBER, + 0}, + {0, + 1, + 0, + 0, + S_CATALOG_PROMOTIONAL_ITEM_CATALOG_PAGE_NUMBER, + S_CATALOG_PROMOTIONAL_ITEM, + S_CATALOG_PROMOTIONAL_ITEM_CATALOG_PAGE_NUMBER, + 0}, + {0, + 1, + 0, + 0, + S_CATALOG_PROMOTIONAL_ITEM_ITEM_ID, + S_CATALOG_PROMOTIONAL_ITEM, + S_CATALOG_PROMOTIONAL_ITEM_ITEM_ID, + 0}, + {0, + 0, + 0, + 0, + S_CATALOG_PROMOTIONAL_ITEM_PROMOTION_ID, + S_CATALOG_PROMOTIONAL_ITEM, + S_CATALOG_PROMOTIONAL_ITEM_PROMOTION_ID, + 0}, + {0, + 9, + 0, + 0, + S_CRET_CALL_CENTER_ID, + S_CATALOG_RETURNS, + S_CRET_CALL_CENTER_ID, + 0}, + {0, 0, 0, 0, S_CRET_ORDER_ID, S_CATALOG_RETURNS, S_CRET_ORDER_ID, 0}, + {0, + 0, + 0, + 0, + S_CRET_LINE_NUMBER, + S_CATALOG_RETURNS, + S_CRET_LINE_NUMBER, + 0}, + {0, 0, 0, 0, S_CRET_ITEM_ID, S_CATALOG_RETURNS, S_CRET_ITEM_ID, 0}, + {0, + 0, + 0, + 0, + S_CRET_RETURN_CUSTOMER_ID, + S_CATALOG_RETURNS, + S_CRET_RETURN_CUSTOMER_ID, + 0}, + {0, + 0, + 0, + 0, + S_CRET_REFUND_CUSTOMER_ID, + S_CATALOG_RETURNS, + S_CRET_REFUND_CUSTOMER_ID, + 0}, + {0, 9, 0, 0, S_CRET_DATE, S_CATALOG_RETURNS, S_CRET_DATE, 0}, + {0, 18, 0, 0, S_CRET_TIME, S_CATALOG_RETURNS, S_CRET_TIME, 0}, + {0, 0, 0, 0, S_CRET_QUANTITY, S_CATALOG_RETURNS, S_CRET_QUANTITY, 0}, + {0, 0, 0, 0, S_CRET_AMOUNT, S_CATALOG_RETURNS, S_CRET_AMOUNT, 0}, + {0, 0, 0, 0, S_CRET_TAX, S_CATALOG_RETURNS, S_CRET_TAX, 0}, + {0, 0, 0, 0, S_CRET_FEE, S_CATALOG_RETURNS, S_CRET_FEE, 0}, + {0, 0, 0, 0, S_CRET_SHIP_COST, S_CATALOG_RETURNS, S_CRET_SHIP_COST, 0}, + {0, + 0, + 0, + 0, + S_CRET_REFUNDED_CASH, + S_CATALOG_RETURNS, + S_CRET_REFUNDED_CASH, + 0}, + {0, + 0, + 0, + 0, + S_CRET_REVERSED_CHARGE, + S_CATALOG_RETURNS, + S_CRET_REVERSED_CHARGE, + 0}, + {0, + 0, + 0, + 0, + S_CRET_MERCHANT_CREDIT, + S_CATALOG_RETURNS, + S_CRET_MERCHANT_CREDIT, + 0}, + {0, 9, 0, 0, S_CRET_REASON_ID, S_CATALOG_RETURNS, S_CRET_REASON_ID, 0}, + {0, 72, 0, 0, S_CRET_PRICING, S_CATALOG_RETURNS, S_CRET_PRICING, 0}, + {0, + 9, + 0, + 0, + S_CRET_SHIPMODE_ID, + S_CATALOG_RETURNS, + S_CRET_SHIPMODE_ID, + 0}, + {0, + 9, + 0, + 0, + S_CRET_WAREHOUSE_ID, + S_CATALOG_RETURNS, + S_CRET_WAREHOUSE_ID, + 0}, + {0, + 0, + 0, + 0, + S_CRET_CATALOG_PAGE_ID, + S_CATALOG_RETURNS, + S_CRET_CATALOG_PAGE_ID, + 0}, + {0, 0, 0, 0, S_CATEGORY_ID, S_CATEGORY, S_CATEGORY_ID, 0}, + {0, 0, 0, 0, S_CATEGORY_NAME, S_CATEGORY, S_CATEGORY_NAME, 0}, + {0, 10, 0, 0, S_CATEGORY_DESC, S_CATEGORY, S_CATEGORY_DESC, 0}, + {0, 0, 0, 0, S_CLASS_ID, S_CLASS, S_CLASS_ID, 0}, + {0, 1, 0, 0, S_CLASS_SUBCAT_ID, S_CLASS, S_CLASS_SUBCAT_ID, 0}, + {0, 10, 0, 0, S_CLASS_DESC, S_CLASS, S_CLASS_DESC, 0}, + {0, 0, 0, 0, S_COMPANY_ID, S_COMPANY, S_COMPANY_ID, 0}, + {0, 0, 0, 0, S_COMPANY_NAME, S_COMPANY, S_COMPANY_NAME, 0}, + {0, 0, 0, 0, S_CUST_ID, S_CUSTOMER, S_CUST_ID, 0}, + {0, 1, 0, 0, S_CUST_SALUTATION, S_CUSTOMER, S_CUST_SALUTATION, 0}, + {0, 1, 0, 0, S_CUST_LAST_NAME, S_CUSTOMER, S_CUST_LAST_NAME, 0}, + {0, 1, 0, 0, S_CUST_FIRST_NAME, S_CUSTOMER, S_CUST_FIRST_NAME, 0}, + {0, 1, 0, 0, S_CUST_PREFERRED_FLAG, S_CUSTOMER, S_CUST_PREFERRED_FLAG, 0}, + {0, 1, 0, 0, S_CUST_BIRTH_DATE, S_CUSTOMER, S_CUST_BIRTH_DATE, 0}, + {0, + 1, + 0, + 0, + S_CUST_FIRST_PURCHASE_DATE, + S_CUSTOMER, + S_CUST_FIRST_PURCHASE_DATE, + 0}, + {0, + 1, + 0, + 0, + S_CUST_FIRST_SHIPTO_DATE, + S_CUSTOMER, + S_CUST_FIRST_SHIPTO_DATE, + 0}, + {0, 1, 0, 0, S_CUST_BIRTH_COUNTRY, S_CUSTOMER, S_CUST_BIRTH_COUNTRY, 0}, + {0, 25, 0, 0, S_CUST_LOGIN, S_CUSTOMER, S_CUST_LOGIN, 0}, + {0, 23, 0, 0, S_CUST_EMAIL, S_CUSTOMER, S_CUST_EMAIL, 0}, + {0, 1, 0, 0, S_CUST_LAST_LOGIN, S_CUSTOMER, S_CUST_LAST_LOGIN, 0}, + {0, 1, 0, 0, S_CUST_LAST_REVIEW, S_CUSTOMER, S_CUST_LAST_REVIEW, 0}, + {0, + 4, + 0, + 0, + S_CUST_PRIMARY_MACHINE, + S_CUSTOMER, + S_CUST_PRIMARY_MACHINE, + 0}, + {0, + 4, + 0, + 0, + S_CUST_SECONDARY_MACHINE, + S_CUSTOMER, + S_CUST_SECONDARY_MACHINE, + 0}, + {0, 7, 0, 0, S_CUST_ADDRESS, S_CUSTOMER, S_CUST_ADDRESS, 0}, + {0, + 1, + 0, + 0, + S_CUST_ADDRESS_STREET_NUM, + S_CUSTOMER, + S_CUST_ADDRESS_STREET_NUM, + 0}, + {0, + 1, + 0, + 0, + S_CUST_ADDRESS_STREET_NAME1, + S_CUSTOMER, + S_CUST_ADDRESS_STREET_NAME1, + 0}, + {0, + 1, + 0, + 0, + S_CUST_ADDRESS_STREET_NAME2, + S_CUSTOMER, + S_CUST_ADDRESS_STREET_NAME2, + 0}, + {0, + 1, + 0, + 0, + S_CUST_ADDRESS_STREET_TYPE, + S_CUSTOMER, + S_CUST_ADDRESS_STREET_TYPE, + 0}, + {0, + 1, + 0, + 0, + S_CUST_ADDRESS_SUITE_NUM, + S_CUSTOMER, + S_CUST_ADDRESS_SUITE_NUM, + 0}, + {0, 1, 0, 0, S_CUST_ADDRESS_CITY, S_CUSTOMER, S_CUST_ADDRESS_CITY, 0}, + {0, 1, 0, 0, S_CUST_ADDRESS_ZIP, S_CUSTOMER, S_CUST_ADDRESS_ZIP, 0}, + {0, 1, 0, 0, S_CUST_ADDRESS_COUNTY, S_CUSTOMER, S_CUST_ADDRESS_COUNTY, 0}, + {0, 1, 0, 0, S_CUST_ADDRESS_STATE, S_CUSTOMER, S_CUST_ADDRESS_STATE, 0}, + {0, + 1, + 0, + 0, + S_CUST_ADDRESS_COUNTRY, + S_CUSTOMER, + S_CUST_ADDRESS_COUNTRY, + 0}, + {0, 1, 0, 0, S_CUST_LOCATION_TYPE, S_CUSTOMER, S_CUST_LOCATION_TYPE, 0}, + {0, 1, 0, 0, S_CUST_GENDER, S_CUSTOMER, S_CUST_GENDER, 0}, + {0, 1, 0, 0, S_CUST_MARITAL_STATUS, S_CUSTOMER, S_CUST_MARITAL_STATUS, 0}, + {0, 1, 0, 0, S_CUST_EDUCATION, S_CUSTOMER, S_CUST_EDUCATION, 0}, + {0, 1, 0, 0, S_CUST_CREDIT_RATING, S_CUSTOMER, S_CUST_CREDIT_RATING, 0}, + {0, + 1, + 0, + 0, + S_CUST_PURCHASE_ESTIMATE, + S_CUSTOMER, + S_CUST_PURCHASE_ESTIMATE, + 0}, + {0, 1, 0, 0, S_CUST_BUY_POTENTIAL, S_CUSTOMER, S_CUST_BUY_POTENTIAL, 0}, + {0, 1, 0, 0, S_CUST_DEPENDENT_CNT, S_CUSTOMER, S_CUST_DEPENDENT_CNT, 0}, + {0, 1, 0, 0, S_CUST_EMPLOYED_CNT, S_CUSTOMER, S_CUST_EMPLOYED_CNT, 0}, + {0, 1, 0, 0, S_CUST_COLLEGE_CNT, S_CUSTOMER, S_CUST_COLLEGE_CNT, 0}, + {0, 1, 0, 0, S_CUST_VEHICLE_CNT, S_CUSTOMER, S_CUST_VEHICLE_CNT, 0}, + {0, 1, 0, 0, S_CUST_INCOME, S_CUSTOMER, S_CUST_INCOME, 0}, + {0, 0, 0, 0, S_DIVISION_ID, S_DIVISION, S_DIVISION_ID, 0}, + {0, 0, 0, 0, S_DIVISION_COMPANY, S_DIVISION, S_DIVISION_COMPANY, 0}, + {0, 0, 0, 0, S_DIVISION_NAME, S_DIVISION, S_DIVISION_NAME, 0}, + {0, 1, 0, 0, S_INVN_WAREHOUSE, S_INVENTORY, S_INVN_WAREHOUSE, 0}, + {0, 1, 0, 0, S_INVN_ITEM, S_INVENTORY, S_INVN_ITEM, 0}, + {0, 2, 0, 0, S_INVN_DATE, S_INVENTORY, S_INVN_DATE, 0}, + {0, 1, 0, 0, S_INVN_QUANTITY, S_INVENTORY, S_INVN_QUANTITY, 0}, + {0, 1, 0, 0, S_ITEM_ID, S_ITEM, S_ITEM_ID, 0}, + {0, 0, 0, 0, S_ITEM_PERMUTE, S_ITEM, S_ITEM_PERMUTE, 0}, + {0, 1, 0, 0, S_ITEM_PRODUCT_ID, S_ITEM, S_ITEM_PRODUCT_ID, 0}, + {0, 200, 0, 0, S_ITEM_DESC, S_ITEM, I_ITEM_DESC, 0}, + {0, 2, 0, 0, S_ITEM_LIST_PRICE, S_ITEM, I_CURRENT_PRICE, 0}, + {0, 1, 0, 0, S_ITEM_WHOLESALE_COST, S_ITEM, I_WHOLESALE_COST, 0}, + {0, 1, 0, 0, S_ITEM_MANAGER_ID, S_ITEM, I_MANAGER_ID, 0}, + {0, 1, 0, 0, S_ITEM_SIZE, S_ITEM, I_SIZE, 0}, + {0, 50, 0, 0, S_ITEM_FORMULATION, S_ITEM, I_FORMULATION, 0}, + {0, 1, 0, 0, S_ITEM_FLAVOR, S_ITEM, I_COLOR, 0}, + {0, 1, 0, 0, S_ITEM_UNITS, S_ITEM, I_UNITS, 0}, + {0, 1, 0, 0, S_ITEM_CONTAINER, S_ITEM, I_CONTAINER, 0}, + {0, 1, 0, 0, S_ITEM_SCD, S_ITEM, I_SCD, 0}, + {0, 0, 0, 0, S_MANAGER_ID, S_MANAGER, S_MANAGER_ID, 0}, + {0, 2, 0, 0, S_MANAGER_NAME, S_MANAGER, S_MANAGER_NAME, 0}, + {0, 0, 0, 0, S_MANUFACTURER_ID, S_MANUFACTURER, S_MANUFACTURER_ID, 0}, + {0, 0, 0, 0, S_MANUFACTURER_NAME, S_MANUFACTURER, S_MANUFACTURER_NAME, 0}, + {0, 0, 0, 0, S_MARKET_ID, S_MARKET, S_MARKET_ID, 0}, + {0, 0, 0, 0, S_MARKET_CLASS_NAME, S_MARKET, S_MARKET_CLASS_NAME, 0}, + {0, 10, 0, 0, S_MARKET_DESC, S_MARKET, S_MARKET_DESC, 0}, + {0, 1, 0, 0, S_MARKET_MANAGER_ID, S_MARKET, S_MARKET_MANAGER_ID, 0}, + {0, 0, 0, 0, S_PRODUCT_ID, S_PRODUCT, S_PRODUCT_ID, 0}, + {0, 1, 0, 0, S_PRODUCT_BRAND_ID, S_PRODUCT, S_PRODUCT_BRAND_ID, 0}, + {0, 0, 0, 0, S_PRODUCT_NAME, S_PRODUCT, S_PRODUCT_NAME, 0}, + {0, 1, 0, 0, S_PRODUCT_TYPE, S_PRODUCT, S_PRODUCT_TYPE, 0}, + {0, 1, 0, 0, S_PROMOTION_ID, S_PROMOTION, S_PROMOTION_ID, 0}, + {0, 1, 0, 0, S_PROMOTION_ITEM_ID, S_PROMOTION, S_PROMOTION_ITEM_ID, 0}, + {0, + 1, + 0, + 0, + S_PROMOTION_START_DATE, + S_PROMOTION, + S_PROMOTION_START_DATE, + 0}, + {0, 1, 0, 0, S_PROMOTION_END_DATE, S_PROMOTION, S_PROMOTION_END_DATE, 0}, + {0, 1, 0, 0, S_PROMOTION_COST, S_PROMOTION, S_PROMOTION_COST, 0}, + {0, + 1, + 0, + 0, + S_PROMOTION_RESPONSE_TARGET, + S_PROMOTION, + S_PROMOTION_RESPONSE_TARGET, + 0}, + {0, 0, 0, 0, S_PROMOTION_DMAIL, S_PROMOTION, S_PROMOTION_DMAIL, 0}, + {0, 0, 0, 0, S_PROMOTION_EMAIL, S_PROMOTION, S_PROMOTION_EMAIL, 0}, + {0, 0, 0, 0, S_PROMOTION_CATALOG, S_PROMOTION, S_PROMOTION_CATALOG, 0}, + {0, 0, 0, 0, S_PROMOTION_TV, S_PROMOTION, S_PROMOTION_TV, 0}, + {0, 0, 0, 0, S_PROMOTION_RADIO, S_PROMOTION, S_PROMOTION_RADIO, 0}, + {0, 0, 0, 0, S_PROMOTION_PRESS, S_PROMOTION, S_PROMOTION_PRESS, 0}, + {0, 0, 0, 0, S_PROMOTION_EVENT, S_PROMOTION, S_PROMOTION_EVENT, 0}, + {0, 0, 0, 0, S_PROMOTION_DEMO, S_PROMOTION, S_PROMOTION_DEMO, 0}, + {0, 100, 0, 0, S_PROMOTION_DETAILS, S_PROMOTION, P_CHANNEL_DETAILS, 0}, + {0, 1, 0, 0, S_PROMOTION_PURPOSE, S_PROMOTION, S_PROMOTION_PURPOSE, 0}, + {0, + 1, + 0, + 0, + S_PROMOTION_DISCOUNT_ACTIVE, + S_PROMOTION, + S_PROMOTION_DISCOUNT_ACTIVE, + 0}, + {0, + 1, + 0, + 0, + S_PROMOTION_DISCOUNT_PCT, + S_PROMOTION, + S_PROMOTION_DISCOUNT_PCT, + 0}, + {0, 0, 0, 0, S_PROMOTION_NAME, S_PROMOTION, S_PROMOTION_NAME, 0}, + {0, 1, 0, 0, S_PROMOTION_BITFIELD, S_PROMOTION, S_PROMOTION_BITFIELD, 0}, + {0, 0, 0, 0, S_PURCHASE_ID, S_PURCHASE, S_PURCHASE_ID, 0}, + {0, 1, 0, 0, S_PURCHASE_STORE_ID, S_PURCHASE, S_PURCHASE_STORE_ID, 0}, + {0, + 1, + 0, + 0, + S_PURCHASE_CUSTOMER_ID, + S_PURCHASE, + S_PURCHASE_CUSTOMER_ID, + 0}, + {0, 1, 0, 0, S_PURCHASE_DATE, S_PURCHASE, S_PURCHASE_DATE, 0}, + {0, 1, 0, 0, S_PURCHASE_TIME, S_PURCHASE, S_PURCHASE_TIME, 0}, + {0, 1, 0, 0, S_PURCHASE_REGISTER, S_PURCHASE, S_PURCHASE_REGISTER, 0}, + {0, 1, 0, 0, S_PURCHASE_CLERK, S_PURCHASE, S_PURCHASE_CLERK, 0}, + {0, 100, 0, 0, S_PURCHASE_COMMENT, S_PURCHASE, S_PURCHASE_COMMENT, 0}, + {0, 7, 0, 0, S_PURCHASE_PRICING, S_PURCHASE, S_PURCHASE_PRICING, 0}, + {0, 1, 0, 0, S_PLINE_ITEM_ID, S_PURCHASE, S_PLINE_ITEM_ID, 0}, + {0, + 12, + 0, + 0, + S_PLINE_PURCHASE_ID, + S_PURCHASE_LINEITEM, + S_PLINE_PURCHASE_ID, + 0}, + {0, 12, 0, 0, S_PLINE_NUMBER, S_PURCHASE_LINEITEM, S_PLINE_NUMBER, 0}, + {0, + 12, + 0, + 0, + S_PLINE_PROMOTION_ID, + S_PURCHASE_LINEITEM, + S_PLINE_PROMOTION_ID, + 0}, + {0, + 12, + 0, + 0, + S_PLINE_SALE_PRICE, + S_PURCHASE_LINEITEM, + S_PLINE_SALE_PRICE, + 0}, + {0, 12, 0, 0, S_PLINE_QUANTITY, S_PURCHASE_LINEITEM, S_PLINE_QUANTITY, 0}, + {0, + 12, + 0, + 0, + S_PLINE_COUPON_AMT, + S_PURCHASE_LINEITEM, + S_PLINE_COUPON_AMT, + 0}, + {0, 1200, 0, 0, S_PLINE_COMMENT, S_PURCHASE_LINEITEM, S_PLINE_COMMENT, 0}, + {0, 96, 0, 0, S_PLINE_PRICING, S_PURCHASE_LINEITEM, S_PLINE_PRICING, 0}, + {0, + 12, + 0, + 0, + S_PLINE_IS_RETURNED, + S_PURCHASE_LINEITEM, + S_PLINE_IS_RETURNED, + 0}, + {0, 0, 0, 0, S_PLINE_PERMUTE, S_PURCHASE_LINEITEM, S_PLINE_PERMUTE, 0}, + {0, 0, 0, 0, S_REASON_ID, S_REASON, S_REASON_ID, 0}, + {0, 10, 0, 0, S_REASON_DESC, S_REASON, S_REASON_DESC, 0}, + {0, 1, 0, 0, S_STORE_ID, S_STORE, S_STORE_ID, 0}, + {0, 1, 0, 0, S_STORE_ADDRESS_ID, S_STORE, S_STORE_ADDRESS_ID, 0}, + {0, 1, 0, 0, S_STORE_DIVISION_ID, S_STORE, S_STORE_DIVISION_ID, 0}, + {0, 1, 0, 0, S_STORE_OPEN_DATE, S_STORE, S_STORE_OPEN_DATE, 0}, + {0, 1, 0, 0, S_STORE_CLOSE_DATE, S_STORE, S_STORE_CLOSE_DATE, 0}, + {0, 0, 0, 0, S_STORE_NAME, S_STORE, S_STORE_NAME, 0}, + {0, 0, 0, 0, S_STORE_CLASS, S_STORE, S_STORE_CLASS, 0}, + {0, 1, 0, 0, S_STORE_EMPLOYEES, S_STORE, S_STORE_EMPLOYEES, 0}, + {0, 1, 0, 0, S_STORE_FLOOR_SPACE, S_STORE, S_STORE_FLOOR_SPACE, 0}, + {0, 1, 0, 0, S_STORE_HOURS, S_STORE, S_STORE_HOURS, 0}, + {0, + 0, + 0, + 0, + S_STORE_MARKET_MANAGER_ID, + S_STORE, + S_STORE_MARKET_MANAGER_ID, + 0}, + {0, 1, 0, 0, S_STORE_MANAGER_ID, S_STORE, S_STORE_MANAGER_ID, 0}, + {0, 1, 0, 0, S_STORE_MARKET_ID, S_STORE, S_STORE_MARKET_ID, 0}, + {0, + 1, + 0, + 0, + S_STORE_GEOGRAPHY_CLASS, + S_STORE, + S_STORE_GEOGRAPHY_CLASS, + 0}, + {0, 1, 0, 0, S_STORE_TAX_PERCENTAGE, S_STORE, S_STORE_TAX_PERCENTAGE, 0}, + {0, + 1, + 0, + 0, + S_SITM_PROMOTION_ID, + S_STORE_PROMOTIONAL_ITEM, + S_SITM_PROMOTION_ID, + 0}, + {0, 1, 0, 0, S_SITM_ITEM_ID, S_STORE_PROMOTIONAL_ITEM, S_SITM_ITEM_ID, 0}, + {0, + 1, + 0, + 0, + S_SITM_STORE_ID, + S_STORE_PROMOTIONAL_ITEM, + S_SITM_STORE_ID, + 0}, + {0, 0, 0, 0, S_SRET_STORE_ID, S_STORE_RETURNS, S_SRET_STORE_ID, 0}, + {0, 0, 0, 0, S_SRET_PURCHASE_ID, S_STORE_RETURNS, S_SRET_PURCHASE_ID, 0}, + {0, 0, 0, 0, S_SRET_LINENUMBER, S_STORE_RETURNS, S_SRET_LINENUMBER, 0}, + {0, 0, 0, 0, S_SRET_ITEM_ID, S_STORE_RETURNS, S_SRET_ITEM_ID, 0}, + {0, 0, 0, 0, S_SRET_CUSTOMER_ID, S_STORE_RETURNS, S_SRET_CUSTOMER_ID, 0}, + {0, 24, 0, 0, S_SRET_RETURN_DATE, S_STORE_RETURNS, S_SRET_RETURN_DATE, 0}, + {0, 12, 0, 0, S_SRET_RETURN_TIME, S_STORE_RETURNS, S_SRET_RETURN_TIME, 0}, + {0, + 0, + 0, + 0, + S_SRET_TICKET_NUMBER, + S_STORE_RETURNS, + S_SRET_TICKET_NUMBER, + 0}, + {0, + 0, + 0, + 0, + S_SRET_RETURN_QUANTITY, + S_STORE_RETURNS, + S_SRET_RETURN_QUANTITY, + 0}, + {0, 0, 0, 0, S_SRET_RETURN_AMT, S_STORE_RETURNS, S_SRET_RETURN_AMT, 0}, + {0, 0, 0, 0, S_SRET_RETURN_TAX, S_STORE_RETURNS, S_SRET_RETURN_TAX, 0}, + {0, 0, 0, 0, S_SRET_RETURN_FEE, S_STORE_RETURNS, S_SRET_RETURN_FEE, 0}, + {0, + 0, + 0, + 0, + S_SRET_RETURN_SHIP_COST, + S_STORE_RETURNS, + S_SRET_RETURN_SHIP_COST, + 0}, + {0, + 0, + 0, + 0, + S_SRET_REFUNDED_CASH, + S_STORE_RETURNS, + S_SRET_REFUNDED_CASH, + 0}, + {0, + 0, + 0, + 0, + S_SRET_REVERSED_CHARGE, + S_STORE_RETURNS, + S_SRET_REVERSED_CHARGE, + 0}, + {0, + 0, + 0, + 0, + S_SRET_MERCHANT_CREDIT, + S_STORE_RETURNS, + S_SRET_MERCHANT_CREDIT, + 0}, + {0, 12, 0, 0, S_SRET_REASON_ID, S_STORE_RETURNS, S_SRET_REASON_ID, 0}, + {0, 84, 0, 0, S_SRET_PRICING, S_STORE_RETURNS, S_SRET_PRICING, 0}, + {0, 0, 0, 0, S_SBCT_ID, S_SUBCATEGORY, S_SBCT_ID, 0}, + {0, 1, 0, 0, S_SBCT_CATEGORY_ID, S_SUBCATEGORY, S_SBCT_CATEGORY_ID, 0}, + {0, 0, 0, 0, S_SBCT_NAME, S_SUBCATEGORY, S_SBCT_NAME, 0}, + {0, 10, 0, 0, S_SBCT_DESC, S_SUBCATEGORY, S_SBCT_DESC, 0}, + {0, 0, 0, 0, S_SUBC_ID, S_SUBCLASS, S_SUBC_ID, 0}, + {0, 1, 0, 0, S_SUBC_CLASS_ID, S_SUBCLASS, S_SUBC_CLASS_ID, 0}, + {0, 0, 0, 0, S_SUBC_NAME, S_SUBCLASS, S_SUBC_NAME, 0}, + {0, 10, 0, 0, S_SUBC_DESC, S_SUBCLASS, S_SUBC_DESC, 0}, + {0, 1, 0, 0, S_WRHS_ID, S_WAREHOUSE, S_WRHS_ID, 0}, + {0, 10, 0, 0, S_WRHS_DESC, S_WAREHOUSE, S_WRHS_DESC, 0}, + {0, 1, 0, 0, S_WRHS_SQFT, S_WAREHOUSE, S_WRHS_SQFT, 0}, + {0, 1, 0, 0, S_WRHS_ADDRESS_ID, S_WAREHOUSE, S_WRHS_ADDRESS_ID, 0}, + {0, 1, 0, 0, S_WORD_ID, S_WEB_ORDER, S_WORD_ID, 0}, + {0, + 1, + 0, + 0, + S_WORD_BILL_CUSTOMER_ID, + S_WEB_ORDER, + S_WORD_BILL_CUSTOMER_ID, + 0}, + {0, + 2, + 0, + 0, + S_WORD_SHIP_CUSTOMER_ID, + S_WEB_ORDER, + S_WORD_SHIP_CUSTOMER_ID, + 0}, + {0, 1, 0, 0, S_WORD_ORDER_DATE, S_WEB_ORDER, S_WORD_ORDER_DATE, 0}, + {0, 1, 0, 0, S_WORD_ORDER_TIME, S_WEB_ORDER, S_WORD_ORDER_TIME, 0}, + {0, 1, 0, 0, S_WORD_SHIP_MODE_ID, S_WEB_ORDER, S_WORD_SHIP_MODE_ID, 0}, + {0, 1, 0, 0, S_WORD_WEB_SITE_ID, S_WEB_ORDER, S_WORD_WEB_SITE_ID, 0}, + {0, 100, 0, 0, S_WORD_COMMENT, S_WEB_ORDER, S_WORD_COMMENT, 0}, + {0, 1, 0, 0, S_WLIN_ITEM_ID, S_WEB_ORDER, S_WLIN_ITEM_ID, 0}, + {0, 12, 0, 0, S_WLIN_ID, S_WEB_ORDER_LINEITEM, S_WLIN_ID, 0}, + {0, + 0, + 0, + 0, + S_WLIN_LINE_NUMBER, + S_WEB_ORDER_LINEITEM, + S_WLIN_LINE_NUMBER, + 0}, + {0, + 12, + 0, + 0, + S_WLIN_PROMOTION_ID, + S_WEB_ORDER_LINEITEM, + S_WLIN_PROMOTION_ID, + 0}, + {0, 12, 0, 0, S_WLIN_QUANTITY, S_WEB_ORDER_LINEITEM, S_WLIN_QUANTITY, 0}, + {0, + 12, + 0, + 0, + S_WLIN_COUPON_AMT, + S_WEB_ORDER_LINEITEM, + S_WLIN_COUPON_AMT, + 0}, + {0, + 12, + 0, + 0, + S_WLIN_WAREHOUSE_ID, + S_WEB_ORDER_LINEITEM, + S_WLIN_WAREHOUSE_ID, + 0}, + {0, + 12, + 0, + 0, + S_WLIN_SHIP_DATE, + S_WEB_ORDER_LINEITEM, + S_WLIN_SHIP_DATE, + 0}, + {0, + 12, + 0, + 0, + S_WLIN_WEB_PAGE_ID, + S_WEB_ORDER_LINEITEM, + S_WLIN_WEB_PAGE_ID, + 0}, + {0, 96, 0, 0, S_WLIN_PRICING, S_WEB_ORDER_LINEITEM, S_WLIN_PRICING, 0}, + {0, 0, 0, 0, S_WLIN_SHIP_COST, S_WEB_ORDER_LINEITEM, S_WLIN_SHIP_COST, 0}, + {0, + 12, + 0, + 0, + S_WLIN_IS_RETURNED, + S_WEB_ORDER_LINEITEM, + S_WLIN_IS_RETURNED, + 0}, + {0, 0, 0, 0, S_WLIN_PERMUTE, S_WEB_ORDER_LINEITEM, S_WLIN_PERMUTE, 0}, + {0, 1, 0, 0, S_WPAG_SITE_ID, S_WEB_PAGE, S_WPAG_SITE_ID, 0}, + {0, 1, 0, 0, S_WPAG_ID, S_WEB_PAGE, S_WPAG_ID, 0}, + {0, 1, 0, 0, S_WPAG_CREATE_DATE, S_WEB_PAGE, S_WPAG_CREATE_DATE, 0}, + {0, 1, 0, 0, S_WPAG_ACCESS_DATE, S_WEB_PAGE, S_WPAG_ACCESS_DATE, 0}, + {0, 1, 0, 0, S_WPAG_AUTOGEN_FLAG, S_WEB_PAGE, S_WPAG_AUTOGEN_FLAG, 0}, + {0, 1, 0, 0, S_WPAG_DEPARTMENT, S_WEB_PAGE, S_WPAG_DEPARTMENT, 0}, + {0, 1, 0, 0, S_WPAG_URL, S_WEB_PAGE, S_WPAG_URL, 0}, + {0, 1, 0, 0, S_WPAG_TYPE, S_WEB_PAGE, S_WPAG_TYPE, 0}, + {0, 1, 0, 0, S_WPAG_CHAR_CNT, S_WEB_PAGE, S_WPAG_CHAR_CNT, 0}, + {0, 1, 0, 0, S_WPAG_LINK_CNT, S_WEB_PAGE, S_WPAG_LINK_CNT, 0}, + {0, 1, 0, 0, S_WPAG_IMAGE_CNT, S_WEB_PAGE, S_WPAG_IMAGE_CNT, 0}, + {0, 1, 0, 0, S_WPAG_MAX_AD_CNT, S_WEB_PAGE, S_WPAG_MAX_AD_CNT, 0}, + {0, 0, 0, 0, S_WPAG_PERMUTE, S_WEB_PAGE, S_WPAG_PERMUTE, 0}, + {0, 1, 0, 0, S_WITM_SITE_ID, S_WEB_PROMOTIONAL_ITEM, S_WITM_SITE_ID, 0}, + {0, 1, 0, 0, S_WITM_PAGE_ID, S_WEB_PROMOTIONAL_ITEM, S_WITM_PAGE_ID, 0}, + {0, 1, 0, 0, S_WITM_ITEM_ID, S_WEB_PROMOTIONAL_ITEM, S_WITM_ITEM_ID, 0}, + {0, + 1, + 0, + 0, + S_WITM_PROMOTION_ID, + S_WEB_PROMOTIONAL_ITEM, + S_WITM_PROMOTION_ID, + 0}, + {0, 0, 0, 0, S_WRET_SITE_ID, S_WEB_RETURNS, S_WRET_SITE_ID, 0}, + {0, 0, 0, 0, S_WRET_ORDER_ID, S_WEB_RETURNS, S_WRET_ORDER_ID, 0}, + {0, 0, 0, 0, S_WRET_LINE_NUMBER, S_WEB_RETURNS, S_WRET_LINE_NUMBER, 0}, + {0, 0, 0, 0, S_WRET_ITEM_ID, S_WEB_RETURNS, S_WRET_ITEM_ID, 0}, + {0, + 0, + 0, + 0, + S_WRET_RETURN_CUST_ID, + S_WEB_RETURNS, + S_WRET_RETURN_CUST_ID, + 0}, + {0, + 0, + 0, + 0, + S_WRET_REFUND_CUST_ID, + S_WEB_RETURNS, + S_WRET_REFUND_CUST_ID, + 0}, + {0, 24, 0, 0, S_WRET_RETURN_DATE, S_WEB_RETURNS, S_WRET_RETURN_DATE, 0}, + {0, 12, 0, 0, S_WRET_RETURN_TIME, S_WEB_RETURNS, S_WRET_RETURN_TIME, 0}, + {0, 12, 0, 0, S_WRET_REASON_ID, S_WEB_RETURNS, S_WRET_REASON_ID, 0}, + {0, 84, 0, 0, S_WRET_PRICING, S_WEB_RETURNS, S_WRET_PRICING, 0}, + {0, 1, 0, 0, S_WSIT_ID, S_WEB_SITE, S_WSIT_ID, 0}, + {0, 1, 0, 0, S_WSIT_OPEN_DATE, S_WEB_SITE, S_WSIT_OPEN_DATE, 0}, + {0, 1, 0, 0, S_WSIT_CLOSE_DATE, S_WEB_SITE, S_WSIT_CLOSE_DATE, 0}, + {0, 0, 0, 0, S_WSIT_NAME, S_WEB_SITE, S_WSIT_NAME, 0}, + {0, 1, 0, 0, S_WSIT_ADDRESS_ID, S_WEB_SITE, S_WSIT_ADDRESS_ID, 0}, + {0, 1, 0, 0, S_WSIT_DIVISION_ID, S_WEB_SITE, S_WSIT_DIVISION_ID, 0}, + {0, 1, 0, 0, S_WSIT_CLASS, S_WEB_SITE, S_WSIT_CLASS, 0}, + {0, 1, 0, 0, S_WSIT_MANAGER_ID, S_WEB_SITE, S_WSIT_MANAGER_ID, 0}, + {0, 1, 0, 0, S_WSIT_MARKET_ID, S_WEB_SITE, S_WSIT_MARKET_ID, 0}, + {0, 1, 0, 0, S_WSIT_TAX_PERCENTAGE, S_WEB_SITE, S_WSIT_TAX_PERCENTAGE, 0}, + {0, 0, 0, 0, S_ZIPG_ZIP, S_ZIPG, S_ZIPG_ZIP, 0}, + {0, 0, 0, 0, S_ZIPG_GMT, S_ZIPG, S_ZIPG_GMT, 0}, + {-1, -1, -1, -1, -1, -1, -1, 0}}; + + void Reset(); +}; + +/* must match WriteDist() in dcomp.c */ +#define IDX_SIZE (D_NAME_LEN + 7 * sizeof(int)) + +int dist_op( + void* dest, + int op, + const char* d_name, + int vset, + int wset, + int stream, + DSDGenContext& dsdGenContext); +#define pick_distribution(dest, dist, v, w, s, dsdGenContext) \ + dist_op(dest, 0, dist, v, w, s, dsdGenContext) +#define dist_member(dest, dist, v, w, dsdGenContext) \ + dist_op(dest, 1, dist, v, w, 0, dsdGenContext) +#define dist_max(dist, w, dsdGenContext) dist->maximums[w - 1] +int dist_weight( + int* dest, + const char* d, + int index, + int wset, + DSDGenContext& dsdGenContext); +int distsize(const char* szDistname, DSDGenContext& dsdGenContext); +int dist_type(const char* szDistName, int vset, DSDGenContext& dsdGenContext); +const d_idx_t* find_dist(const char* name); +int IntegrateDist( + const char* szDistName, + int nPct, + int nStartIndex, + int nWeightSet, + DSDGenContext& dsdGenContext); +void dump_dist(const char* szName, DSDGenContext& dsdGenContext); +int dist_active( + const char* szName, + int nWeightSet, + DSDGenContext& dsdGenContext); +int DistNameIndex( + const char* szDist, + int nNameType, + const char* szName, + DSDGenContext& dsdGenContext); +int DistSizeToShiftWidth( + const char* szDist, + int nWeightSet, + DSDGenContext& dsdGenContext); +int MatchDistWeight( + void* dest, + const char* szDist, + int nWeight, + int nWeightSet, + int ValueSet, + DSDGenContext& dsdGenContext); +int findDistValue( + const char* szValue, + const char* szDistName, + int ValueSet, + DSDGenContext& dsdGenContext); +int di_compare(const void* op1, const void* op2); +int load_dists(); + +#define DIST_UNIFORM 0x0001 +#define DIST_EXPONENTIAL 0x0002 +/* sales and returns are special; they must match calendar.dst */ +#define DIST_SALES 3 +#define DIST_RETURNS 5 +#define DIST_CHAR 0x0004 +#define DIST_INT 0x0008 +#define DIST_NAMES_SET 0xff00 + +/* DistNameIndex needs to know what sort of name we are trying to match */ +#define VALUE_NAME 0x0000 +#define WEIGHT_NAME 0x0001 diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/error_msg.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/error_msg.h new file mode 100644 index 0000000000000..b8571ef643055 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/error_msg.h @@ -0,0 +1,76 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#define QERR_OK 0 +#define QERR_NO_FILE -1 +#define QERR_LINE_TOO_LONG -2 +#define QERR_NO_MEMORY -3 +#define QERR_SYNTAX -4 +#define QERR_RANGE_ERROR -5 +#define QERR_NON_UNIQUE -6 +#define QERR_BAD_NAME -7 +#define QERR_DEFINE_OVERFLOW -8 +#define QERR_INVALID_TAG -9 +#define QERR_READ_FAILED -10 +#define QERR_TEMPLATE_OVERFLOW -11 +#define QERR_ONE_WORKLOAD -12 +#define QERR_CLASS_REDEFINE -13 +#define QERR_DUP_QUERY -14 +#define QERR_OPEN_FAILED -15 +#define QERR_NOT_IMPLEMENTED -16 +#define QERR_STR_TRUNCATED -17 +#define QERR_BAD_STRING -18 +#define QERR_WRITE_FAILED -19 +#define QERR_NO_TYPE -20 +#define QERR_NO_WEIGHT -21 +#define QERR_NO_LIMIT -22 +#define QERR_BAD_PERCENT -23 +#define QERR_ROWCOUNT_NAME -24 +#define QERR_NO_EXPR -25 +#define QERR_NO_INIT -26 +#define QERR_NO_NORMAL_RANGE -27 +#define QERR_UNBALANCED -28 +#define QERR_INCLUDE_OVERFLOW -29 +#define QERR_BAD_PARAMS -30 +#define DBGEN_ERROR_HIERACHY_ORDER -31 +#define QERR_NAMES_EARLY -32 +#define QERR_ARG_OVERFLOW -33 +#define QERR_INVALID_ARG -34 +#define QERR_RANGE_LIST -35 +#define QERR_BAD_SCALE -36 +#define QERR_BAD_PARAM -37 +#define QERR_BAD_JOIN -38 +#define QERR_TABLE_NOP -39 +#define QERR_TABLE_CHILD -40 +#define QERR_CMDLINE_TOO_LONG -41 +#define QERR_NO_QUERYLIST -42 +#define QERR_QUERY_RANGE -43 +#define QERR_MODIFIED_PARAM -44 +#define QERR_RANGE_OVERRUN -45 +#define QERR_QUALIFICATION_SCALE -46 +#define QERR_TABLE_UPDATE -47 +#define MAX_ERROR 47 + +typedef struct ERR_MSG_T { + int flags; + const char* prompt; +} err_msg_t; + +/* Flag determine formating */ +#define EFLG_NO_ARG 0x0000 +#define EFLG_STR_ARG 0x0001 +#define EFLG_ARG_MASK 0x0001 + +#define EFLG_SYSTEM 0x0002 + +int ReportError(int nError, const char* arg, int bExit); +int ReportErrorNoLine(int nError, const char* arg, int bExit); +void SetErrorGlobals(char* szFileName, int* pnLineNumber); diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/genrand.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/genrand.h new file mode 100644 index 0000000000000..6cec1e25d9af3 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/genrand.h @@ -0,0 +1,84 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef GENRAND_H +#define GENRAND_H + +#include "address.h" +#include "date.h" +#include "decimal.h" +#include "dist.h" + +extern rng_t Streams[]; + +#define FL_SEED_OVERRUN 0x0001 + +#define ALPHANUM "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789" +#define DIGITS "0123456789" + +#define RNG_SEED 19620718 + +int genrand_integer( + int* dest, + int dist, + int min, + int max, + int mean, + int stream, + DSDGenContext& dsdGenContext); +int genrand_decimal( + decimal_t* dest, + int dist, + decimal_t* min, + decimal_t* max, + decimal_t* mean, + int stream, + DSDGenContext& dsdGenContext); +int genrand_date( + date_t* dest, + int dist, + date_t* min, + date_t* max, + date_t* mean, + int stream, + DSDGenContext& dsdGenContext); +ds_key_t genrand_key( + ds_key_t* dest, + int dist, + ds_key_t min, + ds_key_t max, + ds_key_t mean, + int stream, + DSDGenContext& dsdGenContext); +int gen_charset( + char* dest, + char* set, + int min, + int max, + int stream, + DSDGenContext& dsdGenContext); +int dump_seeds_ds(int tbl); +void init_rand(DSDGenContext& dsdGenContext); +void skip_random(int s, ds_key_t count, DSDGenContext& dsdGenContext); +int RNGReset(int nTable); +long next_random(int nStream, DSDGenContext& dsdGenContext); +void genrand_email( + char* pEmail, + char* pFirst, + char* pLast, + int nColumn, + DSDGenContext& dsdGenContext); +void genrand_ipaddr(char* pDest, int nColumn, DSDGenContext& dsdGenContext); +int genrand_url(char* pDest, int nColumn); +int setSeed(int nStream, int nValue, DSDGenContext& dsdGenContext); +void resetSeeds(int nTable, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/grammar.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/grammar.h new file mode 100644 index 0000000000000..31a12acd570dd --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/grammar.h @@ -0,0 +1,30 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef GRAMMAR_H +#define GRAMMAR_H + +typedef struct TOKEN_T { + int index; + char word[40]; + int (*handler)(char* s, struct TOKEN_T* t); +} token_t; + +#define COMMENT_CHAR '-' +#define STMT_END ';' +int ParseFile(char* szPath); +int FindToken(char* name); +void SetTokens(token_t* t); +char* ProcessStr(char* stmt, token_t* pTokens); +char* SafeStrtok(char* string, char* delims); +extern token_t* pTokens; + +#endif /* GRAMMAR_H */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/grammar_support.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/grammar_support.h new file mode 100644 index 0000000000000..b629eaad4a0ce --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/grammar_support.h @@ -0,0 +1,35 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef GRAMMAR_SUPPORT_H +#define GRAMMAR_SUPPORT_H +/* + * entry in the file stack used to manage multiple input file and include files + */ +typedef struct FILE_REF_T { + FILE* file; + char* name; + int line_number; + void* pContext; + struct FILE_REF_T* pNext; +#if defined(MKS) || defined(FLEX) + void* pLexState; +#endif +} file_ref_t; + +extern file_ref_t* pCurrentFile; + +int yywarn(char* str); +void yyerror(char* msg, ...); +int setup(void); +int include_file(char* fn, void* pContext); +void GetErrorCounts(int* nError, int* nWarning); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/list.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/list.h new file mode 100644 index 0000000000000..89855484ec89a --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/list.h @@ -0,0 +1,46 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef LIST_H +#define LIST_H +typedef struct LIST_NODE_T { + struct LIST_NODE_T* pNext; + struct LIST_NODE_T* pPrev; + void* pData; +} node_t; + +typedef struct LIST_T { + struct LIST_NODE_T* head; + struct LIST_NODE_T* tail; + struct LIST_NODE_T* pCurrent; + int (*pSortFunc)(const void* pD1, const void* pD2); + int nMembers; + int nFlags; +} list_t; + +/* list_t flags */ +#define L_FL_HEAD 0x01 /* add at head */ +#define L_FL_TAIL 0x02 /* add at tail */ +#define L_FL_SORT 0x04 /* create sorted list */ + +#define length(list) list->nMembers + +list_t* makeList( + int nFlags, + int (*pSortFunc)(const void* pD1, const void* pD2)); +list_t* addList(list_t* pList, void* pData); +void* findList(list_t* pList, void* pData); +void* removeItem(list_t* pList, int bFromHead); +void* getHead(list_t* pList); +void* getTail(list_t* pList); +void* getNext(list_t* pList); +void* getItem(list_t* pList, int nIndex); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/load.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/load.h new file mode 100644 index 0000000000000..6c3b4977bd534 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/load.h @@ -0,0 +1,18 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef LOAD_H +#define LOAD_H +#include "tables.h" +void load_init(void); +void load_close(void); +int create_table(int nTable); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/mathops.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/mathops.h new file mode 100644 index 0000000000000..7f4d0edc6941b --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/mathops.h @@ -0,0 +1,29 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#define OP_PLUS 0x00001 +#define OP_MINUS 0x00002 +#define OP_MULT 0x00004 +#define OP_DIV 0x00008 +#define OP_MOD 0x00010 +#define OP_XOR 0x00020 +#define OP_PAREN 0x00040 +#define OP_BRACKET 0x00080 +#define OP_NEST 0x00100 /* a --> (a) */ +#define OP_NEG 0x00200 +#define OP_ADDR 0x00400 /* get an address */ +#define OP_PTR 0x00800 /* reference through a pointer */ +#define OP_FUNC 0x01000 /* user function/macro */ +#define OP_UNIQUE 0x02000 /* built in functions start here */ +#define OP_TEXT 0x04000 +#define OP_RANDOM 0x08000 +#define OP_RANGE 0x10000 +#define OP_USER 0x20000 /* user defined function */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/misc.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/misc.h new file mode 100644 index 0000000000000..8c7d26ab5643c --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/misc.h @@ -0,0 +1,29 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef MISC_H +#define MISC_H +int prep_direct(int dialect); +int close_direct(int dialect); +int pick_tbl(char* dname); +int itostr(char* dest, int i); +int char_op(char* dest, int op, char* s1, char* s2); +char* gen_text( + char* dest, + int min, + int max, + int stream, + DSDGenContext& dsdGenContext); +int int_op(int* dest, int op, int arg1, int arg2); + +char* env_config(char* var, char* dflt); +int a_rnd(int min, int max, int column, char* dest); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/nulls.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/nulls.h new file mode 100644 index 0000000000000..8c9dbcea41081 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/nulls.h @@ -0,0 +1,20 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef R_NULLCHECK_H +#define R_NULLCHECK_H + +#include "dist.h" + +int nullCheck(int nColumn, DSDGenContext& dsdGenContext); +void nullSet(ds_key_t* pDest, int nStream, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/parallel.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/parallel.h new file mode 100644 index 0000000000000..bc86e3cc13a34 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/parallel.h @@ -0,0 +1,23 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef PARALLEL_H +#define PARALLEL_H + +int split_work( + int nTable, + ds_key_t* pkFirstRow, + ds_key_t* pkRowCount, + DSDGenContext& dsdGenContext); +int row_stop(int tbl, DSDGenContext& dsdGenContext); +int row_skip(int tbl, ds_key_t count, DSDGenContext& dsdGenContext); + +#endif /* PARALLEL_H */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/params.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/params.h new file mode 100644 index 0000000000000..62b2ff12c5357 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/params.h @@ -0,0 +1,25 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef QGEN_PARAMS_H +#define QGEN_PARAMS_H + +#include "build_support.h" +#include "r_params.h" + +#ifdef DECLARER +#else +extern option_t options[]; +extern char* params[]; +extern char* szTableNames[]; +#endif + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/permute.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/permute.h new file mode 100644 index 0000000000000..0d0c96c875fd4 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/permute.h @@ -0,0 +1,22 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +int* makePermutation( + int* pNumberSet, + int nSize, + int nStream, + DSDGenContext& dsdGenContext); +ds_key_t* makeKeyPermutation( + ds_key_t* pNumberSet, + ds_key_t nSize, + int nStream, + DSDGenContext& dsdGenContext); +#define getPermutationEntry(pPermutation, nIndex) (pPermutation[nIndex - 1] + 1) diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/porting.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/porting.h new file mode 100644 index 0000000000000..117c4a58b8559 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/porting.h @@ -0,0 +1,144 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef PORTING_H +#define PORTING_H + +#include +// #ifdef USE_STRING_H +// #include +// #else +// #include +// #endif + +#ifdef USE_VALUES_H +#include +#endif + +#ifdef USE_LIMITS_H +#include +#endif + +#ifdef USE_STDLIB_H +#include +#endif + +#ifndef WIN32 +#include +#else +#define int32_t __int32 +#define int64_t __int64 +#endif + +#ifdef WIN32 +#include +#define timeb _timeb +#define ftime _ftime +#else +#include +#endif + +#include "config.h" + +typedef HUGE_TYPE ds_key_t; + +/* + * add some functions that are not strictly ANSI standard + */ +#ifndef strdup +char* strdup(const char*); +#endif + +#ifdef WIN32 +#include +#include +#include +#include +#define random rand +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#define strdup _strdup +#define access _access +#define isatty _isatty +#define fileno _fileno +#define F_OK 0 +#define MAXINT INT_MAX +#define THREAD __declspec(thread) +#define MIN_MULTI_NODE_ROWS 100000 +#define MIN_MULTI_THREAD_ROWS 5000 +#define THREAD __declspec(thread) +/* Lines added by Chuck McDevitt for WIN32 support */ +#ifndef _POSIX_ +#ifndef S_ISREG +#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) +#define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO) +#endif +#endif +#endif /* WIN32 */ + +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#endif + +#ifdef INTERIX +#include +#define MAXINT INT_MAX +#endif /* INTERIX */ + +#ifdef AIX +#define MAXINT INT_MAX +#endif + +#ifdef MACOS +#include +#define MAXINT INT_MAX +#endif /* MACOS */ + +#define INTERNAL(m) \ + { \ + auto result = fprintf( \ + stderr, "ERROR: %s\n\tFile: %s\n\tLine: %d\n", m, __FILE__, __LINE__); \ + if (result < 0) \ + perror("sprintf failed"); \ + } + +#define OPEN_CHECK(var, path) \ + if ((var) == NULL) { \ + fprintf( \ + stderr, "Open failed for %s at %s:%d\n", path, __FILE__, __LINE__); \ + exit(1); \ + } + +#ifdef MEM_TEST +#define MALLOC_CHECK(v) \ + if (v == NULL) { \ + fprintf(stderr, "Malloc Failed at %d in %s\n", __LINE__, __FILE__); \ + exit(1); \ + } else { \ + fprintf( \ + stderr, \ + "Add (%x) %d at %d in %s\n", \ + sizeof(*v), \ + v, \ + __LINE__, \ + __FILE__); \ + } +#else +#define MALLOC_CHECK(v) \ + if (v == nullptr) { \ + int result = \ + fprintf(stderr, "Malloc Failed at %d in %s\n", __LINE__, __FILE__); \ + if (result < 0) \ + perror("fprintf failed"); \ + exit(1); \ + } +#endif /* MEM_TEST */ +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/pricing.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/pricing.h new file mode 100644 index 0000000000000..beb7ce76ec039 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/pricing.h @@ -0,0 +1,29 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef PRICING_H +#define PRICING_H +#include "decimal.h" + +typedef struct DS_LIMITS_T { + int nId; + char* szQuantity; + char* szMarkUp; + char* szDiscount; + char* szWholesale; + char* szCoupon; +} ds_limits_t; + +void set_pricing( + int nTabId, + ds_pricing_t* pPricing, + DSDGenContext& dsdGenContext); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/r_params.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/r_params.h new file mode 100644 index 0000000000000..ee631698e3588 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/r_params.h @@ -0,0 +1,53 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "dist.h" + +#ifndef R_PARAMS_H +#define R_PARAMS_H +#define OPT_NONE 0x00 +#define OPT_FLG 0x01 /* option is a flag; no parameter */ +#define OPT_INT 0x02 /* argument is an integer */ +#define OPT_STR 0x04 /* argument is a string */ +#define OPT_NOP 0x08 /* flags non-operational options */ +#define OPT_SUB 0x10 /* sub-option defined */ +#define OPT_ADV 0x20 /* advanced option */ +#define OPT_SET \ + 0x40 /* not changeable -- used for default/file/command precedence */ +#define OPT_DFLT 0x80 /* param set to non-zero default */ +#define OPT_MULTI 0x100 /* param may be set repeatedly */ +#define OPT_HIDE 0x200 /* hidden option -- not listed in usage */ +#define TYPE_MASK 0x07 +#endif +/* + * function declarations + */ +int process_options(int count, const char** args); +char* get_str(const char* var, DSDGenContext& dsdGenContext); +void set_str( + const char* param, + const char* value, + DSDGenContext& dsdGenContext); +int get_int(const char* var, DSDGenContext& dsdGenContext); +void set_int(const char* var, const char* val, DSDGenContext& dsdGenContext); +double get_dbl(const char* var, DSDGenContext& dsdGenContext); +int is_set(const char* flag, DSDGenContext& dsdGenContext); +void clr_flg(const char* flag, DSDGenContext& dsdGenContext); +int find_table(const char* szParamName, const char* tname); +char* GetParamName(int nParam, DSDGenContext& dsdGenContext); +char* GetParamValue(int nParam, DSDGenContext& dsdGenContext); +int load_param(int nParam, const char* value, DSDGenContext& dsdGenContext); +int fnd_param(const char* name, DSDGenContext& dsdGenContext); +int init_params(DSDGenContext& dsdGenContext); +int set_option(const char* pname, const char* value); +void load_params(void); +int IsIntParam(const char* szName, DSDGenContext& dsdGenContext); +int IsStrParam(const char* szName, DSDGenContext& dsdGenContext); diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/scaling.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/scaling.h new file mode 100644 index 0000000000000..7a217a6619550 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/scaling.h @@ -0,0 +1,28 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "dist.h" + +#ifndef SCALING_H +#define SCALING_H + +ds_key_t get_rowcount(int table, DSDGenContext& dsdGenContext); +ds_key_t getIDCount(int nTable, DSDGenContext& dsdGenContext); +int getUpdateID(ds_key_t* pDest, int nTable, int nColumn); +int getScaleSlot(int nTargetGB, DSDGenContext& dsdGenContext); +int getSkewedJulianDate(int nWeight, int nColumn, DSDGenContext& dsdGenContext); +ds_key_t dateScaling(int nColumn, ds_key_t jDate, DSDGenContext& dsdGenContext); +int getUpdateDate(int nTable, ds_key_t kRowcount, DSDGenContext& dsdGenContext); +void setUpdateDates(DSDGenContext& dsdGenContext); +void setUpdateScaling(int nTable, DSDGenContext& dsdGenContext); +ds_key_t getUpdateBase(int nTable, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/scd.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/scd.h new file mode 100644 index 0000000000000..842316b9061da --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/scd.h @@ -0,0 +1,52 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef SCD_H +#define SCD_H + +#include "decimal.h" +#include "tables.h" + +extern char arBKeys[MAX_TABLE][17]; +int setSCDKeys( + int nTableID, + ds_key_t hgIndex, + char* szBKey, + ds_key_t* hgBeginDateKey, + ds_key_t* hgEndDateKey, + DSDGenContext& dsdGenContext); +ds_key_t +scd_join(int tbl, int col, ds_key_t jDate, DSDGenContext& dsdGenContext); +ds_key_t matchSCDSK( + ds_key_t kUnique, + ds_key_t jDate, + int nTable, + DSDGenContext& dsdGenContext); +ds_key_t getSKFromID(ds_key_t kID, int nColumn, DSDGenContext& dsdGenContext); +ds_key_t getFirstSK(ds_key_t kID); +/* + * handle the partial change of a history keeping record + * TODO: remove the macros in favor of straight fucntion calls + */ +#define SCD_INT 0 +#define SCD_CHAR 1 +#define SCD_DEC 2 +#define SCD_KEY 3 +#define SCD_PTR 4 +void changeSCD( + int nDataType, + void* pNewData, + void* pOldData, + int* nFlags, + int bFirst); +int validateSCD(int nTable, ds_key_t kRow, int* Permutation); +void printValidation(int nTable, ds_key_t kRow); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/skip_days.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/skip_days.h new file mode 100644 index 0000000000000..1fdc3fc8a6194 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/skip_days.h @@ -0,0 +1,22 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef R_SKIP_DAYS_H +#define R_SKIP_DAYS_H + +#include "config.h" +#include "dist.h" +#include "porting.h" + +ds_key_t +skipDays(int nTable, ds_key_t* pRemainder, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/sparse.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/sparse.h new file mode 100644 index 0000000000000..f4305162fe1db --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/sparse.h @@ -0,0 +1,20 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "dist.h" + +int initSparseKeys( + int nTable, + DSDGenContext& dsdGenContext); /* populate the set of valid keys */ +ds_key_t randomSparseKey( + int nTable, + int nColumn, + DSDGenContext& dsdGenContext); /* select a random sparse key */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/streams.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/streams.h new file mode 100644 index 0000000000000..b7f316d939f25 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/streams.h @@ -0,0 +1,18 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +/* + * THIS IS A GENERATED FILE + * SEE COLUMNS.LIST + */ +#ifndef STREAMS_H +#define STREAMS_H +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tables.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tables.h new file mode 100644 index 0000000000000..5559c831ab761 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tables.h @@ -0,0 +1,92 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +/* + * THIS IS A GENERATED FILE + * SEE COLUMNS.LIST + */ +#ifndef TABLES_H +#define TABLES_H +#define CALL_CENTER 0 +#define CATALOG_PAGE 1 +#define CATALOG_RETURNS 2 +#define CATALOG_SALES 3 +#define CUSTOMER 4 +#define CUSTOMER_ADDRESS 5 +#define CUSTOMER_DEMOGRAPHICS 6 +#define DATET 7 +#define HOUSEHOLD_DEMOGRAPHICS 8 +#define INCOME_BAND 9 +#define INVENTORY 10 +#define ITEM 11 +#define PROMOTION 12 +#define REASON 13 +#define SHIP_MODE 14 +#define STORE 15 +#define STORE_RETURNS 16 +#define STORE_SALES 17 +#define TIME 18 +#define WAREHOUSE 19 +#define WEB_PAGE 20 +#define WEB_RETURNS 21 +#define WEB_SALES 22 +#define WEB_SITE 23 +#define DBGEN_VERSION 24 +#define S_BRAND 25 +#define S_CUSTOMER_ADDRESS 26 +#define S_CALL_CENTER 27 +#define S_CATALOG 28 +#define S_CATALOG_ORDER 29 +#define S_CATALOG_ORDER_LINEITEM 30 +#define S_CATALOG_PAGE 31 +#define S_CATALOG_PROMOTIONAL_ITEM 32 +#define S_CATALOG_RETURNS 33 +#define S_CATEGORY 34 +#define S_CLASS 35 +#define S_COMPANY 36 +#define S_CUSTOMER 37 +#define S_DIVISION 38 +#define S_INVENTORY 39 +#define S_ITEM 40 +#define S_MANAGER 41 +#define S_MANUFACTURER 42 +#define S_MARKET 43 +#define S_PRODUCT 44 +#define S_PROMOTION 45 +#define S_PURCHASE 46 +#define S_PURCHASE_LINEITEM 47 +#define S_REASON 48 +#define S_STORE 49 +#define S_STORE_PROMOTIONAL_ITEM 50 +#define S_STORE_RETURNS 51 +#define S_SUBCATEGORY 52 +#define S_SUBCLASS 53 +#define S_WAREHOUSE 54 +#define S_WEB_ORDER 55 +#define S_WEB_ORDER_LINEITEM 56 +#define S_WEB_PAGE 57 +#define S_WEB_PROMOTIONAL_ITEM 58 +#define S_WEB_RETURNS 59 +#define S_WEB_SITE 60 +#define S_ZIPG 61 +#define PSEUDO_TABLE_START 62 +/* PSEUDO TABLES from here on; used in hierarchies */ +#define ITEM_BRAND 62 +#define ITEM_CLASS 63 +#define ITEM_CATEGORY 64 +#define DIVISIONS 65 +#define COMPANY 66 +#define CONCURRENT_WEB_SITES 67 +#define ACTIVE_CITIES 68 +#define ACTIVE_COUNTIES 69 +#define ACTIVE_STATES 70 +#define MAX_TABLE 70 +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tdef_functions.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tdef_functions.h new file mode 100644 index 0000000000000..f75685c529460 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tdef_functions.h @@ -0,0 +1,46 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef TDEF_FUNCTIONS_H +#define TDEF_FUNCTIONS_H +#include "dist.h" +#include "tables.h" + +/* +* table functions. +* NOTE: This table contains the function declarations in the table descriptions; +it must be kept in sync with the +* declararions of assocaited constants, found in tdefs.h + +*/ +typedef struct TABLE_FUNC_T { + char* name; /* -- name of the table; */ + int (*builder)( + void*, + ds_key_t, + DSDGenContext& dsdGenContext); /* -- function to prep output */ + int (*loader[2])(void*); /* -- functions to present output */ + /* -- data validation function */ + int (*validate)(int nTable, ds_key_t kRow, int* Permutation); +} table_func_t; + +extern table_func_t w_tdef_funcs[MAX_TABLE]; +extern table_func_t s_tdef_funcs[MAX_TABLE]; +extern table_func_t* tdef_funcs; + +int validateGeneric(int nTable, ds_key_t kRow, int* Permutation); +int validateSCD(int nTable, ds_key_t kRow, int* Permutation); + +#endif /* TDEF_FUNCTIONS_H */ +extern table_func_t s_tdef_funcs[]; +extern table_func_t w_tdef_funcs[]; + +table_func_t* getTdefFunctionsByNumber(int nTable); diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tdefs.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tdefs.h new file mode 100644 index 0000000000000..5da454bbfc4d2 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tdefs.h @@ -0,0 +1,30 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef TDEFS_H +#define TDEFS_H + +#include +#include "columns.h" +#include "dist.h" +#include "tables.h" +#include "tdef_functions.h" + +#define tdefIsFlagSet(t, f) (tdefs[t].flags & f) +ds_key_t GetRowcountByName(char* szName, DSDGenContext& dsdGenContext); +int GetTableNumber(char* szName, DSDGenContext& dsdGenContext); +const char* getTableNameByID(int id, DSDGenContext& dsdGenContext); +int getTableFromColumn(int id, DSDGenContext& dsdGenContext); +int initSpareKeys(int id, DSDGenContext& dsdGenContext); +tdef* getSimpleTdefsByNumber(int nTable, DSDGenContext& dsdGenContext); +tdef* getTdefsByNumber(int nTable, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/template.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/template.h new file mode 100644 index 0000000000000..e1d1cb36f2e98 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/template.h @@ -0,0 +1,46 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef TEMPLATE_H +#define TEMPLATE_H +#include "StringBuffer.h" +#include "expr.h" +#include "list.h" +#include "substitution.h" + +/* Replacement flags */ +#define REPL_FL_NONE 0x0001 /* no effect on result set size */ +#define REPL_FL_MORE 0x0002 /* likely to increase result set size */ +#define REPL_FL_LESS 0x0004 /* likely to decrease result set size */ + +typedef struct TEMPLATE_T { + char* name; + int index; + int flags; + list_t* SubstitutionList; + list_t* SegmentList; + list_t* DistList; +} template_t; +#define QT_INIT 0x0001 + +extern template_t* pCurrentQuery; + +void PrintQuery(FILE* fp, template_t* t); +int AddQuerySegment(template_t* pQuery, char* szSQL); +int AddQuerySubstitution( + template_t* Query, + char* szSubName, + int nUse, + int nSubPart); +int AddSubstitution(template_t* t, char* s, expr_t* pExpr); +int SetSegmentFlag(template_t* Query, int nSegmentNumber, int nFlag); +substitution_t* FindSubstitution(template_t* t, char* stmt, int* nUse); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tpcds.idx.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tpcds.idx.h new file mode 100644 index 0000000000000..40ce44ac44886 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/tpcds.idx.h @@ -0,0 +1,266 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +/* +THIS IS AN AUTOMATICALLY GENERATED FILE +DO NOT EDIT + +See distcomp.c for details +*/ + +/* aliases for values/weights in the first_names distribution */ +#define first_names_name 1 +#define first_names_male 1 +#define first_names_female 2 +#define first_names_unified 3 + +/* aliases for values/weights in the last_names distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the calendar distribution */ +#define calendar_day_seq 1 +#define calendar_month_name 2 +#define calendar_date 3 +#define calendar_season 4 +#define calendar_month_num 5 +#define calendar_quarter 6 +#define calendar_fom 7 +#define calendar_holiday 8 +#define calendar_uniform 1 +#define calendar_uniform_leap 2 +#define calendar_sales 3 +#define calendar_sales_leap 4 +#define calendar_returns 5 +#define calendar_returns_leap 6 +#define calendar_skewed 7 +#define calendar_low 8 +#define calendar_medium 9 +#define calendar_high 10 + +/* aliases for values/weights in the week_info distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the fips_county distribution */ +#define fips_county_fips 1 +#define fips_county_county 2 +#define fips_county_st 3 +#define fips_county_state 4 +#define fips_county_zone 5 +#define fips_county_gmt 6 +#define fips_county_uniform 1 +#define fips_county_population 2 +#define fips_county_tz 3 +#define fips_county_tz90 4 +#define fips_county_tz9 5 +#define fips_county_tz1 6 + +/* aliases for values/weights in the street_names distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the street_type distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the adjectives distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the adverbs distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the articles distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the nouns distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the prepositions distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the verbs distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the auxiliaries distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the terminators distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the sentences distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the syllables distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the cities distribution */ +#define cities_name 1 +#define cities_usgs 1 +#define cities_uniform 2 +#define cities_large 3 +#define cities_medium 4 +#define cities_small 5 +#define cities_unified 6 + +/* aliases for values/weights in the categories distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the women_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the men_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the children_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the shoe_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the music_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the jewelry_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the home_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the sport_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the book_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the electronic_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the sizes distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the units distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the container distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the colors distribution */ +#define colors_name 1 +#define colors_uniform 1 +#define colors_skewed 2 +#define colors_low 3 +#define colors_medium 4 +#define colors_high 5 + +/* aliases for values/weights in the brand_syllables distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the i_current_price distribution */ +#define i_current_price_index 1 +#define i_current_price_low_bound 2 +#define i_current_price_high_bound 3 +#define i_current_price_skew 1 +#define i_current_price_high 2 +#define i_current_price_medium 3 +#define i_current_price_low 4 + +/* aliases for values/weights in the i_manufact_id distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the i_manager_id distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the rowcounts distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the gender distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the marital_status distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the education distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the purchase_band distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the buy_potential distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the credit_rating distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the income_band distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the dependent_count distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the vehicle_count distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the promo_purpose distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the return_reasons distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the store_type distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the geography_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the divisions distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the stores distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the hours distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the call_centers distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the call_center_hours distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the call_center_class distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the salutations distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the ship_mode_code distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the ship_mode_type distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the ship_mode_carrier distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the web_page_use distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the web_page_type distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the catalog_page_type distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the location_type distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the top_domains distribution */ +/* NONE DEFINED */ + +/* aliases for values/weights in the countries distribution */ +/* NONE DEFINED */ diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_call_center.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_call_center.h new file mode 100644 index 0000000000000..5d6da36840bc7 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_call_center.h @@ -0,0 +1,31 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_CALL_CENTER_H +#define W_CALL_CENTER_H +#include "address.h" +#include "constants.h" +#include "date.h" +#include "decimal.h" +#include "dist.h" +#include "pricing.h" + +#define MIN_CC_TAX_PERCENTAGE "0.00" +#define MAX_CC_TAX_PERCENTAGE "0.12" + +int mk_w_call_center( + void* pDest, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); +int pr_w_call_center(void* pSrc); +int ld_w_call_center(void* r); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_page.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_page.h new file mode 100644 index 0000000000000..0241eacdab3b2 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_page.h @@ -0,0 +1,24 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef CATALOG_PAGE_H +#define CATALOG_PAGE_H + +#include "constants.h" +#include "dist.h" +#include "porting.h" + +int mk_w_catalog_page( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_returns.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_returns.h new file mode 100644 index 0000000000000..3233f75d2973e --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_returns.h @@ -0,0 +1,23 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_CATALOG_RETURNS_H +#define W_CATALOG_RETURNS_H + +#include "dist.h" +#include "pricing.h" + +int mk_w_catalog_returns( + void* row, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_sales.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_sales.h new file mode 100644 index 0000000000000..9a30c0c8c0c95 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_catalog_sales.h @@ -0,0 +1,27 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_CATALOG_SALES_H +#define W_CATALOG_SALES_H + +#include "dist.h" +#include "pricing.h" + +int mk_w_catalog_sales( + void* info_arr, + ds_key_t index, + DSDGenContext& dsdGenContext); +int vld_w_catalog_sales( + int nTable, + ds_key_t kRow, + int* Permutation, + DSDGenContext& dsdGenContext); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer.h new file mode 100644 index 0000000000000..e069b44062f69 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer.h @@ -0,0 +1,24 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_CUSTOMER_H +#define W_CUSTOMER_H + +#include "constants.h" +#include "dist.h" +#include "porting.h" + +int mk_w_customer( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer_address.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer_address.h new file mode 100644 index 0000000000000..cc0c9638e6404 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer_address.h @@ -0,0 +1,24 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_CUSTOMER_ADDRESS_H +#define W_CUSTOMER_ADDRESS_H +#include "address.h" +#include "constants.h" +#include "dist.h" +#include "porting.h" + +int mk_w_customer_address( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer_demographics.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer_demographics.h new file mode 100644 index 0000000000000..1cc223313d367 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_customer_demographics.h @@ -0,0 +1,30 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_CUSTOMER_DEMOGRAPHICS_H +#define W_CUSTOMER_DEMOGRAPHICS_H + +#include "dist.h" +#include "porting.h" + +/*** +*** CD_xxx Customer Demographcis Defines +***/ +#define CD_MAX_CHILDREN 7 +#define CD_MAX_EMPLOYED 7 +#define CD_MAX_COLLEGE 7 + +int mk_w_customer_demographics( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_datetbl.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_datetbl.h new file mode 100644 index 0000000000000..875063671b395 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_datetbl.h @@ -0,0 +1,28 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ +/* + * DATE table structure + */ +#ifndef W_DATETBL_H +#define W_DATETBL_H + +#include "constants.h" +#include "dist.h" +#include "porting.h" + +int mk_w_date(void* info_arr, ds_key_t kIndex, DSDGenContext& dsdGenContext); + +int vld_w_date( + int nTable, + ds_key_t kRow, + int* Permutation, + DSDGenContext& dsdGenContext); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_household_demographics.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_household_demographics.h new file mode 100644 index 0000000000000..1f41e957fbe83 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_household_demographics.h @@ -0,0 +1,23 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_HOUSEHOLD_DEMOGRAPHICS_H +#define W_HOUSEHOLD_DEMOGRAPHICS_H + +#include "dist.h" +#include "porting.h" + +int mk_w_household_demographics( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_income_band.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_income_band.h new file mode 100644 index 0000000000000..1bf9f0bc52a6e --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_income_band.h @@ -0,0 +1,18 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "dist.h" +#include "porting.h" + +int mk_w_income_band( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_inventory.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_inventory.h new file mode 100644 index 0000000000000..2d46bdd91b59c --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_inventory.h @@ -0,0 +1,20 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "dist.h" +#include "porting.h" + +int mk_w_inventory( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); + +ds_key_t sc_w_inventory(int nScale, DSDGenContext& dsdGenContext); diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_item.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_item.h new file mode 100644 index 0000000000000..a8dbef459dd0f --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_item.h @@ -0,0 +1,30 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_ITEM_H +#define W_ITEM_H + +#include "constants.h" +#include "decimal.h" +#include "porting.h" + +#define I_PROMO_PERCENTAGE \ + 20 /* percent of items that have associated promotions */ +#define MIN_ITEM_MARKDOWN_PCT "0.30" +#define MAX_ITEM_MARKDOWN_PCT "0.90" + +int mk_w_item(void* info_arr, ds_key_t kIndex, DSDGenContext& dsdGenContext); +int vld_w_item( + int nTable, + ds_key_t kRow, + int* Permutation, + DSDGenContext& dsdGenContext); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_promotion.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_promotion.h new file mode 100644 index 0000000000000..b7e0eb67eca0c --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_promotion.h @@ -0,0 +1,24 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_PROMOTION_H +#define W_PROMOTION_H + +#include "constants.h" +#include "decimal.h" +#include "porting.h" + +int mk_w_promotion( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_reason.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_reason.h new file mode 100644 index 0000000000000..08edca765d7c9 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_reason.h @@ -0,0 +1,21 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_REASON_H +#define W_REASON_H + +#include "constants.h" +#include "dist.h" +#include "porting.h" + +int mk_w_reason(void* info_arr, ds_key_t kIndex, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_ship_mode.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_ship_mode.h new file mode 100644 index 0000000000000..ca169d130dba6 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_ship_mode.h @@ -0,0 +1,23 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_SHIP_MODE_H +#define W_SHIP_MODE_H + +#include "constants.h" +#include "dist.h" +#include "porting.h" + +int mk_w_ship_mode( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store.h new file mode 100644 index 0000000000000..a914fb5ff0715 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store.h @@ -0,0 +1,20 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_STORE_H +#define W_STORE_H + +#include "address.h" +#include "decimal.h" + +int mk_w_store(void* info_arr, ds_key_t kIndex, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store_returns.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store_returns.h new file mode 100644 index 0000000000000..30553c7dfc008 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store_returns.h @@ -0,0 +1,23 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_STORE_RETURNS_H +#define W_STORE_RETURNS_H +#include "decimal.h" +#include "pricing.h" + +#define SR_SAME_CUSTOMER 80 + +int mk_w_store_returns( + void* row, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store_sales.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store_sales.h new file mode 100644 index 0000000000000..62a48b076eed9 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_store_sales.h @@ -0,0 +1,27 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_STORE_SALES_H +#define W_STORE_SALES_H + +#include "constants.h" +#include "pricing.h" + +int mk_w_store_sales( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); +int vld_w_store_sales( + int nTable, + ds_key_t kRow, + int* Permutation, + DSDGenContext& dsdGenContext); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_timetbl.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_timetbl.h new file mode 100644 index 0000000000000..69b633efd2e19 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_timetbl.h @@ -0,0 +1,24 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +/* + * TIME table structure + */ +#ifndef W_TIME_TBL_H +#define W_TIME_TBL_H + +#include "constants.h" +#include "dist.h" +#include "porting.h" + +int mk_w_time(void* info_arr, ds_key_t kIndex, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_warehouse.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_warehouse.h new file mode 100644 index 0000000000000..9979c622b1a5f --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_warehouse.h @@ -0,0 +1,23 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_WAREHOUSE_H +#define W_WAREHOUSE_H + +#include "address.h" +#include "porting.h" + +int mk_w_warehouse( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_page.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_page.h new file mode 100644 index 0000000000000..a75f27cb7f519 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_page.h @@ -0,0 +1,19 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "constants.h" +#include "dist.h" +#include "porting.h" + +int mk_w_web_page( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_returns.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_returns.h new file mode 100644 index 0000000000000..6456400556185 --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_returns.h @@ -0,0 +1,19 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "dist.h" +#include "porting.h" +#ifndef W_WEB_RETURNS_H +#define W_WEB_RETURNS_H + +int mk_w_web_returns(void* row, ds_key_t kIndex, DSDGenContext& dsdGenContext); + +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_sales.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_sales.h new file mode 100644 index 0000000000000..3e24d422aa48b --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_sales.h @@ -0,0 +1,38 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#include "porting.h" +#include "pricing.h" + +/*** +*** WS_xxx Web Sales Defines +***/ +#define WS_QUANTITY_MAX "100" +#define WS_MARKUP_MAX "2.00" +#define WS_DISCOUNT_MAX "1.00" +#define WS_WHOLESALE_MAX "100.00" +#define WS_COUPON_MAX "0.50" +#define WS_GIFT_PCT \ + 7 /* liklihood that a purchase is shipped to someone else \ + */ +#define WS_ITEMS_PER_ORDER 9 /* number of lineitems in an order */ +#define WS_MIN_SHIP_DELAY 1 /* time between order date and ship date */ +#define WS_MAX_SHIP_DELAY 120 + +int mk_w_web_sales( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); +int vld_web_sales( + int nTable, + ds_key_t kRow, + int* Permutation, + DSDGenContext& dsdGenContext); diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_site.h b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_site.h new file mode 100644 index 0000000000000..dfb8e8e4ac46a --- /dev/null +++ b/presto-native-execution/presto_cpp/external/dsdgen/include/dsdgen-c/w_web_site.h @@ -0,0 +1,26 @@ +/* + * Copyright owned by the Transaction Processing Performance Council. + * + * A copy of the license is included under external/dsdgen/LICENSE + * in this repository. + * + * You may not use this file except in compliance with the License. + * + * THE TPC SOFTWARE IS AVAILABLE WITHOUT CHARGE FROM TPC. + */ + +#ifndef W_WEB_SITE_H +#define W_WEB_SITE_H + +#include "address.h" +#include "constants.h" +#include "decimal.h" + +#define WEB_MIN_TAX_PERCENTAGE "0.00" +#define WEB_MAX_TAX_PERCENTAGE "0.12" + +int mk_w_web_site( + void* info_arr, + ds_key_t kIndex, + DSDGenContext& dsdGenContext); +#endif diff --git a/presto-native-execution/presto_cpp/external/dsdgen/include/tpcds.idx b/presto-native-execution/presto_cpp/external/dsdgen/include/tpcds.idx new file mode 100644 index 0000000000000000000000000000000000000000..0f49b70e574e8f275c61123ce41bde74641f3c44 GIT binary patch literal 640585 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 Date: Tue, 21 Jan 2025 14:09:49 -0800 Subject: [PATCH 3/7] [native] Update presto protocol --- .../connector/tpcds/TpcdsConnectorProtocol.h | 33 +++ .../tpcds/presto_protocol-json-cpp.mustache | 146 +++++++++++ .../tpcds/presto_protocol-json-hpp.mustache | 68 +++++ .../connector/tpcds/presto_protocol_tpcds.cpp | 241 ++++++++++++++++++ .../connector/tpcds/presto_protocol_tpcds.h | 106 ++++++++ .../connector/tpcds/presto_protocol_tpcds.yml | 49 ++++ .../tpcds/special/TpcdsColumnHandle.hpp.inc | 31 +++ .../special/TpcdsTransactionHandle.cpp.inc | 30 +++ .../special/TpcdsTransactionHandle.hpp.inc | 28 ++ .../ConnectorTransactionHandle.cpp.inc | 1 + 10 files changed, 733 insertions(+) create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/TpcdsConnectorProtocol.h create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol-json-cpp.mustache create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol-json-hpp.mustache create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.cpp create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.h create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.yml create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsColumnHandle.hpp.inc create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsTransactionHandle.cpp.inc create mode 100644 presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsTransactionHandle.hpp.inc diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/TpcdsConnectorProtocol.h b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/TpcdsConnectorProtocol.h new file mode 100644 index 0000000000000..15711cd59d551 --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/TpcdsConnectorProtocol.h @@ -0,0 +1,33 @@ +/* + * Licensed 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. + */ + +#pragma once + +#include "presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.h" +#include "presto_cpp/presto_protocol/core/ConnectorProtocol.h" + +namespace facebook::presto::protocol::tpcds { + +using TpcdsConnectorProtocol = ConnectorProtocolTemplate< + TpcdsTableHandle, + TpcdsTableLayoutHandle, + TpcdsColumnHandle, + NotImplemented, + NotImplemented, + TpcdsSplit, + TpcdsPartitioningHandle, + TpcdsTransactionHandle, + NotImplemented>; + +} // namespace facebook::presto::protocol::tpcds diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol-json-cpp.mustache b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol-json-cpp.mustache new file mode 100644 index 0000000000000..b5aa3d9e5386d --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol-json-cpp.mustache @@ -0,0 +1,146 @@ +/* + * Licensed 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. + */ +// presto_protocol.prolog.cpp +// + +{{#.}} +{{#comment}} +{{comment}} +{{/comment}} +{{/.}} + + +#include "presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.h" +using namespace std::string_literals; + +namespace facebook::presto::protocol::tpcds { + +void to_json(json& j, const TpcdsTransactionHandle& p) { + j = json::array(); + j.push_back(p._type); + j.push_back(p.instance); +} + +void from_json(const json& j, TpcdsTransactionHandle& p) { + j[0].get_to(p._type); + j[1].get_to(p.instance); +} +} // namespace facebook::presto::protocol +{{#.}} +{{#cinc}} +{{&cinc}} +{{/cinc}} +{{^cinc}} +{{#struct}} +namespace facebook::presto::protocol::tpcds { + {{#super_class}} + {{&class_name}}::{{&class_name}}() noexcept { + _type = "{{json_key}}"; + } + {{/super_class}} + + void to_json(json& j, const {{&class_name}}& p) { + j = json::object(); + {{#super_class}} + j["@type"] = "{{&json_key}}"; + {{/super_class}} + {{#fields}} + to_json_key(j, "{{&field_name}}", p.{{field_name}}, "{{&class_name}}", "{{&field_text}}", "{{&field_name}}"); + {{/fields}} + } + + void from_json(const json& j, {{&class_name}}& p) { + {{#super_class}} + p._type = j["@type"]; + {{/super_class}} + {{#fields}} + from_json_key(j, "{{&field_name}}", p.{{field_name}}, "{{&class_name}}", "{{&field_text}}", "{{&field_name}}"); + {{/fields}} + } +} +{{/struct}} +{{#enum}} +namespace facebook::presto::protocol::tpcds { + //Loosly copied this here from NLOHMANN_JSON_SERIALIZE_ENUM() + + // NOLINTNEXTLINE: cppcoreguidelines-avoid-c-arrays + static const std::pair<{{&class_name}}, json> + {{&class_name}}_enum_table[] = { // NOLINT: cert-err58-cpp + {{#elements}} + { {{&class_name}}::{{&element}}, "{{&element}}" }{{^_last}},{{/_last}} + {{/elements}} + }; + void to_json(json& j, const {{&class_name}}& e) + { + static_assert(std::is_enum<{{&class_name}}>::value, "{{&class_name}} must be an enum!"); + const auto* it = std::find_if(std::begin({{&class_name}}_enum_table), std::end({{&class_name}}_enum_table), + [e](const std::pair<{{&class_name}}, json>& ej_pair) -> bool + { + return ej_pair.first == e; + }); + j = ((it != std::end({{&class_name}}_enum_table)) ? it : std::begin({{&class_name}}_enum_table))->second; + } + void from_json(const json& j, {{&class_name}}& e) + { + static_assert(std::is_enum<{{&class_name}}>::value, "{{&class_name}} must be an enum!"); + const auto* it = std::find_if(std::begin({{&class_name}}_enum_table), std::end({{&class_name}}_enum_table), + [&j](const std::pair<{{&class_name}}, json>& ej_pair) -> bool + { + return ej_pair.second == j; + }); + e = ((it != std::end({{&class_name}}_enum_table)) ? it : std::begin({{&class_name}}_enum_table))->first; + } +} +{{/enum}} +{{#abstract}} +namespace facebook::presto::protocol::tpcds { + void to_json(json& j, const std::shared_ptr<{{&class_name}}>& p) { + if ( p == nullptr ) { + return; + } + String type = p->_type; + + {{#subclasses}} + if ( type == "{{&key}}" ) { + j = *std::static_pointer_cast<{{&type}}>(p); + return; + } + {{/subclasses}} + + throw TypeError(type + " no abstract type {{&class_name}} {{&key}}"); + } + + void from_json(const json& j, std::shared_ptr<{{&class_name}}>& p) { + String type; + try { + type = p->getSubclassKey(j); + } catch (json::parse_error &e) { + throw ParseError(std::string(e.what()) + " {{&class_name}} {{&key}} {{&class_name}}"); + } + + {{#subclasses}} + if ( type == "{{&key}}" ) { + std::shared_ptr<{{&type}}> k = std::make_shared<{{&type}}>(); + j.get_to(*k); + p = std::static_pointer_cast<{{&class_name}}>(k); + return; + } + {{/subclasses}} + + throw TypeError(type + " no abstract type {{&class_name}} {{&key}}"); + } +} +{{/abstract}} +{{/cinc}} +{{/.}} diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol-json-hpp.mustache b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol-json-hpp.mustache new file mode 100644 index 0000000000000..13b0dc952ac23 --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol-json-hpp.mustache @@ -0,0 +1,68 @@ +/* + * Licensed 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. + */ +#pragma once + +{{#.}} +{{#comment}} +{{comment}} +{{/comment}} +{{/.}} + +#include +#include + +#include "presto_cpp/external/json/nlohmann/json.hpp" +#include "presto_cpp/presto_protocol/core/presto_protocol_core.h" + +namespace facebook::presto::protocol::tpcds { +struct TpcdsTransactionHandle : public ConnectorTransactionHandle { + String instance = {}; + }; +void to_json(json& j, const TpcdsTransactionHandle& p); + +void from_json(const json& j, TpcdsTransactionHandle& p); +} //namespace facebook::presto::protocol +{{#.}} +{{#hinc}} +{{&hinc}} +{{/hinc}} +{{^hinc}} +{{#struct}} +namespace facebook::presto::protocol::tpcds { + struct {{class_name}} {{#super_class}}: public {{super_class}}{{/super_class}}{ + {{#fields}} + {{#field_local}}{{#optional}}std::shared_ptr<{{/optional}}{{&field_text}}{{#optional}}>{{/optional}} {{&field_name}} = {};{{/field_local}} + {{/fields}} + + {{#super_class}} + {{class_name}}() noexcept; + {{/super_class}} + }; + void to_json(json& j, const {{class_name}}& p); + void from_json(const json& j, {{class_name}}& p); +} +{{/struct}} +{{#enum}} +namespace facebook::presto::protocol::tpcds { + enum class {{class_name}} { + {{#elements}} + {{&element}}{{^_last}},{{/_last}} + {{/elements}} + }; + extern void to_json(json& j, const {{class_name}}& e); + extern void from_json(const json& j, {{class_name}}& e); +} +{{/enum}} +{{/hinc}} +{{/.}} diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.cpp b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.cpp new file mode 100644 index 0000000000000..0124bdf70516b --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.cpp @@ -0,0 +1,241 @@ +// DO NOT EDIT : This file is generated by chevron +/* + * Licensed 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. + */ +// presto_protocol.prolog.cpp +// + +// This file is generated DO NOT EDIT @generated + +#include "presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.h" +using namespace std::string_literals; + +namespace facebook::presto::protocol::tpcds { + +void to_json(json& j, const TpcdsTransactionHandle& p) { + j = json::array(); + j.push_back(p._type); + j.push_back(p.instance); +} + +void from_json(const json& j, TpcdsTransactionHandle& p) { + j[0].get_to(p._type); + j[1].get_to(p.instance); +} +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +TpcdsColumnHandle::TpcdsColumnHandle() noexcept { + _type = "tpcds"; +} + +void to_json(json& j, const TpcdsColumnHandle& p) { + j = json::object(); + j["@type"] = "tpcds"; + to_json_key( + j, + "columnName", + p.columnName, + "TpcdsColumnHandle", + "String", + "columnName"); + to_json_key(j, "type", p.type, "TpcdsColumnHandle", "Type", "type"); +} + +void from_json(const json& j, TpcdsColumnHandle& p) { + p._type = j["@type"]; + from_json_key( + j, + "columnName", + p.columnName, + "TpcdsColumnHandle", + "String", + "columnName"); + from_json_key(j, "type", p.type, "TpcdsColumnHandle", "Type", "type"); +} +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +TpcdsPartitioningHandle::TpcdsPartitioningHandle() noexcept { + _type = "tpcds"; +} + +void to_json(json& j, const TpcdsPartitioningHandle& p) { + j = json::object(); + j["@type"] = "tpcds"; + to_json_key( + j, "table", p.table, "TpcdsPartitioningHandle", "String", "table"); + to_json_key( + j, + "totalRows", + p.totalRows, + "TpcdsPartitioningHandle", + "int64_t", + "totalRows"); +} + +void from_json(const json& j, TpcdsPartitioningHandle& p) { + p._type = j["@type"]; + from_json_key( + j, "table", p.table, "TpcdsPartitioningHandle", "String", "table"); + from_json_key( + j, + "totalRows", + p.totalRows, + "TpcdsPartitioningHandle", + "int64_t", + "totalRows"); +} +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +void to_json(json& j, const std::shared_ptr& p) { + if (p == nullptr) { + return; + } + String type = p->_type; + + if (type == "tpcds") { + j = *std::static_pointer_cast(p); + return; + } + + throw TypeError(type + " no abstract type ColumnHandle "); +} + +void from_json(const json& j, std::shared_ptr& p) { + String type; + try { + type = p->getSubclassKey(j); + } catch (json::parse_error& e) { + throw ParseError(std::string(e.what()) + " ColumnHandle ColumnHandle"); + } + + if (type == "tpcds") { + std::shared_ptr k = + std::make_shared(); + j.get_to(*k); + p = std::static_pointer_cast(k); + return; + } + + throw TypeError(type + " no abstract type ColumnHandle "); +} +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +TpcdsTableHandle::TpcdsTableHandle() noexcept { + _type = "tpcds"; +} + +void to_json(json& j, const TpcdsTableHandle& p) { + j = json::object(); + j["@type"] = "tpcds"; + to_json_key( + j, "tableName", p.tableName, "TpcdsTableHandle", "String", "tableName"); + to_json_key( + j, + "scaleFactor", + p.scaleFactor, + "TpcdsTableHandle", + "double", + "scaleFactor"); +} + +void from_json(const json& j, TpcdsTableHandle& p) { + p._type = j["@type"]; + from_json_key( + j, "tableName", p.tableName, "TpcdsTableHandle", "String", "tableName"); + from_json_key( + j, + "scaleFactor", + p.scaleFactor, + "TpcdsTableHandle", + "double", + "scaleFactor"); +} +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +TpcdsSplit::TpcdsSplit() noexcept { + _type = "tpcds"; +} + +void to_json(json& j, const TpcdsSplit& p) { + j = json::object(); + j["@type"] = "tpcds"; + to_json_key( + j, + "tableHandle", + p.tableHandle, + "TpcdsSplit", + "TpcdsTableHandle", + "tableHandle"); + to_json_key(j, "partNumber", p.partNumber, "TpcdsSplit", "int", "partNumber"); + to_json_key(j, "totalParts", p.totalParts, "TpcdsSplit", "int", "totalParts"); + to_json_key( + j, + "addresses", + p.addresses, + "TpcdsSplit", + "List", + "addresses"); + to_json_key(j, "noSexism", p.noSexism, "TpcdsSplit", "bool", "noSexism"); +} + +void from_json(const json& j, TpcdsSplit& p) { + p._type = j["@type"]; + from_json_key( + j, + "tableHandle", + p.tableHandle, + "TpcdsSplit", + "TpcdsTableHandle", + "tableHandle"); + from_json_key( + j, "partNumber", p.partNumber, "TpcdsSplit", "int", "partNumber"); + from_json_key( + j, "totalParts", p.totalParts, "TpcdsSplit", "int", "totalParts"); + from_json_key( + j, + "addresses", + p.addresses, + "TpcdsSplit", + "List", + "addresses"); + from_json_key(j, "noSexism", p.noSexism, "TpcdsSplit", "bool", "noSexism"); +} +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +TpcdsTableLayoutHandle::TpcdsTableLayoutHandle() noexcept { + _type = "tpcds"; +} + +void to_json(json& j, const TpcdsTableLayoutHandle& p) { + j = json::object(); + j["@type"] = "tpcds"; + to_json_key( + j, + "table", + p.table, + "TpcdsTableLayoutHandle", + "TpcdsTableHandle", + "table"); +} + +void from_json(const json& j, TpcdsTableLayoutHandle& p) { + p._type = j["@type"]; + from_json_key( + j, + "table", + p.table, + "TpcdsTableLayoutHandle", + "TpcdsTableHandle", + "table"); +} +} // namespace facebook::presto::protocol::tpcds diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.h b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.h new file mode 100644 index 0000000000000..eb44440d7721a --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.h @@ -0,0 +1,106 @@ +// DO NOT EDIT : This file is generated by chevron +/* + * Licensed 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. + */ +#pragma once + +// This file is generated DO NOT EDIT @generated + +#include +#include + +#include "presto_cpp/external/json/nlohmann/json.hpp" +#include "presto_cpp/presto_protocol/core/presto_protocol_core.h" + +namespace facebook::presto::protocol::tpcds { +struct TpcdsTransactionHandle : public ConnectorTransactionHandle { + String instance = {}; +}; +void to_json(json& j, const TpcdsTransactionHandle& p); + +void from_json(const json& j, TpcdsTransactionHandle& p); +} // namespace facebook::presto::protocol::tpcds +/* + * Licensed 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. + */ + +// TpcdsColumnHandle is special since it needs an implementation of +// operator<(). + +namespace facebook::presto::protocol::tpcds { +struct TpcdsColumnHandle : public ColumnHandle { + String columnName = {}; + Type type = {}; + + TpcdsColumnHandle() noexcept; + + bool operator<(const ColumnHandle& o) const override { + return columnName < dynamic_cast(o).columnName; + } +}; +void to_json(json& j, const TpcdsColumnHandle& p); +void from_json(const json& j, TpcdsColumnHandle& p); +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +struct TpcdsPartitioningHandle : public ConnectorPartitioningHandle { + String table = {}; + int64_t totalRows = {}; + + TpcdsPartitioningHandle() noexcept; +}; +void to_json(json& j, const TpcdsPartitioningHandle& p); +void from_json(const json& j, TpcdsPartitioningHandle& p); +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +struct TpcdsTableHandle : public ConnectorTableHandle { + String tableName = {}; + double scaleFactor = {}; + + TpcdsTableHandle() noexcept; +}; +void to_json(json& j, const TpcdsTableHandle& p); +void from_json(const json& j, TpcdsTableHandle& p); +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +struct TpcdsSplit : public ConnectorSplit { + TpcdsTableHandle tableHandle = {}; + int partNumber = {}; + int totalParts = {}; + List addresses = {}; + bool noSexism = {}; + + TpcdsSplit() noexcept; +}; +void to_json(json& j, const TpcdsSplit& p); +void from_json(const json& j, TpcdsSplit& p); +} // namespace facebook::presto::protocol::tpcds +namespace facebook::presto::protocol::tpcds { +struct TpcdsTableLayoutHandle : public ConnectorTableLayoutHandle { + TpcdsTableHandle table = {}; + TupleDomain> predicate = {}; + + TpcdsTableLayoutHandle() noexcept; +}; +void to_json(json& j, const TpcdsTableLayoutHandle& p); +void from_json(const json& j, TpcdsTableLayoutHandle& p); +} // namespace facebook::presto::protocol::tpcds diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.yml b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.yml new file mode 100644 index 0000000000000..e874c73bc76ab --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.yml @@ -0,0 +1,49 @@ +# Licensed 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. + +AbstractClasses: + ColumnHandle: + super: JsonEncodedSubclass + comparable: true + subclasses: + - { name: TpcdsColumnHandle, key: tpcds } + + ConnectorPartitioningHandle: + super: JsonEncodedSubclass + subclasses: + - { name: TpcdsPartitioningHandle, key: tpcds} + + ConnectorTableHandle: + super: JsonEncodedSubclass + subclasses: + - { name: TpcdsTableHandle, key: tpcds } + + ConnectorTableLayoutHandle: + super: JsonEncodedSubclass + subclasses: + - { name: TpcdsTableLayoutHandle, key: tpcds } + + ConnectorSplit: + super: JsonEncodedSubclass + subclasses: + - { name: TpcdsSplit, key: tpcds } + +UpdateFields: + TpcdsTableLayoutHandle: + std::shared_ptr: remainingPredicate + +JavaClasses: + - presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsSplit.java + - presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsTableHandle.java + - presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsTableLayoutHandle.java + - presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsColumnHandle.java + - presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsPartitioningHandle.java diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsColumnHandle.hpp.inc b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsColumnHandle.hpp.inc new file mode 100644 index 0000000000000..c0f21bcf6873a --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsColumnHandle.hpp.inc @@ -0,0 +1,31 @@ +/* + * Licensed 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. + */ + +// TpcdsColumnHandle is special since it needs an implementation of +// operator<(). + +namespace facebook::presto::protocol::tpcds { +struct TpcdsColumnHandle : public ColumnHandle { + String columnName = {}; + Type type = {}; + + TpcdsColumnHandle() noexcept; + + bool operator<(const ColumnHandle& o) const override { + return columnName < dynamic_cast(o).columnName; + } +}; +void to_json(json& j, const TpcdsColumnHandle& p); +void from_json(const json& j, TpcdsColumnHandle& p); +} // namespace facebook::presto::protocol::tpcds diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsTransactionHandle.cpp.inc b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsTransactionHandle.cpp.inc new file mode 100644 index 0000000000000..f741669d72dc7 --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsTransactionHandle.cpp.inc @@ -0,0 +1,30 @@ +/* + * Licensed 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. + */ + +// TpcdsTransactionHandle is special since +// the corresponding class in Java is an enum. + +namespace facebook::presto::protocol { + +void to_json(json& j, const TpcdsTransactionHandle& p) { + j = json::array(); + j.push_back(p._type); + j.push_back(p.instance); +} + +void from_json(const json& j, TpcdsTransactionHandle& p) { + j[0].get_to(p._type); + j[1].get_to(p.instance); +} +} // namespace facebook::presto::protocol diff --git a/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsTransactionHandle.hpp.inc b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsTransactionHandle.hpp.inc new file mode 100644 index 0000000000000..d665925648813 --- /dev/null +++ b/presto-native-execution/presto_cpp/presto_protocol/connector/tpcds/special/TpcdsTransactionHandle.hpp.inc @@ -0,0 +1,28 @@ +/* + * Licensed 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. + */ + +// TpcdsTransactionHandle is special since +// the corresponding class in Java is an enum. + +namespace facebook::presto::protocol { + +struct TpcdsTransactionHandle : public ConnectorTransactionHandle { + String instance = {}; +}; + +void to_json(json& j, const TpcdsTransactionHandle& p); + +void from_json(const json& j, TpcdsTransactionHandle& p); + +} // namespace facebook::presto::protocol diff --git a/presto-native-execution/presto_cpp/presto_protocol/core/special/ConnectorTransactionHandle.cpp.inc b/presto-native-execution/presto_cpp/presto_protocol/core/special/ConnectorTransactionHandle.cpp.inc index 8ec2a94e84bd9..1b89a65615b1a 100644 --- a/presto-native-execution/presto_cpp/presto_protocol/core/special/ConnectorTransactionHandle.cpp.inc +++ b/presto-native-execution/presto_cpp/presto_protocol/core/special/ConnectorTransactionHandle.cpp.inc @@ -13,6 +13,7 @@ */ // dependency TpchTransactionHandle +// dependency TpcdsTransactionHandle namespace facebook::presto::protocol { void to_json(json& j, const std::shared_ptr& p) { From c4411779e117bfae359202dbe9be0a92a15497cb Mon Sep 17 00:00:00 2001 From: Pratik Joseph Dabre Date: Fri, 24 Jan 2025 15:51:21 -0800 Subject: [PATCH 4/7] [native] Add TPC-DS connector --- .../prestocpp-linux-build-and-unit-test.yml | 1 + presto-docs/src/main/sphinx/presto-cpp.rst | 4 +- .../facebook/presto/hive/HiveQueryRunner.java | 5 +- presto-native-execution/CMakeLists.txt | 6 + presto-native-execution/Makefile | 3 + .../presto_cpp/main/CMakeLists.txt | 4 + .../presto_cpp/main/PrestoServer.cpp | 17 + .../presto_cpp/main/connectors/CMakeLists.txt | 17 + .../main/connectors/tpcds/CMakeLists.txt | 66 ++ .../main/connectors/tpcds/DSDGenIterator.cpp | 91 ++ .../main/connectors/tpcds/DSDGenIterator.h | 71 ++ .../main/connectors/tpcds/TpcdsConnector.cpp | 190 ++++ .../main/connectors/tpcds/TpcdsConnector.h | 209 ++++ .../connectors/tpcds/TpcdsConnectorSplit.h | 73 ++ .../main/connectors/tpcds/TpcdsGen.cpp | 946 ++++++++++++++++++ .../main/connectors/tpcds/TpcdsGen.h | 99 ++ .../connectors/tpcds/utils/append_info-c.cpp | 158 +++ .../connectors/tpcds/utils/append_info-c.h | 38 + .../presto_cpp/main/tests/CMakeLists.txt | 4 + .../presto_protocol/presto_protocol.cpp | 1 + ...stractTestNativeTpcdsConnectorQueries.java | 83 ++ .../PrestoNativeQueryRunnerUtils.java | 43 +- ...stPrestoNativeSystemQueriesSingleNode.java | 3 +- ...TestPrestoNativeTpcdsConnectorQueries.java | 35 + .../presto/tpcds/TpcdsSplitManager.java | 25 +- 25 files changed, 2171 insertions(+), 21 deletions(-) create mode 100644 presto-native-execution/presto_cpp/main/connectors/CMakeLists.txt create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/CMakeLists.txt create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/DSDGenIterator.cpp create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/DSDGenIterator.h create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnector.cpp create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnector.h create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnectorSplit.h create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsGen.cpp create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsGen.h create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/utils/append_info-c.cpp create mode 100644 presto-native-execution/presto_cpp/main/connectors/tpcds/utils/append_info-c.h create mode 100644 presto-native-execution/src/test/java/com/facebook/presto/nativeworker/AbstractTestNativeTpcdsConnectorQueries.java create mode 100644 presto-native-execution/src/test/java/com/facebook/presto/nativeworker/TestPrestoNativeTpcdsConnectorQueries.java diff --git a/.github/workflows/prestocpp-linux-build-and-unit-test.yml b/.github/workflows/prestocpp-linux-build-and-unit-test.yml index b60fc65ae732d..e60e3668e7cbe 100644 --- a/.github/workflows/prestocpp-linux-build-and-unit-test.yml +++ b/.github/workflows/prestocpp-linux-build-and-unit-test.yml @@ -58,6 +58,7 @@ jobs: -DPRESTO_ENABLE_PARQUET=ON \ -DPRESTO_ENABLE_REMOTE_FUNCTIONS=ON \ -DPRESTO_ENABLE_JWT=ON \ + -DPRESTO_ENABLE_TPCDS_CONNECTOR=ON \ -DPRESTO_STATS_REPORTER_TYPE=PROMETHEUS \ -DPRESTO_MEMORY_CHECKER_TYPE=LINUX_MEMORY_CHECKER \ -DCMAKE_PREFIX_PATH=/usr/local \ diff --git a/presto-docs/src/main/sphinx/presto-cpp.rst b/presto-docs/src/main/sphinx/presto-cpp.rst index 894fab1767f34..99dc73e1bd2be 100644 --- a/presto-docs/src/main/sphinx/presto-cpp.rst +++ b/presto-docs/src/main/sphinx/presto-cpp.rst @@ -54,4 +54,6 @@ Only specific connectors are supported in the Presto C++ evaluation engine. * Iceberg connector supports both V1 and V2 tables, including tables with delete files. -* TPCH connector, with ``tpch.naming=standard`` catalog property. \ No newline at end of file +* TPCH connector, with ``tpch.naming=standard`` catalog property. + +* TPCDS connector. \ No newline at end of file diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/HiveQueryRunner.java b/presto-hive/src/test/java/com/facebook/presto/hive/HiveQueryRunner.java index 8cf90df570ccb..0b336f738b337 100644 --- a/presto-hive/src/test/java/com/facebook/presto/hive/HiveQueryRunner.java +++ b/presto-hive/src/test/java/com/facebook/presto/hive/HiveQueryRunner.java @@ -211,7 +211,10 @@ public static DistributedQueryRunner createQueryRunner( queryRunner.installPlugin(new TpcdsPlugin()); queryRunner.installPlugin(new TestingHiveEventListenerPlugin()); queryRunner.createCatalog("tpch", "tpch"); - queryRunner.createCatalog("tpcds", "tpcds"); + Map tpcdsProperties = ImmutableMap.builder() + .put("tpcds.use-varchar-type", "true") + .build(); + queryRunner.createCatalog("tpcds", "tpcds", tpcdsProperties); Map tpchProperties = ImmutableMap.builder() .put("tpch.column-naming", "standard") .build(); diff --git a/presto-native-execution/CMakeLists.txt b/presto-native-execution/CMakeLists.txt index d5001dde70a74..803dd2b66e816 100644 --- a/presto-native-execution/CMakeLists.txt +++ b/presto-native-execution/CMakeLists.txt @@ -63,6 +63,8 @@ option(PRESTO_ENABLE_TESTING "Enable tests" ON) option(PRESTO_ENABLE_JWT "Enable JWT (JSON Web Token) authentication" OFF) +option(PRESTO_ENABLE_TPCDS_CONNECTOR "Enable TPC-DS connector" OFF) + # Set all Velox options below add_compile_definitions(FOLLY_HAVE_INT128_T=1) @@ -219,6 +221,10 @@ if(PRESTO_ENABLE_JWT) add_compile_definitions(PRESTO_ENABLE_JWT) endif() +if(PRESTO_ENABLE_TPCDS_CONNECTOR) + add_compile_definitions(PRESTO_ENABLE_TPCDS_CONNECTOR) +endif() + if("${MAX_LINK_JOBS}") set_property(GLOBAL APPEND PROPERTY JOB_POOLS "presto_link_job_pool=${MAX_LINK_JOBS}") diff --git a/presto-native-execution/Makefile b/presto-native-execution/Makefile index f3fb5f709f4d5..57e5cc1d50d6b 100644 --- a/presto-native-execution/Makefile +++ b/presto-native-execution/Makefile @@ -39,6 +39,9 @@ endif ifeq ($(PRESTO_ENABLE_JWT), ON) EXTRA_CMAKE_FLAGS += -DPRESTO_ENABLE_JWT=ON endif +ifeq ($(PRESTO_ENABLE_TPCDS_CONNECTOR), ON) + EXTRA_CMAKE_FLAGS += -PRESTO_ENABLE_TPCDS_CONNECTOR=ON +endif ifneq ($(PRESTO_STATS_REPORTER_TYPE),) EXTRA_CMAKE_FLAGS += -DPRESTO_STATS_REPORTER_TYPE=$(PRESTO_STATS_REPORTER_TYPE) endif diff --git a/presto-native-execution/presto_cpp/main/CMakeLists.txt b/presto-native-execution/presto_cpp/main/CMakeLists.txt index b00fee32927b6..afb985d394ea1 100644 --- a/presto-native-execution/presto_cpp/main/CMakeLists.txt +++ b/presto-native-execution/presto_cpp/main/CMakeLists.txt @@ -14,6 +14,7 @@ add_subdirectory(types) add_subdirectory(http) add_subdirectory(common) add_subdirectory(thrift) +add_subdirectory(connectors) add_library( presto_server_lib @@ -106,6 +107,9 @@ add_executable(presto_server PrestoMain.cpp) # TODO: Fix these errors. target_link_libraries(presto_server presto_server_lib velox_hive_connector velox_tpch_connector) +if(PRESTO_ENABLE_TPCDS_CONNECTOR) + target_link_libraries(presto_server presto_tpcds_connector) +endif() if(PRESTO_ENABLE_REMOTE_FUNCTIONS) add_library(presto_server_remote_function JsonSignatureParser.cpp diff --git a/presto-native-execution/presto_cpp/main/PrestoServer.cpp b/presto-native-execution/presto_cpp/main/PrestoServer.cpp index 1f316144bbfce..1b16d23324a2a 100644 --- a/presto-native-execution/presto_cpp/main/PrestoServer.cpp +++ b/presto-native-execution/presto_cpp/main/PrestoServer.cpp @@ -26,6 +26,7 @@ #include "presto_cpp/main/common/ConfigReader.h" #include "presto_cpp/main/common/Counters.h" #include "presto_cpp/main/common/Utils.h" +#include "presto_cpp/main/connectors/tpcds/TpcdsConnector.h" #include "presto_cpp/main/http/HttpConstants.h" #include "presto_cpp/main/http/filters/AccessLogFilter.h" #include "presto_cpp/main/http/filters/HttpEndpointLatencyFilter.h" @@ -71,6 +72,10 @@ #include "presto_cpp/main/RemoteFunctionRegisterer.h" #endif +#ifdef PRESTO_ENABLE_TPCDS_CONNECTOR +#include "presto_cpp/main/connectors/tpcds/TpcdsConnector.h" +#endif + #ifdef __linux__ // Required by BatchThreadFactory #include @@ -276,6 +281,10 @@ void PrestoServer::run() { std::make_unique("system")); registerPrestoToVeloxConnector( std::make_unique("$system@system")); +#ifdef PRESTO_ENABLE_TPCDS_CONNECTOR + registerPrestoToVeloxConnector( + std::make_unique("tpcds")); +#endif velox::exec::OutputBufferManager::initialize({}); initializeVeloxMemory(); @@ -1176,6 +1185,14 @@ void PrestoServer::registerConnectorFactories() { velox::connector::registerConnectorFactory( std::make_shared()); } +#ifdef PRESTO_ENABLE_TPCDS_CONNECTOR + if (!velox::connector::hasConnectorFactory( + presto::connector::tpcds::TpcdsConnectorFactory:: + kTpcdsConnectorName)) { + velox::connector::registerConnectorFactory( + std::make_shared()); + } +#endif } std::vector PrestoServer::registerConnectors( diff --git a/presto-native-execution/presto_cpp/main/connectors/CMakeLists.txt b/presto-native-execution/presto_cpp/main/connectors/CMakeLists.txt new file mode 100644 index 0000000000000..0af6eca9075d2 --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# Licensed 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. + +if(PRESTO_ENABLE_TPCDS_CONNECTOR) + add_subdirectory(tpcds) +endif() diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/CMakeLists.txt b/presto-native-execution/presto_cpp/main/connectors/tpcds/CMakeLists.txt new file mode 100644 index 0000000000000..2c6d344b59cdc --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/CMakeLists.txt @@ -0,0 +1,66 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# Licensed 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. + +cmake_policy(SET CMP0079 NEW) + +project(TPCDS) + +add_library(presto_tpcds_connector OBJECT TpcdsConnector.cpp) +target_link_libraries(presto_tpcds_connector velox_connector tpcds_gen fmt::fmt) + +# Without this hack, there are multiple link errors similar to the one below +# only on GCC. "undefined reference to `vtable for +# velox::connector::tpcds::TpcdsTableHandle`. TODO: Fix this hack. +target_link_libraries(velox_exec_test_lib presto_tpcds_connector) + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-deprecated-declarations -Wno-writable-strings + -Wno-missing-field-initializers) +endif() + +# This stringop-overflow warning seems to have lots of false positives and has +# been the source of a lot of compiler bug reports (e.g. +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578), which causes +# parquet-amalgamation.cpp to fail to compile. For now, we disable this warning +# on the affected compiler (GCC). +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + add_compile_options(-Wno-stringop-overflow -Wno-write-strings) +endif() + +# Add subdirectories +add_subdirectory(${CMAKE_SOURCE_DIR}/presto_cpp/external/dsdgen/dsdgen-c build) + +# Generate tpcds_idx.hpp +set(INPUT_FILE tpcds.idx) +set(OUTPUT_FILE tpcds_idx.hpp) +set(WORKING_DIR ${CMAKE_SOURCE_DIR}/presto_cpp/external/dsdgen/include/) + +add_custom_command( + OUTPUT ${WORKING_DIR}/${OUTPUT_FILE} + COMMAND xxd -i -c 16 ${INPUT_FILE} > ${OUTPUT_FILE} + DEPENDS ${WORKING_DIR}/${INPUT_FILE} + COMMENT "Generating ${OUTPUT_FILE} from ${INPUT_FILE}" + WORKING_DIRECTORY ${WORKING_DIR}) + +add_custom_target(generate_tpcds_idx ALL DEPENDS ${WORKING_DIR}/${OUTPUT_FILE}) +add_dependencies(dsdgen_c generate_tpcds_idx) + +add_library(append_info OBJECT utils/append_info-c.cpp) +target_link_libraries(append_info velox_vector_test_lib Folly::folly xsimd) +target_link_libraries(dsdgen_c append_info) + +add_library(tpcds_gen TpcdsGen.cpp DSDGenIterator.cpp) +target_include_directories(tpcds_gen PUBLIC dsdgen/include) +target_link_libraries(tpcds_gen velox_memory velox_vector dsdgen_c append_info + fmt::fmt) diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/DSDGenIterator.cpp b/presto-native-execution/presto_cpp/main/connectors/tpcds/DSDGenIterator.cpp new file mode 100644 index 0000000000000..b2122edaae954 --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/DSDGenIterator.cpp @@ -0,0 +1,91 @@ +/* + * Licensed 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. + */ + +#include "presto_cpp/main/connectors/tpcds/DSDGenIterator.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/dist.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/genrand.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/parallel.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/params.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/scaling.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/tdefs.h" +#include "velox/common/base/Exceptions.h" + +using namespace facebook::velox; + +namespace facebook::presto::connector::tpcds { + +void initializeDSDgen( + double scale, + int32_t parallel, + int32_t child, + DSDGenContext& dsdGenContext) { + dsdGenContext.Reset(); + resetCountCount(); + + std::string scaleStr = std::to_string(scale); + set_str("SCALE", scaleStr.c_str(), dsdGenContext); + std::string parallelStr = std::to_string(parallel); + set_str("PARALLEL", parallelStr.c_str(), dsdGenContext); + std::string childStr = std::to_string(child); + set_str("CHILD", childStr.c_str(), dsdGenContext); + + init_rand(dsdGenContext); // no random numbers without this +} + +DSDGenIterator::DSDGenIterator( + double scaleFactor, + int32_t parallel, + int32_t child) { + tableDefs_.resize(DBGEN_VERSION); // there are 24 TPC-DS tables + VELOX_CHECK_GE(scaleFactor, 0.0, "Tpcds scale factor must be non-negative"); + initializeDSDgen(scaleFactor, parallel, child, dsdgenCtx_); +} + +void DSDGenIterator::initializeTable( + const std::vector& children, + int table_id) { + auto tdef = getSimpleTdefsByNumber(table_id, dsdgenCtx_); + TpcdsTableDef table_def; + table_def.name = tdef->name; + table_def.fl_child = tdef->flags & FL_CHILD ? 1 : 0; + table_def.fl_small = tdef->flags & FL_SMALL ? 1 : 0; + table_def.first_column = tdef->nFirstColumn; + table_def.children = children; + table_def.dsdGenContext = &dsdgenCtx_; + tableDefs_[table_id] = std::make_unique(table_def); +} + +std::vector>& DSDGenIterator::getTableDefs() { + return tableDefs_; +}; + +tpcds_builder_func DSDGenIterator::getTDefFunctionByNumber(int table_id) { + auto table_funcs = getTdefFunctionsByNumber(table_id); + return table_funcs->builder; +} + +void DSDGenIterator::initTableOffset(int32_t table_id, size_t offset) { + row_skip(table_id, offset, dsdgenCtx_); +} +void DSDGenIterator::genRow(int32_t table_id, size_t index) { + auto builder_func = getTDefFunctionByNumber(table_id); + builder_func((void*)&tableDefs_, index, dsdgenCtx_); + row_stop(table_id, dsdgenCtx_); +} + +int64_t DSDGenIterator::getRowCount(int32_t table) { + return get_rowcount(table, dsdgenCtx_); +} + +} // namespace facebook::presto::connector::tpcds diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/DSDGenIterator.h b/presto-native-execution/presto_cpp/main/connectors/tpcds/DSDGenIterator.h new file mode 100644 index 0000000000000..3a2641f6434bc --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/DSDGenIterator.h @@ -0,0 +1,71 @@ +/* + * Licensed 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. + */ + +#pragma once + +#include + +#include "presto_cpp/external/dsdgen/include/dsdgen-c/dist.h" +#include "presto_cpp/main/connectors/tpcds/utils/append_info-c.h" + +using namespace facebook::velox; +namespace facebook::presto::connector::tpcds { + +typedef int64_t ds_key_t; + +typedef int (*tpcds_builder_func)(void*, ds_key_t, DSDGenContext& dsdgenCtx); + +void initializeDSDgen( + double scale, + int32_t parallel, + int32_t child, + DSDGenContext& dsdGenContext); + +/// This class exposes a thread-safe and reproducible iterator over TPC-DS +/// synthetically generated data, backed by DSDGEN. +class DSDGenIterator { + public: + explicit DSDGenIterator(double scaleFactor, int32_t parallel, int32_t child); + + /// Initializes the table definition and the table schema. + void initializeTable(const std::vector& children, int table); + + /// Returns a vector of all the table definitions. + std::vector>& getTableDefs(); + + // Before generating records using the gen*() functions below, call the + // initTableOffset(int32_t table_id, size_t offset) function to correctly + // initialize the seed given the offset to be generated. + // table_id corresponds to the table that needs to be generated and offset + // specifies the number of rows to skip before using the gen*() functions. + void initTableOffset(int32_t table_id, size_t offset); + + /// Generate different types of records. + // table_id corresponds to the table that is to be generated and row is the + // row to be generated. + void genRow(int32_t table_id, size_t row); + + /// Gets the row count for a table. + ds_key_t getRowCount(int32_t table_id); + + // Gets the metadata for a table, which hold information about the mk_*() + // functions responsible for generating the data. + tpcds_builder_func getTDefFunctionByNumber(int table_id); + + protected: + DSDGenContext dsdgenCtx_; + std::vector> tableDefs_; +}; + +} // namespace facebook::presto::connector::tpcds diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnector.cpp b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnector.cpp new file mode 100644 index 0000000000000..15fe9c9bcce0e --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnector.cpp @@ -0,0 +1,190 @@ +/* + * Licensed 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. + */ + +#include "presto_cpp/main/connectors/tpcds/TpcdsConnector.h" +#include "presto_cpp/main/connectors/tpcds/DSDGenIterator.h" +#include "presto_cpp/presto_protocol/connector/tpcds/TpcdsConnectorProtocol.h" + +using namespace ::facebook::velox; +namespace facebook::presto::connector::tpcds { + +using facebook::presto::connector::tpcds::Table; + +std::string TpcdsTableHandle::toString() const { + return fmt::format( + "table: {}, scale factor: {}", toTableName(table_), scaleFactor_); +} + +TpcdsDataSource::TpcdsDataSource( + const std::shared_ptr& outputType, + const std::shared_ptr& tableHandle, + const std::unordered_map< + std::string, + std::shared_ptr>& columnHandles, + velox::memory::MemoryPool* FOLLY_NONNULL pool) + : pool_(pool) { + auto tpcdsTableHandle = + std::dynamic_pointer_cast(tableHandle); + VELOX_CHECK_NOT_NULL( + tpcdsTableHandle, "TableHandle must be an instance of TpcdsTableHandle"); + table_ = tpcdsTableHandle->getTpcdsTable(); + scaleFactor_ = tpcdsTableHandle->getScaleFactor(); + DSDGenIterator dsdGenIterator(scaleFactor_, 1, 1); + rowCount_ = dsdGenIterator.getRowCount(static_cast(table_)); + + auto tpcdsTableSchema = getTableSchema(tpcdsTableHandle->getTpcdsTable()); + VELOX_CHECK_NOT_NULL(tpcdsTableSchema, "TpcdsSchema can't be null."); + + outputColumnMappings_.reserve(outputType->size()); + + for (const auto& outputName : outputType->names()) { + auto it = columnHandles.find(outputName); + VELOX_CHECK( + it != columnHandles.end(), + "ColumnHandle is missing for output column '{}' on table '{}'", + outputName, + toTableName(table_)); + + auto handle = std::dynamic_pointer_cast(it->second); + VELOX_CHECK_NOT_NULL( + handle, + "ColumnHandle must be an instance of TpcdsColumnHandle " + "for '{}' on table '{}'", + handle->name(), + toTableName(table_)); + + auto idx = tpcdsTableSchema->getChildIdxIfExists(handle->name()); + VELOX_CHECK( + idx != std::nullopt, + "Column '{}' not found on TPC-DS table '{}'.", + handle->name(), + toTableName(table_)); + outputColumnMappings_.emplace_back(*idx); + } + outputType_ = outputType; +} + +RowVectorPtr TpcdsDataSource::projectOutputColumns(RowVectorPtr inputVector) { + std::vector children; + children.reserve(outputColumnMappings_.size()); + + for (const auto channel : outputColumnMappings_) { + children.emplace_back(inputVector->childAt(channel)); + } + + return std::make_shared( + pool_, + outputType_, + BufferPtr(), + inputVector->size(), + std::move(children)); +} + +void TpcdsDataSource::addSplit(std::shared_ptr split) { + VELOX_CHECK_EQ( + currentSplit_, + nullptr, + "Previous split has not been processed yet. Call next() to process the split."); + currentSplit_ = std::dynamic_pointer_cast(split); + VELOX_CHECK(currentSplit_, "Wrong type of split for TpcdsDataSource."); + + size_t partSize = + std::ceil((double)rowCount_ / (double)currentSplit_->totalParts_); + + splitOffset_ = partSize * currentSplit_->partNumber_; + splitEnd_ = splitOffset_ + partSize; +} + +std::optional TpcdsDataSource::next( + uint64_t size, + velox::ContinueFuture& /*future*/) { + VELOX_CHECK_NOT_NULL( + currentSplit_, "No split to process. Call addSplit() first."); + + size_t maxRows = std::min(size, (splitEnd_ - splitOffset_)); + vector_size_t parallel = currentSplit_->totalParts_; + vector_size_t child = currentSplit_->partNumber_; + auto outputVector = genTpcdsData( + table_, maxRows, splitOffset_, pool_, scaleFactor_, parallel, child); + + // If the split is exhausted. + if (!outputVector || outputVector->size() == 0) { + currentSplit_ = nullptr; + return nullptr; + } + + // splitOffset needs to advance based on maxRows passed to getTpcdsData(), and + // not the actual number of returned rows in the output vector, as they are + // not the same for lineitem. + splitOffset_ += maxRows; + completedRows_ += outputVector->size(); + completedBytes_ += outputVector->retainedSize(); + + return projectOutputColumns(outputVector); +} + +std::unique_ptr +TpcdsPrestoToVeloxConnector::toVeloxSplit( + const protocol::ConnectorId& catalogId, + const protocol::ConnectorSplit* connectorSplit, + const protocol::SplitContext* splitContext) const { + auto tpcdsSplit = + dynamic_cast(connectorSplit); + VELOX_CHECK_NOT_NULL( + tpcdsSplit, "Unexpected split type {}", connectorSplit->_type); + return std::make_unique( + catalogId, + splitContext->cacheable, + tpcdsSplit->totalParts, + tpcdsSplit->partNumber); +} + +std::unique_ptr +TpcdsPrestoToVeloxConnector::toVeloxColumnHandle( + const protocol::ColumnHandle* column, + const TypeParser& typeParser) const { + auto tpcdsColumn = + dynamic_cast(column); + VELOX_CHECK_NOT_NULL( + tpcdsColumn, "Unexpected column handle type {}", column->_type); + return std::make_unique( + tpcdsColumn->columnName); +} + +std::unique_ptr +TpcdsPrestoToVeloxConnector::toVeloxTableHandle( + const protocol::TableHandle& tableHandle, + const VeloxExprConverter& exprConverter, + const TypeParser& typeParser, + std::unordered_map< + std::string, + std::shared_ptr>& assignments) const { + auto tpcdsLayout = + std::dynamic_pointer_cast( + tableHandle.connectorTableLayout); + VELOX_CHECK_NOT_NULL( + tpcdsLayout, + "Unexpected layout type {}", + tableHandle.connectorTableLayout->_type); + return std::make_unique( + tableHandle.connectorId, + presto::connector::tpcds::fromTableName(tpcdsLayout->table.tableName), + tpcdsLayout->table.scaleFactor); +} + +std::unique_ptr +TpcdsPrestoToVeloxConnector::createConnectorProtocol() const { + return std::make_unique(); +} +} // namespace facebook::presto::connector::tpcds diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnector.h b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnector.h new file mode 100644 index 0000000000000..36dd55628fab2 --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnector.h @@ -0,0 +1,209 @@ +/* + * Licensed 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. + */ + +#pragma once + +#include "presto_cpp/main/connectors/tpcds/TpcdsConnectorSplit.h" +#include "presto_cpp/main/connectors/tpcds/TpcdsGen.h" +#include "presto_cpp/main/types/PrestoToVeloxConnector.h" +#include "velox/connectors/Connector.h" + +using namespace facebook::velox; +using namespace facebook::velox::connector; + +namespace facebook::presto::connector::tpcds { + +class TpcdsConnector; + +// TPC-DS column handle only needs the column name (all columns are generated in +// the same way). +class TpcdsColumnHandle : public velox::connector::ColumnHandle { + public: + explicit TpcdsColumnHandle(const std::string& name) : name_(name) {} + + const std::string& name() const { + return name_; + } + + private: + const std::string name_; +}; + +// TPC-DS table handle uses the underlying enum to describe the target table. +class TpcdsTableHandle : public ConnectorTableHandle { + public: + explicit TpcdsTableHandle( + std::string connectorId, + tpcds::Table table, + double scaleFactor = 1.0) + : ConnectorTableHandle(std::move(connectorId)), + table_(table), + scaleFactor_(scaleFactor) { + VELOX_CHECK_GE(scaleFactor, 0.0, "Tpcds scale factor must be non-negative"); + } + + ~TpcdsTableHandle() override {} + + std::string toString() const override; + + tpcds::Table getTpcdsTable() const { + return table_; + } + + double getScaleFactor() const { + return scaleFactor_; + } + + private: + const tpcds::Table table_; + double scaleFactor_; +}; + +class TpcdsDataSource : public velox::connector::DataSource { + public: + TpcdsDataSource( + const std::shared_ptr& outputType, + const std::shared_ptr& + tableHandle, + const std::unordered_map< + std::string, + std::shared_ptr>& columnHandles, + velox::memory::MemoryPool* FOLLY_NONNULL pool); + + void addSplit(std::shared_ptr split) override; + + void addDynamicFilter( + column_index_t /*outputChannel*/, + const std::shared_ptr& /*filter*/) override { + VELOX_NYI("Dynamic filters not supported by TpcdsConnector."); + } + + std::optional next(uint64_t size, velox::ContinueFuture& future) + override; + + uint64_t getCompletedRows() override { + return completedRows_; + } + + uint64_t getCompletedBytes() override { + return completedBytes_; + } + + std::unordered_map runtimeStats() override { + return {}; + } + + private: + RowVectorPtr projectOutputColumns(RowVectorPtr vector); + + tpcds::Table table_; + double scaleFactor_{1.0}; + size_t rowCount_{0}; + RowTypePtr outputType_; + + // Mapping between output columns and their indices (column_index_t) in the + // dsdgen generated datasets. + std::vector outputColumnMappings_; + + std::shared_ptr currentSplit_; + + // Offset of the first row in current split. + uint64_t splitOffset_{0}; + // Offset of the last row in current split. + uint64_t splitEnd_{0}; + + size_t completedRows_{0}; + size_t completedBytes_{0}; + + memory::MemoryPool* FOLLY_NONNULL pool_; +}; + +class TpcdsConnector final : public velox::connector::Connector { + public: + TpcdsConnector( + const std::string& id, + std::shared_ptr config, + folly::Executor* FOLLY_NULLABLE /*executor*/) + : Connector(id) {} + + std::unique_ptr createDataSource( + const std::shared_ptr& outputType, + const std::shared_ptr& tableHandle, + const std::unordered_map< + std::string, + std::shared_ptr>& columnHandles, + ConnectorQueryCtx* FOLLY_NONNULL connectorQueryCtx) override final { + return std::make_unique( + outputType, + tableHandle, + columnHandles, + connectorQueryCtx->memoryPool()); + } + + std::unique_ptr createDataSink( + RowTypePtr /*inputType*/, + std::shared_ptr< + ConnectorInsertTableHandle> /*connectorInsertTableHandle*/, + ConnectorQueryCtx* /*connectorQueryCtx*/, + CommitStrategy /*commitStrategy*/) override final { + VELOX_NYI("TpcdsConnector does not support data sink."); + } +}; + +class TpcdsConnectorFactory : public ConnectorFactory { + public: + static constexpr const char* kTpcdsConnectorName{"tpcds"}; + + TpcdsConnectorFactory() : ConnectorFactory(kTpcdsConnectorName) {} + + explicit TpcdsConnectorFactory(const char* connectorName) + : ConnectorFactory(connectorName) {} + + std::shared_ptr newConnector( + const std::string& id, + std::shared_ptr config, + folly::Executor* ioExecutor = nullptr, + folly::Executor* cpuExecutor = nullptr) override { + return std::make_shared(id, config, ioExecutor); + } +}; + +class TpcdsPrestoToVeloxConnector final : public PrestoToVeloxConnector { + public: + explicit TpcdsPrestoToVeloxConnector(std::string connectorId) + : PrestoToVeloxConnector(std::move(connectorId)) {} + + std::unique_ptr toVeloxSplit( + const protocol::ConnectorId& catalogId, + const protocol::ConnectorSplit* connectorSplit, + const protocol::SplitContext* splitContext) const final; + + std::unique_ptr toVeloxColumnHandle( + const protocol::ColumnHandle* column, + const TypeParser& typeParser) const final; + + std::unique_ptr toVeloxTableHandle( + const protocol::TableHandle& tableHandle, + const VeloxExprConverter& exprConverter, + const TypeParser& typeParser, + std::unordered_map< + std::string, + std::shared_ptr>& assignments) + const final; + + std::unique_ptr createConnectorProtocol() + const final; +}; + +} // namespace facebook::presto::connector::tpcds diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnectorSplit.h b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnectorSplit.h new file mode 100644 index 0000000000000..76c85c402dc32 --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsConnectorSplit.h @@ -0,0 +1,73 @@ +/* + * Licensed 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. + */ + +#pragma once + +#include +#include "velox/connectors/Connector.h" + +using namespace facebook::velox; + +namespace facebook::presto::connector::tpcds { + +struct TpcdsConnectorSplit : public velox::connector::ConnectorSplit { + explicit TpcdsConnectorSplit( + const std::string& connectorId, + size_t totalParts, + size_t partNumber) + : TpcdsConnectorSplit(connectorId, true, totalParts, partNumber) {} + + TpcdsConnectorSplit( + const std::string& connectorId, + bool cacheable, + size_t totalParts, + size_t partNumber) + : ConnectorSplit(connectorId, /*splitWeight=*/0, cacheable), + totalParts_(totalParts), + partNumber_(partNumber) { + VELOX_CHECK_GE(totalParts, 1, "totalParts must be >= 1"); + VELOX_CHECK_GT(totalParts, partNumber, "totalParts must be > partNumber"); + } + + // In how many parts the generated TPC-DS table will be segmented, roughly + // `rowCount / totalParts` + const vector_size_t totalParts_{1}; + + // Which of these parts will be read by this split. + const vector_size_t partNumber_{0}; +}; + +} // namespace facebook::presto::connector::tpcds + +template <> +struct fmt::formatter + : formatter { + auto format( + facebook::presto::connector::tpcds::TpcdsConnectorSplit s, + format_context& ctx) { + return formatter::format(s.toString(), ctx); + } +}; + +template <> +struct fmt::formatter< + std::shared_ptr> + : formatter { + auto format( + std::shared_ptr + s, + format_context& ctx) { + return formatter::format(s->toString(), ctx); + } +}; diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsGen.cpp b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsGen.cpp new file mode 100644 index 0000000000000..83a4f1769291a --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsGen.cpp @@ -0,0 +1,946 @@ +/* + * Licensed 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. + */ + +#include "presto_cpp/main/connectors/tpcds/TpcdsGen.h" +#include "presto_cpp/main/connectors/tpcds/DSDGenIterator.h" +#include "velox/vector/ComplexVector.h" + +using namespace facebook::velox; +namespace facebook::presto::connector::tpcds { + +namespace { +size_t getVectorSize(size_t rowCount, size_t maxRows, size_t offset) { + if (offset >= rowCount) { + return 0; + } + return std::min(rowCount - offset, maxRows); +} + +std::vector allocateChildVectors( + const RowTypePtr& type, + size_t vectorSize, + memory::MemoryPool* pool) { + std::vector vector; + vector.reserve(type->size()); + + for (const auto& childType : type->children()) { + vector.emplace_back(BaseVector::create(childType, vectorSize, pool)); + } + return vector; +} + +RowVectorPtr genTpcdsRowVector( + int32_t tableId, + memory::MemoryPool* pool, + RowTypePtr rowType, + std::vector>& tableDef) { + auto rowCount = tableDef[tableId]->rowIndex; + for (auto& child : tableDef[tableId]->children) { + child->resize(rowCount); + } + + return std::make_shared( + pool, + rowType, + BufferPtr(nullptr), + rowCount, + std::move(tableDef[tableId]->children)); +} + +RowVectorPtr genTpcdsTableData( + Table table, + memory::MemoryPool* pool, + size_t maxRows, + size_t offset, + double scaleFactor, + int32_t parallel, + int32_t child) { + // Create schema and allocate vectors. + auto rowType = getTableSchema(table); + auto table_id = static_cast(table); + DSDGenIterator dsdGenIterator(scaleFactor, parallel, child); + size_t vectorSize = + getVectorSize(dsdGenIterator.getRowCount(table_id), maxRows, offset); + auto children = allocateChildVectors(rowType, vectorSize, pool); + dsdGenIterator.initTableOffset(table_id, offset); + dsdGenIterator.initializeTable(children, table_id); + auto& tableDef = dsdGenIterator.getTableDefs(); + for (size_t i = 0; i < vectorSize; ++i) { + dsdGenIterator.genRow(table_id, i + offset + 1); + } + return std::make_shared( + pool, + rowType, + BufferPtr(nullptr), + vectorSize, + std::move(tableDef[table_id]->children)); +} + +RowVectorPtr genTpcdsParentAndChildTable( + memory::MemoryPool* pool, + size_t maxRows, + size_t offset, + double scaleFactor, + int32_t parallel, + int32_t child, + Table parentTable, + Table childTable, + bool childTableCall) { + // Whenever a call to generate a table which is either marked as a + // parent or a child is requested, both the child and parent tables + // need to be populated. + + auto parentTableType = getTableSchema(parentTable); + DSDGenIterator dsdGenIterator(scaleFactor, parallel, child); + size_t parentTableVectorSize = getVectorSize( + dsdGenIterator.getRowCount(static_cast(parentTable)), + maxRows, + offset); + + size_t parentTableUpperBound = parentTableVectorSize * 16; + auto children = + allocateChildVectors(parentTableType, parentTableUpperBound, pool); + + auto childTableType = getTableSchema(childTable); + auto childChildren = + allocateChildVectors(childTableType, parentTableUpperBound, pool); + + auto parentTableId = static_cast(parentTable); + auto childTableId = static_cast(childTable); + + dsdGenIterator.initTableOffset(parentTableId, offset); + dsdGenIterator.initializeTable(children, parentTableId); + dsdGenIterator.initializeTable(childChildren, childTableId); + auto& tableDef = dsdGenIterator.getTableDefs(); + for (size_t i = 0; i < parentTableVectorSize; ++i) { + dsdGenIterator.genRow(parentTableId, i + offset + 1); + } + if (childTableCall) { + return genTpcdsRowVector(childTableId, pool, childTableType, tableDef); + } else { + return genTpcdsRowVector(parentTableId, pool, parentTableType, tableDef); + } +} +} // namespace + +static const RowTypePtr callCenterType = ROW( + {"cc_call_center_sk", "cc_call_center_id", + "cc_rec_start_date", "cc_rec_end_date", + "cc_closed_date_sk", "cc_open_date_sk", + "cc_name", "cc_class", + "cc_employees", "cc_sq_ft", + "cc_hours", "cc_manager", + "cc_mkt_id", "cc_mkt_class", + "cc_mkt_desc", "cc_market_manager", + "cc_division", "cc_division_name", + "cc_company", "cc_company_name", + "cc_street_number", "cc_street_name", + "cc_street_type", "cc_suite_number", + "cc_city", "cc_county", + "cc_state", "cc_zip", + "cc_country", "cc_gmt_offset", + "cc_tax_percentage"}, + {BIGINT(), VARCHAR(), DATE(), DATE(), INTEGER(), INTEGER(), + VARCHAR(), VARCHAR(), INTEGER(), INTEGER(), VARCHAR(), VARCHAR(), + INTEGER(), VARCHAR(), VARCHAR(), VARCHAR(), INTEGER(), VARCHAR(), + INTEGER(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), + VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), DECIMAL(5, 2), + DECIMAL(5, 2)}); + +static const RowTypePtr catalogPageType = + ROW({"cp_catalog_page_sk", + "cp_catalog_page_id", + "cp_start_date_sk", + "cp_end_date_sk", + "cp_department", + "cp_catalog_number", + "cp_catalog_page_number", + "cp_description", + "cp_type"}, + {BIGINT(), + VARCHAR(), + INTEGER(), + INTEGER(), + VARCHAR(), + INTEGER(), + INTEGER(), + VARCHAR(), + VARCHAR()}); + +static const RowTypePtr catalogReturnsType = ROW( + {"cr_returned_date_sk", + "cr_returned_time_sk", + "cr_item_sk", + "cr_refunded_customer_sk", + "cr_refunded_cdemo_sk", + "cr_refunded_hdemo_sk", + "cr_refunded_addr_sk", + "cr_returning_customer_sk", + "cr_returning_cdemo_sk", + "cr_returning_hdemo_sk", + "cr_returning_addr_sk", + "cr_call_center_sk", + "cr_catalog_page_sk", + "cr_ship_mode_sk", + "cr_warehouse_sk", + "cr_reason_sk", + "cr_order_number", + "cr_return_quantity", + "cr_return_amount", + "cr_return_tax", + "cr_return_amt_inc_tax", + "cr_fee", + "cr_return_ship_cost", + "cr_refunded_cash", + "cr_reversed_charge", + "cr_store_credit", + "cr_net_loss"}, + {BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), INTEGER(), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2)}); + +static const RowTypePtr catalogSalesType = ROW( + {"cs_sold_date_sk", + "cs_sold_time_sk", + "cs_ship_date_sk", + "cs_bill_customer_sk", + "cs_bill_cdemo_sk", + "cs_bill_hdemo_sk", + "cs_bill_addr_sk", + "cs_ship_customer_sk", + "cs_ship_cdemo_sk", + "cs_ship_hdemo_sk", + "cs_ship_addr_sk", + "cs_call_center_sk", + "cs_catalog_page_sk", + "cs_ship_mode_sk", + "cs_warehouse_sk", + "cs_item_sk", + "cs_promo_sk", + "cs_order_number", + "cs_quantity", + "cs_wholesale_cost", + "cs_list_price", + "cs_sales_price", + "cs_ext_discount_amt", + "cs_ext_sales_price", + "cs_ext_wholesale_cost", + "cs_ext_list_price", + "cs_ext_tax", + "cs_coupon_amt", + "cs_ext_ship_cost", + "cs_net_paid", + "cs_net_paid_inc_tax", + "cs_net_paid_inc_ship", + "cs_net_paid_inc_ship_tax", + "cs_net_profit"}, + {BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), INTEGER(), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2)}); + +static const RowTypePtr customerType = ROW( + { + "c_customer_sk", + "c_customer_id", + "c_current_cdemo_sk", + "c_current_hdemo_sk", + "c_current_addr_sk", + "c_first_shipto_date_sk", + "c_first_sales_date_sk", + "c_salutation", + "c_first_name", + "c_last_name", + "c_preferred_cust_flag", + "c_birth_day", + "c_birth_month", + "c_birth_year", + "c_birth_country", + "c_login", + "c_email_address", + "c_last_review_date_sk", + }, + { + BIGINT(), + VARCHAR(), + BIGINT(), + BIGINT(), + BIGINT(), + BIGINT(), + BIGINT(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + INTEGER(), + INTEGER(), + INTEGER(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + BIGINT(), + }); + +static const RowTypePtr customerAddressType = + ROW({"ca_address_sk", + "ca_address_id", + "ca_street_number", + "ca_street_name", + "ca_street_type", + "ca_suite_number", + "ca_city", + "ca_county", + "ca_state", + "ca_zip", + "ca_country", + "ca_gmt_offset", + "ca_location_type"}, + {BIGINT(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + DECIMAL(5, 2), + VARCHAR()}); + +static const RowTypePtr customerDemographicsType = + ROW({"cd_demo_sk", + "cd_gender", + "cd_marital_status", + "cd_education_status", + "cd_purchase_estimate", + "cd_credit_rating", + "cd_dep_count", + "cd_dep_employed_count", + "cd_dep_college_count"}, + {BIGINT(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + INTEGER(), + VARCHAR(), + INTEGER(), + INTEGER(), + INTEGER()}); + +static const RowTypePtr dateDimType = ROW( + { + "d_date_sk", + "d_date_id", + "d_date", + "d_month_seq", + "d_week_seq", + "d_quarter_seq", + "d_year", + "d_dow", + "d_moy", + "d_dom", + "d_qoy", + "d_fy_year", + "d_fy_quarter_seq", + "d_fy_week_seq", + "d_day_name", + "d_quarter_name", + "d_holiday", + "d_weekend", + "d_following_holiday", + "d_first_dom", + "d_last_dom", + "d_same_day_ly", + "d_same_day_lq", + "d_current_day", + "d_current_week", + "d_current_month", + "d_current_quarter", + "d_current_year", + }, + { + BIGINT(), VARCHAR(), DATE(), INTEGER(), INTEGER(), INTEGER(), + INTEGER(), INTEGER(), INTEGER(), INTEGER(), INTEGER(), INTEGER(), + INTEGER(), INTEGER(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), + VARCHAR(), INTEGER(), INTEGER(), INTEGER(), INTEGER(), VARCHAR(), + VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), + }); + +static const RowTypePtr householdDemographicsType = + ROW({"hd_demo_sk", + "hd_income_band_sk", + "hd_buy_potential", + "hd_dep_count", + "hd_vehicle_count"}, + {BIGINT(), BIGINT(), VARCHAR(), INTEGER(), INTEGER()}); + +static const RowTypePtr incomeBandType = + ROW({"ib_income_band_sk", "ib_lower_bound", "ib_upper_bound"}, + {BIGINT(), INTEGER(), INTEGER()}); + +static const RowTypePtr inventoryType = ROW( + {"inv_date_sk", "inv_item_sk", "inv_warehouse_sk", "inv_quantity_on_hand"}, + {BIGINT(), BIGINT(), BIGINT(), INTEGER()}); + +static const RowTypePtr itemType = ROW( + {"i_item_sk", "i_item_id", "i_rec_start_date", "i_rec_end_date", + "i_item_desc", "i_current_price", "i_wholesale_cost", "i_brand_id", + "i_brand", "i_class_id", "i_class", "i_category_id", + "i_category", "i_manufact_id", "i_manufact", "i_size", + "i_formulation", "i_color", "i_units", "i_container", + "i_manager_id", "i_product_name"}, + {BIGINT(), VARCHAR(), DATE(), DATE(), VARCHAR(), DECIMAL(7, 2), + DECIMAL(7, 2), INTEGER(), VARCHAR(), INTEGER(), VARCHAR(), INTEGER(), + VARCHAR(), INTEGER(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), + VARCHAR(), VARCHAR(), INTEGER(), VARCHAR()}); + +static const RowTypePtr promotionType = + ROW({"p_promo_sk", + "p_promo_id", + "p_start_date_sk", + "p_end_date_sk", + "p_item_sk", + "p_cost", + "p_response_targe", + "p_promo_name", + "p_channel_dmail", + "p_channel_email", + "p_channel_catalog", + "p_channel_tv", + "p_channel_radio", + "p_channel_press", + "p_channel_event", + "p_channel_demo", + "p_channel_details", + "p_purpose", + "p_discount_active"}, + {BIGINT(), + VARCHAR(), + BIGINT(), + BIGINT(), + BIGINT(), + DECIMAL(15, 2), + INTEGER(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR()}); + +static const RowTypePtr reasonType = + ROW({"r_reason_sk", "r_reason_id", "r_reason_desc"}, + {BIGINT(), VARCHAR(), VARCHAR()}); + +static const RowTypePtr shipModeType = + ROW({"sm_ship_mode_sk", + "sm_ship_mode_id", + "sm_type", + "sm_code", + "sm_carrier", + "sm_contract"}, + {BIGINT(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR()}); + +static const RowTypePtr storeType = ROW( + { + "s_store_sk", + "s_store_id", + "s_rec_start_date", + "s_rec_end_date", + "s_closed_date_sk", + "s_store_name", + "s_number_employees", + "s_floor_space", + "s_hours", + "s_manager", + "s_market_id", + "s_geography_class", + "s_market_desc", + "s_market_manager", + "s_division_id", + "s_division_name", + "s_company_id", + "s_company_name", + "s_street_number", + "s_street_name", + "s_street_type", + "s_suite_number", + "s_city", + "s_county", + "s_state", + "s_zip", + "s_country", + "s_gmt_offset", + "s_tax_precentage", + }, + { + BIGINT(), VARCHAR(), DATE(), DATE(), BIGINT(), + VARCHAR(), INTEGER(), INTEGER(), VARCHAR(), VARCHAR(), + INTEGER(), VARCHAR(), VARCHAR(), VARCHAR(), INTEGER(), + VARCHAR(), INTEGER(), VARCHAR(), VARCHAR(), VARCHAR(), + VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), + VARCHAR(), VARCHAR(), DECIMAL(5, 2), DECIMAL(5, 2), + }); + +static const RowTypePtr storeReturnsType = + ROW({"sr_returned_date_sk", + "sr_return_time_sk", + "sr_item_sk", + "sr_customer_sk", + "sr_cdemo_sk", + "sr_hdemo_sk", + "sr_addr_sk", + "sr_store_sk", + "sr_reason_sk", + "sr_ticket_number", + "sr_return_quantity", + "sr_return_amt", + "sr_return_tax", + "sr_return_amt_inc_tax", + "sr_fee", + "sr_return_ship_cost", + "sr_refunded_cash", + "sr_reversed_charge", + "sr_store_credit", + "sr_net_loss"}, + {BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), INTEGER(), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2)}); + +static const RowTypePtr storeSalesType = ROW( + {"ss_sold_date_sk", "ss_sold_time_sk", "ss_item_sk", + "ss_customer_sk", "ss_cdemo_sk", "ss_hdemo_sk", + "ss_addr_sk", "ss_store_sk", "ss_promo_sk", + "ss_ticket_number", "ss_quantity", "ss_wholesale_cost", + "ss_list_price", "ss_sales_price", "ss_ext_discount_amt", + "ss_ext_sales_price", "ss_ext_wholesale_cost", "ss_ext_list_price", + "ss_ext_tax", "ss_coupon_amt", "ss_net_paid", + "ss_net_paid_inc_tax", "ss_net_profit"}, + {BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + INTEGER(), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2)}); + +static const RowTypePtr timeDimType = + ROW({"t_time_sk", + "t_time_id", + "t_time", + "t_hour", + "t_minute", + "t_second", + "t_am_pm", + "t_shift", + "t_sub_shift", + "t_meal_time"}, + {BIGINT(), + VARCHAR(), + INTEGER(), + INTEGER(), + INTEGER(), + INTEGER(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR()}); + +static const RowTypePtr warehouseType = + ROW({"w_warehouse_sk", + "w_warehouse_id", + "w_warehouse_name", + "w_warehouse_sq_ft", + "w_street_number", + "w_street_name", + "w_street_type", + "w_suite_number", + "w_city", + "w_county", + "w_state", + "w_zip", + "w_country", + "w_gmt_offset"}, + {BIGINT(), + VARCHAR(), + VARCHAR(), + INTEGER(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + VARCHAR(), + DECIMAL(5, 2)}); + +static const RowTypePtr webPageType = + ROW({"wp_web_page_sk", + "wp_web_page_id", + "wp_rec_start_date", + "wp_rec_end_date", + "wp_creation_date_sk", + "wp_access_date_sk", + "wp_autogen_flag", + "wp_customer_sk", + "wp_url", + "wp_type", + "wp_char_count", + "wp_link_count", + "wp_image_count", + "wp_max_ad_count"}, + {BIGINT(), + VARCHAR(), + DATE(), + DATE(), + BIGINT(), + BIGINT(), + VARCHAR(), + BIGINT(), + VARCHAR(), + VARCHAR(), + INTEGER(), + INTEGER(), + INTEGER(), + INTEGER()}); + +static const RowTypePtr webReturnsType = ROW( + {"wr_returned_date_sk", + "wr_returned_time_sk", + "wr_item_sk", + "wr_refunded_customer_sk", + "wr_refunded_cdemo_sk", + "wr_refunded_hdemo_sk", + "wr_refunded_addr_sk", + "wr_returning_customer_sk", + "wr_returning_cdemo_sk", + "wr_returning_hdemo_sk", + "wr_returning_addr_sk", + "wr_web_page_sk", + "wr_reason_sk", + "wr_order_number", + "wr_return_quantity", + "wr_return_amt", + "wr_return_tax", + "wr_return_amt_inc_tax", + "wr_fee", + "wr_return_ship_cost", + "wr_refunded_cash", + "wr_reversed_charge", + "wr_account_credit", + "wr_net_loss"}, + {BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), INTEGER(), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2)}); + +static const RowTypePtr webSalesType = ROW( + {"ws_sold_date_sk", + "ws_sold_time_sk", + "ws_ship_date_sk", + "ws_item_sk", + "ws_bill_customer_sk", + "ws_bill_cdemo_sk", + "ws_bill_hdemo_sk", + "ws_bill_addr_sk", + "ws_ship_customer_sk", + "ws_ship_cdemo_sk", + "ws_ship_hdemo_sk", + "ws_ship_addr_sk", + "ws_web_page_sk", + "ws_web_site_sk", + "ws_ship_mode_sk", + "ws_warehouse_sk", + "ws_promo_sk", + "ws_order_number", + "ws_quantity", + "ws_wholesale_cost", + "ws_list_price", + "ws_sales_price", + "ws_ext_discount_amt", + "ws_ext_sales_price", + "ws_ext_wholesale_cost", + "ws_ext_list_price", + "ws_ext_tax", + "ws_coupon_amt", + "ws_ext_ship_cost", + "ws_net_paid", + "ws_net_paid_inc_tax", + "ws_net_paid_inc_ship", + "ws_net_paid_inc_ship_tax", + "ws_net_profit"}, + {BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), BIGINT(), BIGINT(), + BIGINT(), BIGINT(), BIGINT(), INTEGER(), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), + DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2), DECIMAL(7, 2)}); + +static const RowTypePtr websiteType = ROW( + {"web_site_sk", "web_site_id", "web_rec_start_date", + "web_rec_end_date", "web_name", "web_open_date_sk", + "web_close_date_sk", "web_class", "web_manager", + "web_mkt_id", "web_mkt_class", "web_mkt_desc", + "web_market_manager", "web_company_id", "web_company_name", + "web_street_number", "web_street_name", "web_street_type", + "web_suite_number", "web_city", "web_county", + "web_state", "web_zip", "web_country", + "web_gmt_offset", "web_tax_percentage"}, + {BIGINT(), VARCHAR(), DATE(), DATE(), VARCHAR(), BIGINT(), + BIGINT(), VARCHAR(), VARCHAR(), INTEGER(), VARCHAR(), VARCHAR(), + VARCHAR(), INTEGER(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), + VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR(), + DECIMAL(5, 2), DECIMAL(5, 2)}); + +const RowTypePtr getTableSchema(Table table) { + switch (table) { + case Table::TBL_CALL_CENTER: + return callCenterType; + case Table::TBL_CATALOG_PAGE: + return catalogPageType; + case Table::TBL_CATALOG_RETURNS: + return catalogReturnsType; + case Table::TBL_CATALOG_SALES: + return catalogSalesType; + case Table::TBL_CUSTOMER: + return customerType; + case Table::TBL_CUSTOMER_ADDRESS: + return customerAddressType; + case Table::TBL_CUSTOMER_DEMOGRAPHICS: + return customerDemographicsType; + case Table::TBL_DATE_DIM: + return dateDimType; + case Table::TBL_HOUSEHOLD_DEMOGRAPHICS: + return householdDemographicsType; + case Table::TBL_INCOME_BAND: + return incomeBandType; + case Table::TBL_INVENTORY: + return inventoryType; + case Table::TBL_ITEM: + return itemType; + case Table::TBL_PROMOTION: + return promotionType; + case Table::TBL_REASON: + return reasonType; + case Table::TBL_SHIP_MODE: + return shipModeType; + case Table::TBL_STORE: + return storeType; + case Table::TBL_STORE_RETURNS: + return storeReturnsType; + case Table::TBL_STORE_SALES: + return storeSalesType; + case Table::TBL_TIME_DIM: + return timeDimType; + case Table::TBL_WAREHOUSE: + return warehouseType; + case Table::TBL_WEB_PAGE: + return webPageType; + case Table::TBL_WEB_RETURNS: + return webReturnsType; + case Table::TBL_WEB_SALES: + return webSalesType; + case Table::TBL_WEB_SITE: + return websiteType; + default: + VELOX_UNREACHABLE(); + } +} + +std::string toTableName(Table table) { + switch (table) { + case Table::TBL_CALL_CENTER: + return "call_center"; + case Table::TBL_CATALOG_PAGE: + return "catalog_page"; + case Table::TBL_CATALOG_RETURNS: + return "catalog_returns"; + case Table::TBL_CATALOG_SALES: + return "catalog_sales"; + case Table::TBL_CUSTOMER: + return "customer"; + case Table::TBL_CUSTOMER_ADDRESS: + return "customer_address"; + case Table::TBL_CUSTOMER_DEMOGRAPHICS: + return "customer_demographics"; + case Table::TBL_DATE_DIM: + return "date_dim"; + case Table::TBL_HOUSEHOLD_DEMOGRAPHICS: + return "household_demographics"; + case Table::TBL_INCOME_BAND: + return "income_band"; + case Table::TBL_INVENTORY: + return "inventory"; + case Table::TBL_ITEM: + return "item"; + case Table::TBL_PROMOTION: + return "promotion"; + case Table::TBL_REASON: + return "reason"; + case Table::TBL_SHIP_MODE: + return "ship_mode"; + case Table::TBL_STORE: + return "store"; + case Table::TBL_STORE_RETURNS: + return "store_returns"; + case Table::TBL_STORE_SALES: + return "store_sales"; + case Table::TBL_TIME_DIM: + return "time_dim"; + case Table::TBL_WAREHOUSE: + return "warehouse"; + case Table::TBL_WEB_PAGE: + return "web_page"; + case Table::TBL_WEB_RETURNS: + return "web_returns"; + case Table::TBL_WEB_SALES: + return "web_sales"; + case Table::TBL_WEB_SITE: + return "web_site"; + default: + VELOX_UNREACHABLE(); + } +} + +Table fromTableName(const std::string_view& tableName) { + static const std::unordered_map map{ + {"call_center", Table::TBL_CALL_CENTER}, + {"catalog_page", Table::TBL_CATALOG_PAGE}, + {"catalog_returns", Table::TBL_CATALOG_RETURNS}, + {"catalog_sales", Table::TBL_CATALOG_SALES}, + {"customer", Table::TBL_CUSTOMER}, + {"customer_address", Table::TBL_CUSTOMER_ADDRESS}, + {"customer_demographics", Table::TBL_CUSTOMER_DEMOGRAPHICS}, + {"date_dim", Table::TBL_DATE_DIM}, + {"household_demographics", Table::TBL_HOUSEHOLD_DEMOGRAPHICS}, + {"income_band", Table::TBL_INCOME_BAND}, + {"inventory", Table::TBL_INVENTORY}, + {"item", Table::TBL_ITEM}, + {"promotion", Table::TBL_PROMOTION}, + {"reason", Table::TBL_REASON}, + {"ship_mode", Table::TBL_SHIP_MODE}, + {"store", Table::TBL_STORE}, + {"store_returns", Table::TBL_STORE_RETURNS}, + {"store_sales", Table::TBL_STORE_SALES}, + {"time_dim", Table::TBL_TIME_DIM}, + {"warehouse", Table::TBL_WAREHOUSE}, + {"web_page", Table::TBL_WEB_PAGE}, + {"web_returns", Table::TBL_WEB_RETURNS}, + {"web_sales", Table::TBL_WEB_SALES}, + {"web_site", Table::TBL_WEB_SITE}, + }; + + auto it = map.find(tableName); + if (it != map.end()) { + return it->second; + } + throw std::invalid_argument( + fmt::format("Invalid TPC-DS table name: '{}'", tableName)); +} + +RowVectorPtr genTpcdsData( + Table table, + size_t maxRows, + size_t offset, + memory::MemoryPool* pool, + double scaleFactor, + int32_t parallel, + int32_t child) { + switch (table) { + Table parentTable, childTable; + case Table::TBL_CATALOG_RETURNS: + case Table::TBL_CATALOG_SALES: + parentTable = Table::TBL_CATALOG_SALES; + childTable = Table::TBL_CATALOG_RETURNS; + return genTpcdsParentAndChildTable( + pool, + maxRows, + offset, + scaleFactor, + parallel, + child, + parentTable, + childTable, + table == childTable); + case Table::TBL_WEB_RETURNS: + case Table::TBL_WEB_SALES: + parentTable = Table::TBL_WEB_SALES; + childTable = Table::TBL_WEB_RETURNS; + return genTpcdsParentAndChildTable( + pool, + maxRows, + offset, + scaleFactor, + parallel, + child, + parentTable, + childTable, + table == childTable); + case Table::TBL_STORE_RETURNS: + case Table::TBL_STORE_SALES: + parentTable = Table::TBL_STORE_SALES; + childTable = Table::TBL_STORE_RETURNS; + return genTpcdsParentAndChildTable( + pool, + maxRows, + offset, + scaleFactor, + parallel, + child, + parentTable, + childTable, + table == childTable); + case Table::TBL_CALL_CENTER: + case Table::TBL_CATALOG_PAGE: + case Table::TBL_CUSTOMER: + case Table::TBL_CUSTOMER_ADDRESS: + case Table::TBL_CUSTOMER_DEMOGRAPHICS: + case Table::TBL_DATE_DIM: + case Table::TBL_HOUSEHOLD_DEMOGRAPHICS: + case Table::TBL_INCOME_BAND: + case Table::TBL_INVENTORY: + case Table::TBL_ITEM: + case Table::TBL_PROMOTION: + case Table::TBL_REASON: + case Table::TBL_SHIP_MODE: + case Table::TBL_STORE: + case Table::TBL_TIME_DIM: + case Table::TBL_WAREHOUSE: + case Table::TBL_WEB_PAGE: + case Table::TBL_WEB_SITE: + return genTpcdsTableData( + table, pool, maxRows, offset, scaleFactor, parallel, child); + default: + VELOX_UNREACHABLE(); + } +} +} // namespace facebook::presto::connector::tpcds diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsGen.h b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsGen.h new file mode 100644 index 0000000000000..a2df6a340e213 --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/TpcdsGen.h @@ -0,0 +1,99 @@ +/* + * Licensed 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. + */ + +#pragma once + +#include "velox/common/memory/Memory.h" + +namespace facebook::velox { +class RowVector; +using RowVectorPtr = std::shared_ptr; +class RowType; +using RowTypePtr = std::shared_ptr; +} // namespace facebook::velox + +namespace facebook::presto::connector::tpcds { + +/// This file uses TPC-DS DSDGEN to generate data encoded using Velox Vectors. + +enum class Table : uint8_t { + TBL_CALL_CENTER, + TBL_CATALOG_PAGE, + TBL_CATALOG_RETURNS, + TBL_CATALOG_SALES, + TBL_CUSTOMER, + TBL_CUSTOMER_ADDRESS, + TBL_CUSTOMER_DEMOGRAPHICS, + TBL_DATE_DIM, + TBL_HOUSEHOLD_DEMOGRAPHICS, + TBL_INCOME_BAND, + TBL_INVENTORY, + TBL_ITEM, + TBL_PROMOTION, + TBL_REASON, + TBL_SHIP_MODE, + TBL_STORE, + TBL_STORE_RETURNS, + TBL_STORE_SALES, + TBL_TIME_DIM, + TBL_WAREHOUSE, + TBL_WEB_PAGE, + TBL_WEB_RETURNS, + TBL_WEB_SALES, + TBL_WEB_SITE +}; + +static const auto tables = { + tpcds::Table::TBL_CALL_CENTER, + tpcds::Table::TBL_CATALOG_PAGE, + tpcds::Table::TBL_CATALOG_RETURNS, + tpcds::Table::TBL_CATALOG_SALES, + tpcds::Table::TBL_CUSTOMER, + tpcds::Table::TBL_CUSTOMER_ADDRESS, + tpcds::Table::TBL_CUSTOMER_DEMOGRAPHICS, + tpcds::Table::TBL_DATE_DIM, + tpcds::Table::TBL_HOUSEHOLD_DEMOGRAPHICS, + tpcds::Table::TBL_INCOME_BAND, + tpcds::Table::TBL_INVENTORY, + tpcds::Table::TBL_ITEM, + tpcds::Table::TBL_PROMOTION, + tpcds::Table::TBL_REASON, + tpcds::Table::TBL_SHIP_MODE, + tpcds::Table::TBL_STORE, + tpcds::Table::TBL_STORE_RETURNS, + tpcds::Table::TBL_STORE_SALES, + tpcds::Table::TBL_TIME_DIM, + tpcds::Table::TBL_WAREHOUSE, + tpcds::Table::TBL_WEB_PAGE, + tpcds::Table::TBL_WEB_RETURNS, + tpcds::Table::TBL_WEB_SALES, + tpcds::Table::TBL_WEB_SITE}; + +/// Returns table name as a string. +std::string toTableName(Table table); + +/// Returns the schema (RowType) for a particular TPC-DS table. +const velox::RowTypePtr getTableSchema(Table table); + +Table fromTableName(const std::string_view& tableName); + +velox::RowVectorPtr genTpcdsData( + Table table, + size_t maxRows, + size_t offset, + velox::memory::MemoryPool* pool, + double scaleFactor, + int32_t parallel, + int32_t child); +} // namespace facebook::presto::connector::tpcds diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/utils/append_info-c.cpp b/presto-native-execution/presto_cpp/main/connectors/tpcds/utils/append_info-c.cpp new file mode 100644 index 0000000000000..72edd76819806 --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/utils/append_info-c.cpp @@ -0,0 +1,158 @@ +/* + * Licensed 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. + */ + +#include "append_info-c.h" + +#include +#include "presto_cpp/external/dsdgen/include/dsdgen-c/append_info.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/config.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/date.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/nulls.h" +#include "presto_cpp/external/dsdgen/include/dsdgen-c/porting.h" +#include "velox/vector/FlatVector.h" + +using namespace facebook::velox; +using namespace facebook::presto::connector::tpcds; +append_info* append_info_get(void* info_list, int table_id) { + auto& append_vector = + *((std::vector>*)info_list); + return (append_info*)append_vector[table_id].get(); +} + +bool facebook::presto::connector::tpcds::TpcdsTableDef::IsNull(int32_t column) { + return nullCheck(column, *dsdGenContext); +} + +void append_row_start(append_info info) { + auto append_info = (TpcdsTableDef*)info; +} + +void append_row_end(append_info info) { + auto append_info = (TpcdsTableDef*)info; + append_info->colIndex %= append_info->children.size(); + append_info->rowIndex++; +} + +void append_varchar( + int32_t column, + append_info info, + const char* value, + bool fillEmptyStringAsNull) { + auto append_info = (TpcdsTableDef*)info; + if (((append_info->IsNull(column)) || (!value) || (*value == '\0')) && + (fillEmptyStringAsNull)) { + append_info->children[append_info->colIndex]->setNull( + append_info->rowIndex, true); + } else { + append_info->children[append_info->colIndex] + ->asFlatVector() + ->set(append_info->rowIndex, value); + } + append_info->colIndex++; +} + +void append_varchar( + int32_t column, + append_info info, + std::string value, + bool fillEmptyStringAsNull) { + append_varchar(column, info, value.data(), fillEmptyStringAsNull); +} + +void append_key(int32_t column, append_info info, int64_t value) { + auto append_info = (TpcdsTableDef*)info; + if (append_info->IsNull(column) || value < 0) { + append_info->children[append_info->colIndex]->setNull( + append_info->rowIndex, true); + } else { + append_info->children[append_info->colIndex]->asFlatVector()->set( + append_info->rowIndex, value); + } + append_info->colIndex++; +} + +void append_integer(int32_t column, append_info info, int32_t value) { + auto append_info = (TpcdsTableDef*)info; + if (append_info->IsNull(column)) { + append_info->children[append_info->colIndex]->setNull( + append_info->rowIndex, true); + } else { + append_info->children[append_info->colIndex]->asFlatVector()->set( + append_info->rowIndex, value); + } + append_info->colIndex++; +} + +void append_boolean(int32_t column, append_info info, int32_t value) { + auto append_info = (TpcdsTableDef*)info; + if (append_info->IsNull(column)) { + append_info->children[append_info->colIndex]->setNull( + append_info->rowIndex, true); + } else { + append_info->children[append_info->colIndex]->asFlatVector()->set( + append_info->rowIndex, value != 0); + } + append_info->colIndex++; +} + +// value is a Julian date +// FIXME: direct int conversion, offsets should be constant +void append_date(int32_t column, append_info info, int64_t value) { + auto append_info = (TpcdsTableDef*)info; + if (append_info->IsNull(column) || value < 0) { + append_info->children[append_info->colIndex]->setNull( + append_info->rowIndex, true); + } else { + date_t dTemp; + jtodt(&dTemp, (int)value); + auto stringDate = + fmt::format("{}-{}-{}", dTemp.year, dTemp.month, dTemp.day); + auto date = DATE()->toDays(stringDate); + append_info->children[append_info->colIndex]->asFlatVector()->set( + append_info->rowIndex, date); + } + append_info->colIndex++; +} + +void append_decimal(int32_t column, append_info info, decimal_t* val) { + auto append_info = (TpcdsTableDef*)info; + if (append_info->IsNull(column)) { + append_info->children[append_info->colIndex]->setNull( + append_info->rowIndex, true); + } else { + auto type = append_info->children[append_info->colIndex]->type(); + if (type->isShortDecimal()) { + append_info->children[append_info->colIndex] + ->asFlatVector() + ->set(append_info->rowIndex, val->number); + } else { + append_info->children[append_info->colIndex] + ->asFlatVector() + ->set(append_info->rowIndex, val->number); + } + } + append_info->colIndex++; +} + +void append_integer_decimal(int32_t column, append_info info, int32_t value) { + auto append_info = (TpcdsTableDef*)info; + if (append_info->IsNull(column)) { + append_info->children[append_info->colIndex]->setNull( + append_info->rowIndex, true); + } else { + append_info->children[append_info->colIndex]->asFlatVector()->set( + append_info->rowIndex, (int64_t)value * 100); + } + append_info->colIndex++; +} diff --git a/presto-native-execution/presto_cpp/main/connectors/tpcds/utils/append_info-c.h b/presto-native-execution/presto_cpp/main/connectors/tpcds/utils/append_info-c.h new file mode 100644 index 0000000000000..a02e292c6a859 --- /dev/null +++ b/presto-native-execution/presto_cpp/main/connectors/tpcds/utils/append_info-c.h @@ -0,0 +1,38 @@ +/* + * Licensed 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. + */ + +#pragma once + +#include +#include "presto_cpp/external/dsdgen/include/dsdgen-c/dist.h" + +namespace facebook::velox { +class BaseVector; +using VectorPtr = std::shared_ptr; +} // namespace facebook::velox + +namespace facebook::presto::connector::tpcds { + +struct TpcdsTableDef { + const char* name; + int fl_small; + int fl_child; + int first_column; + int colIndex = 0; + int rowIndex = 0; + DSDGenContext* dsdGenContext; + std::vector children; + bool IsNull(int32_t column); +}; +} // namespace facebook::presto::connector::tpcds diff --git a/presto-native-execution/presto_cpp/main/tests/CMakeLists.txt b/presto-native-execution/presto_cpp/main/tests/CMakeLists.txt index 3af79b15668d6..f4a3f8f932a58 100644 --- a/presto-native-execution/presto_cpp/main/tests/CMakeLists.txt +++ b/presto-native-execution/presto_cpp/main/tests/CMakeLists.txt @@ -53,6 +53,10 @@ target_link_libraries( GTest::gtest GTest::gtest_main) +if(PRESTO_ENABLE_TPCDS_CONNECTOR) + target_link_libraries(presto_server_test presto_tpcds_connector) +endif() + set_property(TARGET presto_server_test PROPERTY JOB_POOL_LINK presto_link_job_pool) diff --git a/presto-native-execution/presto_cpp/presto_protocol/presto_protocol.cpp b/presto-native-execution/presto_cpp/presto_protocol/presto_protocol.cpp index c15084817a434..107ef068fae41 100644 --- a/presto-native-execution/presto_cpp/presto_protocol/presto_protocol.cpp +++ b/presto-native-execution/presto_cpp/presto_protocol/presto_protocol.cpp @@ -17,5 +17,6 @@ #include "presto_cpp/presto_protocol/connector/hive/presto_protocol_hive.cpp" #include "presto_cpp/presto_protocol/connector/iceberg/presto_protocol_iceberg.cpp" +#include "presto_cpp/presto_protocol/connector/tpcds/presto_protocol_tpcds.cpp" #include "presto_cpp/presto_protocol/connector/tpch/presto_protocol_tpch.cpp" #include "presto_cpp/presto_protocol/core/presto_protocol_core.cpp" diff --git a/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/AbstractTestNativeTpcdsConnectorQueries.java b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/AbstractTestNativeTpcdsConnectorQueries.java new file mode 100644 index 0000000000000..f0b4d554fd5e4 --- /dev/null +++ b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/AbstractTestNativeTpcdsConnectorQueries.java @@ -0,0 +1,83 @@ +/* + * Licensed 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 com.facebook.presto.nativeworker; + +import com.facebook.presto.Session; +import com.facebook.presto.tests.AbstractTestQueryFramework; +import org.testng.annotations.Test; + +public abstract class AbstractTestNativeTpcdsConnectorQueries + extends AbstractTestQueryFramework +{ + @Override + public Session getSession() + { + return Session.builder(super.getSession()).setCatalog("tpcds").setSchema("tiny").build(); + } + + @Test + public void testTpcdsTinyTables() + { + Session session = getSession(); + assertQuery(session, "SELECT * FROM catalog_returns"); + assertQuery(session, "SELECT * FROM catalog_sales"); + assertQuery(session, "SELECT * FROM store_sales"); + assertQuery(session, "SELECT * FROM store_returns"); + assertQuery(session, "SELECT * FROM web_sales"); + assertQuery(session, "SELECT * FROM web_returns"); + assertQuery(session, "SELECT * FROM inventory"); + assertQuery(session, "SELECT * FROM item"); + assertQuery(session, "SELECT * FROM customer_address"); + assertQuery(session, "SELECT * FROM customer_demographics"); +// assertQuery(session, "SELECT * FROM call_center"); // failing because of null values, will check + assertQuery(session, "SELECT * FROM customer"); + assertQuery(session, "SELECT * FROM web_site"); + assertQuery(session, "SELECT * FROM web_page"); + assertQuery(session, "SELECT * FROM promotion"); + assertQuery(session, "SELECT * FROM reason"); + assertQuery(session, "SELECT * FROM store"); + assertQuery(session, "SELECT * FROM income_band"); + assertQuery(session, "SELECT * FROM household_demographics"); + assertQuery(session, "SELECT * FROM warehouse"); + assertQuery(session, "SELECT * FROM catalog_page"); + assertQuery(session, "SELECT * FROM date_dim"); + assertQuery(session, "SELECT * FROM time_dim"); + assertQuery(session, "SELECT * FROM ship_mode"); + } + + @Test + public void testTpcdsBasicQueries() + { + Session session = getSession(); + assertQuery(session, "SELECT cc_call_center_sk, cc_name, cc_manager, cc_mkt_id, cc_mkt_class FROM call_center"); + assertQuery(session, "SELECT ss_store_sk, SUM(ss_net_paid) AS total_sales " + + "FROM store_sales GROUP BY ss_store_sk ORDER BY total_sales DESC LIMIT 10"); + assertQuery(session, "SELECT sr_item_sk, SUM(sr_return_quantity) AS total_returns " + + "FROM store_returns WHERE sr_item_sk = 12345 GROUP BY sr_item_sk"); + assertQuery(session, "SELECT ws_order_number, SUM(ws_net_paid) AS total_paid FROM web_sales " + + "WHERE ws_sold_date_sk BETWEEN 2451180 AND 2451545 GROUP BY ws_order_number"); + assertQuery(session, "SELECT inv_item_sk, inv_quantity_on_hand FROM inventory WHERE inv_quantity_on_hand > 1000 " + + "ORDER BY inv_quantity_on_hand DESC"); + assertQuery(session, "SELECT SUM(ss_net_paid) AS total_revenue FROM store_sales, promotion " + + "WHERE p_promo_sk = 100 GROUP BY p_promo_sk"); + assertQuery(session, "SELECT c.c_customer_id FROM customer c " + + "JOIN customer_demographics cd ON c.c_customer_sk = cd.cd_demo_sk WHERE cd_purchase_estimate > 5000"); + assertQuery(session, "SELECT cd_gender, AVG(cd_purchase_estimate) AS avg_purchase_estimate FROM customer_demographics" + + " GROUP BY cd_gender ORDER BY avg_purchase_estimate DESC"); + + // No row passes the filter. + assertQuery(session, + "SELECT s_store_sk, s_store_id, s_number_employees FROM store WHERE s_number_employees > 1000"); + } +} diff --git a/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/PrestoNativeQueryRunnerUtils.java b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/PrestoNativeQueryRunnerUtils.java index 58431a64f7ca7..e61ecaa5f1b03 100644 --- a/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/PrestoNativeQueryRunnerUtils.java +++ b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/PrestoNativeQueryRunnerUtils.java @@ -86,6 +86,7 @@ public class PrestoNativeQueryRunnerUtils ParquetHiveSerDe.class.getName(), SymlinkTextInputFormat.class.getName(), HiveIgnoreKeyTextOutputFormat.class.getName()); + private PrestoNativeQueryRunnerUtils() {} public static QueryRunner createQueryRunner(boolean addStorageFormatToPath, boolean isCoordinatorSidecarEnabled) @@ -121,7 +122,7 @@ public static QueryRunner createQueryRunner( defaultQueryRunner.close(); - return createNativeQueryRunner(dataDirectory.get().toString(), prestoServerPath.get(), workerCount, cacheMaxSize, true, Optional.empty(), storageFormat, addStorageFormatToPath, false, isCoordinatorSidecarEnabled, false); + return createNativeQueryRunner(dataDirectory.get().toString(), prestoServerPath.get(), workerCount, cacheMaxSize, true, Optional.empty(), storageFormat, addStorageFormatToPath, false, isCoordinatorSidecarEnabled, false, false); } public static QueryRunner createJavaQueryRunner() @@ -310,7 +311,7 @@ public static QueryRunner createNativeIcebergQueryRunner( false, false, OptionalInt.of(workerCount.orElse(4)), - getExternalWorkerLauncher("iceberg", prestoServerPath, cacheMaxSize, remoteFunctionServerUds, false, false), + getExternalWorkerLauncher("iceberg", prestoServerPath, cacheMaxSize, remoteFunctionServerUds, false, false, false), dataDirectory, addStorageFormatToPath); } @@ -326,7 +327,8 @@ public static QueryRunner createNativeQueryRunner( boolean addStorageFormatToPath, Boolean failOnNestedLoopJoin, boolean isCoordinatorSidecarEnabled, - boolean singleNodeExecutionEnabled) + boolean singleNodeExecutionEnabled, + boolean enableTpcdsConnector) throws Exception { // The property "hive.allow-drop-table" needs to be set to true because security is always "legacy" in NativeQueryRunner. @@ -356,7 +358,7 @@ public static QueryRunner createNativeQueryRunner( hiveProperties, workerCount, Optional.of(Paths.get(addStorageFormatToPath ? dataDirectory + "/" + storageFormat : dataDirectory)), - getExternalWorkerLauncher("hive", prestoServerPath, cacheMaxSize, remoteFunctionServerUds, failOnNestedLoopJoin, isCoordinatorSidecarEnabled)); + getExternalWorkerLauncher("hive", prestoServerPath, cacheMaxSize, remoteFunctionServerUds, failOnNestedLoopJoin, isCoordinatorSidecarEnabled, enableTpcdsConnector)); } public static QueryRunner createNativeCteQueryRunner(boolean useThrift, String storageFormat) @@ -399,13 +401,13 @@ public static QueryRunner createNativeCteQueryRunner(boolean useThrift, String s hiveProperties, workerCount, Optional.of(Paths.get(addStorageFormatToPath ? dataDirectory + "/" + storageFormat : dataDirectory)), - getExternalWorkerLauncher("hive", prestoServerPath, cacheMaxSize, Optional.empty(), false, false)); + getExternalWorkerLauncher("hive", prestoServerPath, cacheMaxSize, Optional.empty(), false, false, false)); } public static QueryRunner createNativeQueryRunner(String remoteFunctionServerUds) throws Exception { - return createNativeQueryRunner(false, DEFAULT_STORAGE_FORMAT, Optional.ofNullable(remoteFunctionServerUds), false, false, false); + return createNativeQueryRunner(false, DEFAULT_STORAGE_FORMAT, Optional.ofNullable(remoteFunctionServerUds), false, false, false, false); } public static QueryRunner createNativeQueryRunner(boolean useThrift) @@ -417,13 +419,19 @@ public static QueryRunner createNativeQueryRunner(boolean useThrift) public static QueryRunner createNativeQueryRunner(boolean useThrift, boolean failOnNestedLoopJoin) throws Exception { - return createNativeQueryRunner(useThrift, DEFAULT_STORAGE_FORMAT, Optional.empty(), failOnNestedLoopJoin, false, false); + return createNativeQueryRunner(useThrift, DEFAULT_STORAGE_FORMAT, Optional.empty(), failOnNestedLoopJoin, false, false, false); + } + + public static QueryRunner createNativeQueryRunner(boolean useThrift, boolean failOnNestedLoopJoin, boolean enableTpcdsConnector) + throws Exception + { + return createNativeQueryRunner(useThrift, DEFAULT_STORAGE_FORMAT, Optional.empty(), failOnNestedLoopJoin, false, false, enableTpcdsConnector); } public static QueryRunner createNativeQueryRunner(boolean useThrift, String storageFormat) throws Exception { - return createNativeQueryRunner(useThrift, storageFormat, Optional.empty(), false, false, false); + return createNativeQueryRunner(useThrift, storageFormat, Optional.empty(), false, false, false, false); } public static QueryRunner createNativeQueryRunner( @@ -432,7 +440,8 @@ public static QueryRunner createNativeQueryRunner( Optional remoteFunctionServerUds, Boolean failOnNestedLoopJoin, boolean isCoordinatorSidecarEnabled, - boolean singleNodeExecutionEnabled) + boolean singleNodeExecutionEnabled, + boolean enableTpcdsConnector) throws Exception { int cacheMaxSize = 0; @@ -448,7 +457,8 @@ public static QueryRunner createNativeQueryRunner( true, failOnNestedLoopJoin, isCoordinatorSidecarEnabled, - singleNodeExecutionEnabled); + singleNodeExecutionEnabled, + enableTpcdsConnector); } // Start the remote function server. Return the UDS path used to communicate with it. @@ -475,10 +485,10 @@ public static String startRemoteFunctionServer(String remoteFunctionServerBinary public static NativeQueryRunnerParameters getNativeQueryRunnerParameters() { Path prestoServerPath = Paths.get(getProperty("PRESTO_SERVER") - .orElse("_build/debug/presto_cpp/main/presto_server")) + .orElse("_build/debug/presto_cpp/main/presto_server")) .toAbsolutePath(); Path dataDirectory = Paths.get(getProperty("DATA_DIR") - .orElse("target/velox_data")) + .orElse("target/velox_data")) .toAbsolutePath(); Optional workerCount = getProperty("WORKER_COUNT").map(Integer::parseInt); @@ -495,7 +505,8 @@ public static NativeQueryRunnerParameters getNativeQueryRunnerParameters() return new NativeQueryRunnerParameters(prestoServerPath, dataDirectory, workerCount); } - public static Optional> getExternalWorkerLauncher(String catalogName, String prestoServerPath, int cacheMaxSize, Optional remoteFunctionServerUds, Boolean failOnNestedLoopJoin, boolean isCoordinatorSidecarEnabled) + public static Optional> getExternalWorkerLauncher(String catalogName, String prestoServerPath, int cacheMaxSize, Optional remoteFunctionServerUds, Boolean failOnNestedLoopJoin, boolean isCoordinatorSidecarEnabled, + boolean enableTpcdsConnector) { return Optional.of((workerIndex, discoveryUri) -> { @@ -558,6 +569,12 @@ public static Optional> getExternalWorkerLaunc Files.write(catalogDirectoryPath.resolve("tpchstandard.properties"), format("connector.name=tpch%n").getBytes()); + // Add a tpcds catalog. + if (enableTpcdsConnector) { + Files.write(catalogDirectoryPath.resolve("tpcds.properties"), + format("connector.name=tpcds%n").getBytes()); + } + // Disable stack trace capturing as some queries (using TRY) generate a lot of exceptions. return new ProcessBuilder(prestoServerPath, "--logtostderr=1", "--v=1") .directory(tempDirectoryPath.toFile()) diff --git a/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/TestPrestoNativeSystemQueriesSingleNode.java b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/TestPrestoNativeSystemQueriesSingleNode.java index 10cba774d2ddc..31b9b54f4a80f 100644 --- a/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/TestPrestoNativeSystemQueriesSingleNode.java +++ b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/TestPrestoNativeSystemQueriesSingleNode.java @@ -31,7 +31,8 @@ protected QueryRunner createQueryRunner() Optional.empty(), false, false, - true); + true, + false); } @Override diff --git a/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/TestPrestoNativeTpcdsConnectorQueries.java b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/TestPrestoNativeTpcdsConnectorQueries.java new file mode 100644 index 0000000000000..26b93042df34b --- /dev/null +++ b/presto-native-execution/src/test/java/com/facebook/presto/nativeworker/TestPrestoNativeTpcdsConnectorQueries.java @@ -0,0 +1,35 @@ +/* + * Licensed 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 com.facebook.presto.nativeworker; + +import com.facebook.presto.testing.ExpectedQueryRunner; +import com.facebook.presto.testing.QueryRunner; + +public class TestPrestoNativeTpcdsConnectorQueries + extends AbstractTestNativeTpcdsConnectorQueries +{ + @Override + protected QueryRunner createQueryRunner() + throws Exception + { + return PrestoNativeQueryRunnerUtils.createNativeQueryRunner(false, false, true); + } + + @Override + protected ExpectedQueryRunner createExpectedQueryRunner() + throws Exception + { + return PrestoNativeQueryRunnerUtils.createJavaQueryRunner(); + } +} diff --git a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsSplitManager.java b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsSplitManager.java index 77cd902330026..10ae57007cb6a 100644 --- a/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsSplitManager.java +++ b/presto-tpcds/src/main/java/com/facebook/presto/tpcds/TpcdsSplitManager.java @@ -24,10 +24,13 @@ import com.facebook.presto.spi.connector.ConnectorTransactionHandle; import com.google.common.collect.ImmutableList; +import java.util.HashSet; import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; +import static java.util.Arrays.asList; +import static java.util.Collections.unmodifiableSet; import static java.util.Objects.requireNonNull; public class TpcdsSplitManager @@ -62,12 +65,24 @@ public ConnectorSplitSource getSplits( int totalParts = nodes.size() * splitsPerNode; int partNumber = 0; - // Split the data using split and skew by the number of nodes available. + // For larger tables, split the data using split and skew by the number of nodes available. + // The TPCDS connector in presto native uses dsdgen-c for data generation. For certain smaller tables, + // the data cannot be generated in parallel. For these cases, a single split should be processed by + // only one of the worker nodes. + Set smallTables = unmodifiableSet(new HashSet<>(asList("call_center", "item", "store", "web_page", "web_site"))); ImmutableList.Builder splits = ImmutableList.builder(); - for (Node node : nodes) { - for (int i = 0; i < splitsPerNode; i++) { - splits.add(new TpcdsSplit(tableHandle, partNumber, totalParts, ImmutableList.of(node.getHostAndPort()), noSexism)); - partNumber++; + if (smallTables.contains(tableHandle.getTableName())) { + Node node = nodes.stream() + .findFirst() + .orElse(null); + splits.add(new TpcdsSplit(tableHandle, 0, 1, ImmutableList.of(node.getHostAndPort()), noSexism)); + } + else { + for (Node node : nodes) { + for (int i = 0; i < splitsPerNode; i++) { + splits.add(new TpcdsSplit(tableHandle, partNumber, totalParts, ImmutableList.of(node.getHostAndPort()), noSexism)); + partNumber++; + } } } return new FixedSplitSource(splits.build()); From 6c7ff54ba77c2063a73e9af2e23ab885a6348a80 Mon Sep 17 00:00:00 2001 From: Pratik Joseph Dabre Date: Tue, 21 Jan 2025 14:11:31 -0800 Subject: [PATCH 5/7] Add dnf-common to setup scripts --- presto-native-execution/scripts/setup-centos.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/presto-native-execution/scripts/setup-centos.sh b/presto-native-execution/scripts/setup-centos.sh index 5d237460bb404..73777c6e0c9f2 100755 --- a/presto-native-execution/scripts/setup-centos.sh +++ b/presto-native-execution/scripts/setup-centos.sh @@ -31,6 +31,7 @@ function install_presto_deps_from_package_managers { dnf install -y maven java clang-tools-extra jq perl-XML-XPath # This python version is installed by the Velox setup scripts pip install regex pyyaml chevron black + dnf install -y vim-common } function install_gperf { From fcdb1afd314fde4fd679452e974ba575457b773d Mon Sep 17 00:00:00 2001 From: Pratik Joseph Dabre Date: Tue, 21 Jan 2025 14:13:52 -0800 Subject: [PATCH 6/7] Use new dependency image --- .github/workflows/prestocpp-linux-build-and-unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prestocpp-linux-build-and-unit-test.yml b/.github/workflows/prestocpp-linux-build-and-unit-test.yml index e60e3668e7cbe..943fdec24c712 100644 --- a/.github/workflows/prestocpp-linux-build-and-unit-test.yml +++ b/.github/workflows/prestocpp-linux-build-and-unit-test.yml @@ -16,7 +16,7 @@ jobs: prestocpp-linux-build-for-test: runs-on: ubuntu-22.04 container: - image: prestodb/presto-native-dependency:0.290-20241014120930-e1fc090 + image: ghcr.io/pdabre12/tpcds-connector-test:v1.0 env: CCACHE_DIR: "${{ github.workspace }}/ccache" steps: From 6035ab76ca5993b13df73bc4da1b4cb7363291e4 Mon Sep 17 00:00:00 2001 From: Pratik Joseph Dabre Date: Fri, 24 Jan 2025 15:52:19 -0800 Subject: [PATCH 7/7] Reverted CVE fixes --- .../external/dsdgen/dsdgen-c/date.cpp | 96 +++++++------------ .../external/dsdgen/dsdgen-c/nulls.cpp | 6 +- .../external/dsdgen/dsdgen-c/parallel.cpp | 11 ++- 3 files changed, 40 insertions(+), 73 deletions(-) diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/date.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/date.cpp index ff02dd94e01e6..182f02a5fe8ac 100644 --- a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/date.cpp +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/date.cpp @@ -51,7 +51,9 @@ char* weekday_names[8] = { * TODO: None */ date_t* mk_date(void) { - auto res = (date_t*)malloc(sizeof(struct DATE_T)); + date_t* res; + + res = (date_t*)malloc(sizeof(struct DATE_T)); MALLOC_CHECK(res); res->flags = 0; @@ -106,7 +108,9 @@ int strtotime(char* str) { * TODO: None */ date_t* strtodate(char* str) { - auto res = (date_t*)(malloc(sizeof(struct DATE_T))); + date_t* res; + + res = (date_t*)malloc(sizeof(struct DATE_T)); MALLOC_CHECK(res); if (sscanf(str, "%d-%d-%d", &res->year, &res->month, &res->day) != 3) @@ -139,13 +143,13 @@ int jtodt(date_t* dest, int src) { dest->julian = src; l = src + 68569; - n = static_cast(floor((4 * l) / 146097)); - l = l - static_cast(floor((146097 * n + 3) / 4)); - i = static_cast(floor((4000 * (l + 1) / 1461001))); - l = l - static_cast(floor((1461 * i) / 4) + 31); - j = static_cast(floor((80 * l) / 2447)); - dest->day = l - static_cast(floor((2447 * j) / 80)); - l = static_cast(floor(j / 11)); + n = (int)floor((4 * l) / 146097); + l = l - (int)floor((146097 * n + 3) / 4); + i = (int)floor((4000 * (l + 1) / 1461001)); + l = l - (int)floor((1461 * i) / 4) + 31; + j = (int)floor((80 * l) / 2447); + dest->day = l - (int)floor((2447 * j) / 80); + l = (int)floor(j / 11); dest->month = j + 2 - 12 * l; dest->year = 100 * (n - 49) + i + l; @@ -179,9 +183,8 @@ int dttoj(date_t* dt) { /* * added 1 to get dttoj and jtodt to match */ - res = dt->day + (153 * m - 457) / 5 + 365 * y + - static_cast(floor(y / 4)) - static_cast(floor(y / 100)) + - static_cast(floor(y / 400)) + 1721118 + 1; + res = dt->day + (153 * m - 457) / 5 + 365 * y + (int)floor(y / 4) - + (int)floor(y / 100) + (int)floor(y / 400) + 1721118 + 1; return (res); } @@ -209,10 +212,7 @@ int strtodt(date_t* dest, char* s) { } if (sscanf(s, "%4d-%d-%d", &dest->year, &dest->month, &dest->day) != 3) { - auto result = fprintf( - stderr, "ERROR: Invalid string to date conversion in strtodt\n"); - if (result < 0) - perror("sprintf failed"); + fprintf(stderr, "ERROR: Invalid string to date conversion in strtodt\n"); nRetCode = -1; } @@ -236,7 +236,7 @@ int strtodt(date_t* dest, char* s) { * TODO: 20000110 Need to handle more than Y4MD- */ char* dttostr(date_t* d) { - static char* res = nullptr; + static char* res; static int init = 0; if (!init) { @@ -248,11 +248,7 @@ char* dttostr(date_t* d) { if (d == NULL) return (NULL); - if (strlen(res) == 11) { - auto result = sprintf(res, "%4d-%02d-%02d", d->year, d->month, d->day); - if (result < 0) - perror("sprintf failed"); - } + sprintf(res, "%4d-%02d-%02d", d->year, d->month, d->day); return (res); } @@ -272,9 +268,7 @@ char* dttostr(date_t* d) { * TODO: None */ int date_init(void) { - auto result = printf("date_init is not yet complete\n"); - if (result < 0) - perror("sprintf failed"); + printf("date_init is not yet complete\n"); exit(1); return (0); } @@ -309,84 +303,58 @@ int date_t_op(date_t* dest, int op, date_t* d1, date_t* d2) { jtodt(dest, tJulian); break; case OP_SAME_LY: - if (is_leap(d1->year) && (d1->month == 2) && (d1->day == 29)) { - auto result = sprintf(tString, "%d-02-28", d1->year - 1); - if (result < 0) - perror("sprintf failed"); - } else { - auto result = - sprintf(tString, "%4d-%02d-%02d", d1->year - 1, d1->month, d1->day); - if (result < 0) - perror("sprintf failed"); - } + if (is_leap(d1->year) && (d1->month == 2) && (d1->day == 29)) + sprintf(tString, "%d-02-28", d1->year - 1); + else + sprintf(tString, "%4d-%02d-%02d", d1->year - 1, d1->month, d1->day); strtodt(dest, tString); break; case OP_SAME_LQ: switch (d1->month) { case 1: case 2: - case 3: { - auto result = sprintf(tString, "%4d-%s", d1->year, qtr_start[1]); - if (result < 0) - perror("sprintf failed"); + case 3: + sprintf(tString, "%4d-%s", d1->year, qtr_start[1]); strtodt(&tDate, tString); tJulian = d1->julian - tDate.julian; sprintf(tString, "%4d-%s", d1->year - 1, qtr_start[4]); - if (result < 0) - perror("sprintf failed"); strtodt(&tDate, tString); tJulian += tDate.julian; jtodt(dest, tJulian); break; - } case 4: case 5: - case 6: { - auto result = sprintf(tString, "%4d-%s", d1->year, qtr_start[2]); - if (result < 0) - perror("sprintf failed"); + case 6: + sprintf(tString, "%4d-%s", d1->year, qtr_start[2]); strtodt(&tDate, tString); tJulian = d1->julian - tDate.julian; sprintf(tString, "%4d-%s", d1->year, qtr_start[1]); - if (result < 0) - perror("sprintf failed"); strtodt(&tDate, tString); tJulian += tDate.julian; jtodt(dest, tJulian); break; - } case 7: case 8: - case 9: { - auto result = sprintf(tString, "%4d-%s", d1->year, qtr_start[3]); - if (result < 0) - perror("sprintf failed"); + case 9: + sprintf(tString, "%4d-%s", d1->year, qtr_start[3]); strtodt(&tDate, tString); tJulian = d1->julian - tDate.julian; sprintf(tString, "%4d-%s", d1->year, qtr_start[2]); - if (result < 0) - perror("sprintf failed"); strtodt(&tDate, tString); tJulian += tDate.julian; jtodt(dest, tJulian); break; - } case 10: case 11: - case 12: { - auto result = sprintf(tString, "%4d-%s", d1->year, qtr_start[4]); - if (result < 0) - perror("sprintf failed"); + case 12: + sprintf(tString, "%4d-%s", d1->year, qtr_start[4]); strtodt(&tDate, tString); tJulian = d1->julian - tDate.julian; sprintf(tString, "%4d-%s", d1->year, qtr_start[3]); - if (result < 0) - perror("sprintf failed"); strtodt(&tDate, tString); tJulian += tDate.julian; jtodt(dest, tJulian); break; - } } break; } @@ -607,4 +575,4 @@ main() { } return (0); } -#endif /* TEST */ +#endif /* TEST */ \ No newline at end of file diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/nulls.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/nulls.cpp index e1390de0610b8..e5cab55be7147 100644 --- a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/nulls.cpp +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/nulls.cpp @@ -37,9 +37,7 @@ int nullCheck(int nColumn, DSDGenContext& dsdGenContext) { nLastTable = getTableFromColumn(nColumn, dsdGenContext); pTdef = getSimpleTdefsByNumber(nLastTable, dsdGenContext); - kBitMask = - (static_cast(kBitMask) - << static_cast(nColumn - pTdef->nFirstColumn)); + kBitMask <<= nColumn - pTdef->nFirstColumn; return ((pTdef->kNullBitMap & kBitMask) != 0); } @@ -83,4 +81,4 @@ void nullSet(ds_key_t* pDest, int nStream, DSDGenContext& dsdGenContext) { } return; -} +} \ No newline at end of file diff --git a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/parallel.cpp b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/parallel.cpp index f51df2e40f8f4..da16606ee2bfe 100644 --- a/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/parallel.cpp +++ b/presto-native-execution/presto_cpp/external/dsdgen/dsdgen-c/parallel.cpp @@ -99,7 +99,7 @@ int split_work( * TODO: None */ int checkSeeds(tdef* pTdef, DSDGenContext& dsdGenContext) { - int i, nReturnCode = 0; + int i, res, nReturnCode = 0; static int bSetSeeds = 0; if (!dsdGenContext.checkSeeds_init) { @@ -108,16 +108,17 @@ int checkSeeds(tdef* pTdef, DSDGenContext& dsdGenContext) { } for (i = pTdef->nFirstColumn; i <= pTdef->nLastColumn; i++) { + while (dsdGenContext.Streams[i].nUsed < + dsdGenContext.Streams[i].nUsedPerRow) + genrand_integer(&res, DIST_UNIFORM, 1, 100, 0, i, dsdGenContext); if (bSetSeeds) { if (dsdGenContext.Streams[i].nUsed > dsdGenContext.Streams[i].nUsedPerRow) { - auto result = fprintf( + fprintf( stderr, "Seed overrun on column %d. Used: %d\n", i, dsdGenContext.Streams[i].nUsed); - if (result < 0) - perror("sprintf failed"); dsdGenContext.Streams[i].nUsedPerRow = dsdGenContext.Streams[i].nUsed; nReturnCode = 1; } @@ -194,4 +195,4 @@ int row_skip(int tbl, ds_key_t count, DSDGenContext& dsdGenContext) { } return (0); -} +} \ No newline at end of file

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 z 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�-;8BMpwg>eFOAe{#c3QWq)xEbVfJE1utXhtRzmY=jhKc(t526yv~ zVHHW)Rq-rU0=c37t*7xz692EQ(@rz!_}EDL}(vzxR$t@VOj!=yYa;E64-1j7UJW;Cxz&~yI|@ej^{Xdp2KuUCNbEB$H}tw=Ha=doG=p8r5>_-&Cm7(vh%y1r#4R zxd@rJi@1J^xseOi*U{GK$o1--`2I9=RJJVt}OG*l15)}?ngvdMG1xv05ZI?45!c?(>nmtY=o zJJ@t(pTg3CsNi-67R|Y4qikr93fO?(ae{P|=T$j25Y9*yu(=7$GLsr0*eJ4m`5A$` zQ6Vx*b-Kf;53q8qX^5@P$qq}%Lzh|*wgd$VRMNQ0LSZvc~I0~EwtnFpUd37bek z1l)9NxLY~7an*_$ObxqRb5djWA-*bCZoI^LW16C#edy8q@vsQh%3&WPk8rNGDcY`x z69c!oINZ?fQXN0KGb6bqoPx&cSysJGeb3>h+T>X_G=7KBYqB17ZKBa>z<+XPaRw{& z!J%ywS94&LXE8*;_IUYC;%y4iZS9|VA3iKLPmx)zwe1!W1hGX`C8-a9U=1a$QTx>p zNB`wA57_<@S>>H;jm89`kfNE{t6sdmRok!XYA2Y7k}r#XNg7rIq|bKFy3=*rNfU!u zPStf>3^v5e?S9xE6Qq)aRAgXgrL;l>U1>-x0dkc!M$_@Y!f*(-&@p_lPQhOp5zHoQ zLyKLYfwp$+TWceF1m*&-q}@(+_Z8C9K+be1l!Xtkjz>lN`6Vh5AdHcV9rE`&PQtZQ z7M^>Gs@{!Y02L&o{CrWN*VxDaMuK|IO`@Xi%%a}HxlTD4ds9)cII8zPk7>?J52^$k zFNl|Bt}NbR>F8~x*vAZGsQ^p63mT%UTHAyXRramN$5pkAPRg{B_xu(s#-5zu{*G=x z?5lAth|U2kd$aMltk1uIu)n^qS=z1zS`&#sRoztNR3=FSgd`QI7quD$kL7}fNGH_V z*DhI;>xp`XTjXi3F|{7tflYM)Qi#Zi^VrK{^Vxd238QB#F)&2QCTt8G0R}(_Ws4Kt z>ak^r?P!bX5L_s~Z_GR=qb5|k*Bf&vkEpU5GsLDH?FyCa{RNvz zLfLw=VJ|850`@vbRln(P^tiMNdQ-hm_wlv{hX0I-dWE=VBg?S;1)7S~d%`s9TwRZr zQmK2Y6D$6;6Ln1uWVh#35R?sXnsX2p8S8D+%-aA|(BI%13__@8-+JXp6$^2X2|}Ir z29-@;dSXssnYB>E$$nl{9&$)1N~R2{Bwc%AJh{K&2^T@FvP!+H!F0zbZcTy3n z!n;>1*=Vx_6vn&9ENjOmmy5LxHd#0$`ivUm@}uBLKPyk#_t>^M9*xB{ig{A@c8Yr2 zYKs623-!u$$y>5hgO_#Dz;wJlcrKOEfXQLXH0Uz#h7%EN6lZR#XWX9h2?&VWcc&-u z7J_{xR%LWSP#23@ z{L$tcC9@VJNyWCPX;ah~Y!uEp{xqWyH|vC^XEH=m@@5)L{BN*Au*5lvAu6Y(Et6<6 zWZVLfjRT@*1vHI3{`M-7`8D&X!bkx#<|BZrD&KK-;L3%7+*PlAx^hh%&yp@q#bKz= z%w9gzgbhWHotm$#R9z^RDNyHlI5_v20|REFp5WBcr}1XGy((L{U`&PBvSD1dN*J2O zBRmm@Nwy0tzLOxkC^&*+bcKe2C5ZP?_8Kplm0NI|)#gE&5qA_avWJY?ynA88{!xsK ztJDod=uL$ajq=DNbAbJ&SE+B#pJ|1A|9({(fU*g9CrCvbvO*1PeI*_kN7(AsQx!bQ0B4C8Tk&cZF z02T~Tx~MF`8{wExO;|KDA}f5G0A^Ju)rFqH;Hu(7bw>cWSze#gdCXLM)YGP(eRYK$o1v-1{k1gO@3l?b%V(s3+E zcU&4&=?dcw6Job<-JJ$#u|z`r>gj}Gqol+YVAqDRsl+);mAa#qs(}W5=Sb{<5g|G* zH@Sz;;N$XR=qH)EPRlSRHy33kVLmi4h0S=MKzbq%$jC*iSl^3r1ikF zz_Y4ImHWY9E5-qF6Z*A^Qq{|d*Mmc!e`ljgH70-`+md{rWq}WY(@ePIxlq~!&f&U& z{35?$6n~;jmba!m+k2C%bctre7m#>-eFA+kKGPq%4|GP2I58EGoV~I!C(z2T4Yolw zRXD%HJ?g2uXL;zBwMi`jX;E>S-J!Uybe*}zl2?DXS2ev{AeSB5jgi1I(QgL(j9*D zL(w!SZ__;Blo0_tvUH9Kg586HsZfxi#7}i)yw{#ouqf&rZf=droi3(;MTlF1;cMmN z`3vPqnd8ZEH8a#LS6M;Q71j#~!ht8vb7%w}Eiq%K`!MTG^BbH;%`t8NcaT{neI3}_ zgC`R70hyXe-v@oT0BkhZf#xtjSVoqFqNE)HZ#H|XcGbK{?w9S<^RJ?=kfqn9bWwwY z8lgYTI4=JfRVc??h*yB@62i%FiRxgzB0^!4I(%8z+;p356*f+W1d>PubCPvqkCy>c z!;eJ9)f*j~NCAO@s@bGqJV61m2e80vLptz^NACbdDhTl0UW517%A7X?i>ZuIjfFKp z=r=&YqCke)zg>p87W#JZtY9ftLw<32OXe@Dbbltq7c7VSVn20``OBN>BMd4(l(f@e zgDlrU@1q4_H-P6HJB_aW27WJaQ3$!Xm?*M=-9Zd`8qK0z#pjA;}~FyRk#nnuQuC`L8CdwK!8b}nZC{?0D0%4f=UBSeW9S;Jp2r7 zZQY&ectk+MlekB=VbbUa9B$0Vd734=6$gKtYEMF=!-S?Z-Dk0i^`2xdl;2xj-=H0$ zds?Vul87=hcCuD6Z4goR2zx~&}JCZdVF&*&8U0i=-6l}U9fR2T~E|}ax}d% zZ!3DB50y8r&Qu-O?S!{el+d!T)}LyZvMhXfd+kNtqye&qXe%92R78+7T6(FQ)xD&M zY&(^Q`%2dDkgeJ{HeM?y)wWZHXCZz7cqeESuM6VB&j>?Fp*Z-$MHm=k zgyuyOIvdq|MW<>p$N1POIB>VXL=Ct*S_-WiLVvV z3S*d6b?n~JBX(3ioLbN9tuzlD|3}JYSi;bT?~`x_U+d>s9}hugRAXIyP}_gU7^%5H z3dmf*W_FeIFX$P%{Ysx`5FP;^zgUkdZ-z&h!?5+OK2P4r53Sy`{KwbHd~%5e^# zrm!uVox=;~W8qQAAif|6k4WJp#q23&Vgmfm-oS1Gdyc-;UG|-d4vsF`5++XZD-d!% z=b$dBN&}Cff?^A8-Xma2J&;QqPjJ;STvPOBRQ?V*5LB^$R1LhlD%i+eqNGqGKp?^9h6O;$i zg1SCIbLMoimfgjcv`~iP0P85k^q`Va(jD|AG2#pf5CyDooO!7mD)nbw%HpvbCGFeLo)pU^ zT-@9k7oG&ZL7-qW%|Y@wAk;qnp{8#poDtJ8&o&uy)<0gu8!HC z3=jj`X+23NDyoY}HKuE1qPouuP6uqDnst(CmHKpihaU)tqU$yRb;~{&ev(t7EHv9m zW1jTynqRUjrbqpGd(2PixgB{iB=dDx~ZCasMun0hLg)?P%? z=1EQWKxGYhyHg4l`qB<^VI{}I;#bE#pydi@%8#$L{KC7~bO1GGfA_vk0ERTCxfe5d zx!Ar`dpbe6WZ0y~n&J+!HkX2p?jXiZzcS^lE`bE3%1OHrqdlV$27?JrjhA6A9>u;} zZPue_RHLfO6Jc+~J9b5?!tH^YhTA(!FVdC0%4nqFHBz;yFiy#l8jcK-BsWWjV3*pV zQW{kA5SRrw$I@Un(tNT|%q^jmccyv6W9l2^DvuuO=q|zln%PCIc zMREa8Vw$fUVhV;d-l9o-VntHwc3vSi-Gfr zsldakh)z|*nu1-1tF$8JMVbZx%Jxr$6CquP{i?5~h)xPXhR%b8epY&J{ir8=xx==R z(rTyFZkDX_^wJWE*(G&=WxWtRdgW>MYx7t}wKahn5X^4l zh~!tc0Yw$)!T>Wsz~TpogFt4nda1a$@@#@o2$I9sF#TI*X|g>}(i2eW^d24(IF|rc zq%bQvuT9}z_RKnNo_q0M5kY6w{e$q7#b{0hy~arh-a9}MO6tzIS{z~OOq*|R@8aJr z?YlMM096@BO*&=A3~8u zVh7}e6MtDAefR1hD8xl*as{D!@6ND#vGF)GDxH^diEvfD?q{VxO(B{pqwBikfIO&t z&ov!4j1kT{)xv5kD=8Rn&()^QFGh?>>AuhTv1vNaaoUGWc;Dmc;fp9uQIA2qn6wNx z6z(mCmIJLMWyVI$hV#o+8BM5lCMuT$pc@%7>}72RfE8SQdbmy^pvZ01DoX3()B0$` zt226Ro+m6Daq~n59eM;4;{n(OGh*!EbGUC$KbFNWQRQe@~o`Oa2!RjZCAN8W=(S(-EOhaK6c-;uB0+cGU$WzX6Okc zaMVsz7d|-HD}^)28p%OQay#~Dhck>!0UQL3gp(>j$8jWfSHs2%9NE|e)+LkgrpSh+ zX_N%Zw*|Rv?+$S%_*vFPrBy#ylz66M;%E;U9#F0|v)F5x-ndr#K_6e%q+^%!bZqN8Ypg>nP*CQEe_7&s4 zSEpJ1JH49v5-|~J-f_pML3UKI1P5-DumBv&jNx_yRf%3Yg*|0dX8uu7mV6~YqY&(> znMq+k6VzVuDQcpys#6kdYPx5R7Nxb!U{-QSKOz*&I4F*g31;ARj`vlvs`KK6HX?7` zvZH>{a-C1ZS)%@$Lngw))7zr{Cd+-$@#?jgRSu1rA;YLzK6Km0Ub!M7*m$+QlW*7_ zuHe|_Z4a!Bu;CS%`6UfeQ%HoDJgxd&!;=VG1&x( zy>s+*7Uk`mr`Rv><#eTY1sgQZhcyw!knSo`pIs48BD)CC{;Bi2xxDcxdC~-<2%&6U zjZ}v%Q+oHUsrl*zC{^BzR(cmDAma#dQzfl}4nR^CPG1fKf{_vtlUcRV%li~bhVJcDgbOLYM9%VfJaqL)<#7z{%Wz{IBNvFl%36=8zn?aMu@r@ zb?!<^IaEz@)SQow58DR{6WRPpI7&PdjI!wuZTltQJX+OWaSg*>fqAg<6oO1jcS`_0 zcv8}erK>;4h(`C2C)?Z1yk)ssZoQm0uIQ*D!(gXqv?Zzwaff{tT0*7;B`t;7?Pu61 z#DiziZ%4~j5&!TrtQkMk4IWt;+SlPxAv;GVD%R{?7Cb5-MGc`5SY|KL4)0UpwgB%j za1>WbWqt_S3${WTQY*STo^M~t2GaYDI5@=Z=TRtm{Z9X?T^JoV8Ln2&m#^5zQnA59gDB;ig zG5BrpC+B-%_y)HwUxSThJ>i%6Mz!TV=2Jn7N1B_u0elkO;EQ>K^P;wQ-1|DKWT91Riz0{7-N75oigeaf$w?jNaeH24sSOAlFyd0^?jYL^ zHVHC5fS^m`)w-Vslv{;X9D!{Bcghreg8`ppzpGkiFRFyO*qm-+*FH`X1cO3W4Rfrn z{qWDxsCxM|n|Mh@Cwrg~#UPbzCo(wIpjjn=arWA+@MWq@bWns5L){8YMG3vWdy^{& zQMZvz-oyFCzqv5Jl=s{3031(*bc_d;%99?B7XvN^X)ke496vvg@LsE37C@KivKp!p z_)GRxvsq^9)7`2PNzJc;tI;l4(92mvIkrw?Urlu8j}r~0VjBgZnO%d5Li=K2%;keo z@un*9dUpgS#R2Zbr`4B@$D>XIQ@ukU%stv0&)U_Dc>Rq;!+=Ms_R_f71k99y z5O~+~&+HB=f*0ym)fhQ0=0yn$U#dHo!@F3svPv#}<`>OjAjS5!x^Ni!GFM9&Uzf&2 zo_!0Kc@~G;9EW@+nTb%B zsEVi>7ZJ0jYUO|}I@>DIQA}f}JopkF_EdKUFbg*uO?S|E1c+=QfER;r zT(xysF2H-HY~^Ihxx}@AIunTRl{&n>Q^k7nGAv%PjeeI?iig>4T&g>o=W<%_F_JLC zaRv=vo338_+D$kq1xSWDg>7RsKA}@M8scL$| zZvYTUkPt(x&vP*E6%1|{;^~9Dw&w+?g67vjcgqSIl*cW!Y=xDyAEs7+9FztU(lpv~ z_kr(#CdV6;lynPd`}zRCiVs<6$|&r6ZBfSw*kPk7w8~#(g;>6(exOFl%B=`;fLtl5 zL#%dfNRxa4x{#`iqIvBLsq4biiUSbruN18jh}F=9KYSj9|M%*cu|UeUb_qVyeKJtqbxI_u3Jq5P62{Oi~IVm;LGrJs7@Mn zxg|Q=FuO822I3u>=x#fE6!~SbL^F3J?<@*BiSJfuNuvx zSO7$fZqXCf91|Z4Xe<(F7x(5;$lj}=nui-;`m%y+h{{ck2ic^DCt!Fn6#oeX?sBki)O#=&>IFx<$B+X%Hh zW{oSYt|SiH7Dt!Oxi~HN*90YshlEpoVMeN?E*n-?wzUdO>oma^htqgWLY065Rkh~>zXXModA4pTv z>d6j0-T^5_0zF%1-td5^8x<%AnpTdnA(!b&QRK*BHbz^p`@n9l`o|ss$P^E8qjY@O zC=Uprx&*O3Ux*)pB|E2ta<`%OZO^J&k~n2{d93n>#X!V%g)Iyw$jnX^3H-$wV%1)r zarHv?#>NpMho`EVId_1(DS0dONYZrHJtn?t(M_rQhBCWYL!HJufXr@HO``3)5=oKZ zsa&MoiZYh&jXp<0l1f3a#pImar`fmEN5mM?>wCCQY^5<@`5PPDhbxjGPo`AVS+<}h z_?;F9G+MSS{)pmULZ5nihCdzcL;`_Sfl%GgLKV$C5BXJSZZCGk0Kz!2AS5QC?9}S{Dw?b77u^eGS{jxSfI?kmKs*Y zwwxPn6`^i$DrgNwKfX*afHk^oRB^+iu(mtxwn0D_f{<{LIJaQ|D;_-Fo8P-L(h?91K+M4VHSX0D$z}`;GD|KkrLIGZi!5J%~iN$%t1B0=Z z7(J_P!ftXVDEySF>6YwHgy0pOi(1X+%FeJfTy4DmRD$}q<=AEs&G+cHi6pM5R!vU+Xu+xAyn=s(;Ez9%m zF<5(FCV{iUf^!4gCYRY{jUG-)lU7js)9tE#-|Y#-y66jmz&rTl-BDT25z2#n&E%lv zkS}UhFq{^)8#omuLD_|!uo6@R(YwrY-DP69RdHboqpzAW!>}rT2Uj1fZw(2*QCXAi zkMO>Py!MoWt-`z}L%^=MXSB?N<>hor55p4Yfb!POcEQ&{O>#Ep=A)HKmdC(g=q&{M z)NoE1TDJ-Xln3jGM%^8ac9sByE531QPuK=^e{6V#zMPID8f-&|uQ3$pitb02Z7_a1 zA_09JqS3Ez!$`CMMpsS9-hJ{ffjmE+kCFD5-rASa@-NT?1ffaa+Eu8YU7Tt<% zH1J^17E;x!eyMvtgYYxw0sE8o^1rDNg{|N~4>PR@zpmS`=3bzKG9qC7+3BhxIA~by)8n z6a5pSErw!ZlOiAy6MPU$Wr(*WKo>}P9r0;Ig_ zAU*7^s@eIOepImJpmT8l*t|{rm~P|T+SKnUOX(n%plF1Er|Dk1OrGeT ze|fvkMYT>!Gcbj54>8U2a&uNgo5<{H4Bu|;WZ0pNU|{KTlvjt~r%Vj$R@ZnM+>M?9 z$KR~O%BXymCLwQ4bA49l#?hkvUYox@+L#wZ9|jC4FN*P?qPF69c2_$6j{v#3aTN#T!<6kTLcD8CNDfMuq`lnaM)IXT2=nA--AQ!8A!Ud z&iLM}_S~nWGMn@%-a`vE8|wvA0Yz1gwliOd7vMOq&-;}wxzNC+rl;2)ZHhi&xB?0} zRSUnRDeR}EiSV~_Ca0-Fq`JcxH}^!8H+dKjR)ynI6)?_Aox2FqtRhv(OG(KEGe9Os zQ1y(8ygI5eTmeUr!n2@X!?oOp@ zqwMl5^x3&7d9M_@Z2?&KK2Sg>#;0J~LGfV%k^-u$e!T?%qg}YwMbI6)OL9|MRY}Hi zx!g5Ku0VF;7G`pn$(B7z1L#Y>=^CBloyrTcga3qoh{>s14iQ&lKGBt|~bXisLeJH_xbmC<41&Gf0ro~g#y&oPe&`GU+Nj$PJ5c9+-z z%7qADh$iNFN%lABVXzYtKwKJJm4>->(_2iP9WB`0IhSANxqw;>czBr%WM<;9WVDb1 zv*8*o)4ke9ahV1VR9DU0Me_q}B=hFR!{T(AdOkc6esOktw;G`n91%QJ^sn<3of;74 zMO|p($HST^MDDa_EAbcwh0M=Yv0Koaj30)ZqDV!Bt%4JF)yXO2E80Saux)5;OeFoY)Fqm`+I!Tt z#0+LuFGWUg9T##I7({tAdv$MdGbsZD@GYGN&Ego^>(WHU*hjnUikg+GPcC6qckcFu zjEf=xYVJx+Zjfwt1r>d9xKE)VGU zxX#4q=&09}P|BS_9>PPF%h%BTr3#7KsvHT$0xiC%TUU@!mWE$VqYbyCmuzs)(j*O> zI#GC43>Rd9M+#^{c{)*UUq4Ac1mDVCEaWmGcxY^(Z@&y5L(+k>IOp7}01K1rU}LDp z*Wi-vp54RClmjxslwb$SM2M)mR1k?Ha%FgVoJ~P1-qjdgNtKZq$K!(NFmWXm3k*(O z1*|lzpj*pp(nKl+sT)*!WKN-kW)iH_w$L3Xo)~PzqUPgCT?N$hNWtF6v zlybV8Buy%w3on-2O4*0Kf8PBn)rMiJPwQrcj>+Q@u`D6J!L@ijp zza4R|C8ue?(G9};Y?-vt4JrXrK4xCl=5|fan|jJo=2PC8QGBZ(lp#?vaze{&@p^*k z#`qD8pP;^Oc?*yr8{A<3;NGsHrQ`4(-X$W!HVc_uTVnRF>4y$+5we2|a(ES^T6O&d z+2LnTKSvz0xE=cFwPq%&BwWc=^u#H1ZZ5~iCh|KlkuASkfn$?{ZS5FE|PR?_usyg+)jruv%ugh2V zHZTc5;B|9ma%3MVKnR-fNppBgRb}n_+Qn|p-D1KgZxcKKfL9Xu_OuaAg}QWjO_yHc zUeUbuMm&`lBh;HtE)DaF8rU-~Jr-W6rE&4Lni@exGD()H(oX~M_j4X5hQSO;N*D%S z+Hivz!jsVl5U5fsUIF(lg(Zv2wldC0mLcz2dxdBlK^JnPv*Xi*KZ#(`IWO|W!rOL} zbrG^uInm}}4aXc6c{wI$W>3k4!BcX};YhLCkXpQJV0zdrEw)2+JqawK|<-K@U<4JE1Et3`_NFgPDZOs`>