/** * Check whether we can INSERT values that we have reserved for our NULL * indicators The DBMS should throw an error to prevent you from doing that */ TEST_F(TypeSQLTests, TypeLimitSQLTest) { const std::vector<type::TypeId> typeLimitSQLTestTypes = { type::TypeId::BOOLEAN, type::TypeId::TINYINT, type::TypeId::SMALLINT, type::TypeId::INTEGER, type::TypeId::TIMESTAMP, // FIXME type::TypeId::BIGINT, // FIXME type::TypeId::DECIMAL, // FIXME type::TypeId::DATE }; for (auto col_type : typeLimitSQLTestTypes) { // CREATE TABLE that contains a column for each type std::string table_name = "tbl" + TypeIdToString(col_type); std::string sql = StringUtil::Format( "CREATE TABLE %s(id INT PRIMARY KEY, b %s);", table_name.c_str(), TypeIdToString(col_type).c_str()); LOG_TRACE("SQL: %s", sql.c_str()); TestingSQLUtil::ExecuteSQLQuery(sql); // Then try to insert the min value std::ostringstream os; os << "INSERT INTO " << table_name << " VALUES (1, "; switch (col_type) { case type::TypeId::BOOLEAN: os << (int32_t)type::PELOTON_BOOLEAN_NULL; break; case type::TypeId::TINYINT: os << (int32_t)type::PELOTON_INT8_NULL; break; case type::TypeId::SMALLINT: os << type::PELOTON_INT16_NULL; break; case type::TypeId::INTEGER: os << type::PELOTON_INT32_NULL; break; case type::TypeId::BIGINT: os << type::PELOTON_INT64_NULL; break; case type::TypeId::DECIMAL: os << type::PELOTON_DECIMAL_NULL; break; case type::TypeId::TIMESTAMP: os << type::PELOTON_TIMESTAMP_NULL; break; case type::TypeId::DATE: os << type::PELOTON_DATE_NULL; break; default: { // Nothing to do! } } // SWITCH os << ");"; // This should throw an error because the query // is trying to insert a value that is not in a valid range for the type auto result = TestingSQLUtil::ExecuteSQLQuery(os.str()); LOG_TRACE("%s => %s", TypeIdToString(col_type).c_str(), os.str().c_str()); EXPECT_EQ(ResultType::FAILURE, result); } }
std::shared_ptr<storage::Tuple> TypeUtilTestsHelper(catalog::Schema* schema, int tuple_id) { // Populate tuple auto pool = TestingHarness::GetInstance().GetTestingPool(); std::shared_ptr<storage::Tuple> tuple(new storage::Tuple(schema, true)); const int num_cols = (int)schema->GetColumnCount(); for (int i = 0; i < num_cols; i++) { int val = (10 * i) + tuple_id; auto col_type = schema->GetColumn(i).GetType(); switch (col_type) { case type::Type::BOOLEAN: { bool boolVal = (tuple_id == 0); tuple->SetValue(i, type::ValueFactory::GetBooleanValue(boolVal), pool); break; } case type::Type::TINYINT: { tuple->SetValue(i, type::ValueFactory::GetTinyIntValue(val), pool); break; } case type::Type::SMALLINT: { tuple->SetValue(i, type::ValueFactory::GetSmallIntValue(val), pool); break; } case type::Type::INTEGER: { tuple->SetValue(i, type::ValueFactory::GetIntegerValue(val), pool); break; } case type::Type::BIGINT: { tuple->SetValue(i, type::ValueFactory::GetBigIntValue(val), pool); break; } case type::Type::DECIMAL: { tuple->SetValue( i, type::ValueFactory::GetDoubleValue(static_cast<double>(val)), pool); break; } case type::Type::TIMESTAMP: { tuple->SetValue(i, type::ValueFactory::GetTimestampValue( static_cast<uint64_t>(val)), pool); break; } case type::Type::VARCHAR: { std::ostringstream os; os << "TupleID=" << tuple_id << "::"; for (int j = 0; j < 10; j++) { os << j; } tuple->SetValue(i, type::ValueFactory::GetVarcharValue(os.str()), pool); break; } default: throw peloton::Exception(StringUtil::Format( "Unexpected type %s", TypeIdToString(col_type).c_str())); } } return (tuple); }
FieldInfo TrafficCop::GetColumnFieldForValueType( std::string column_name, type::Type::TypeId column_type) { PostgresValueType field_type; size_t field_size; switch (column_type) { case type::Type::INTEGER: { field_type = PostgresValueType::INTEGER; field_size = 4; break; } case type::Type::DECIMAL: { field_type = PostgresValueType::DOUBLE; field_size = 8; break; } case type::Type::VARCHAR: case type::Type::VARBINARY: { field_type = PostgresValueType::TEXT; field_size = 255; break; } case type::Type::TIMESTAMP: { field_type = PostgresValueType::TIMESTAMPS; field_size = 64; break; } default: { // Type not Identified LOG_ERROR("Unrecognized field type '%s' [%d] for field '%s'", TypeIdToString(column_type).c_str(), column_type, column_name.c_str()); field_type = PostgresValueType::TEXT; field_size = 255; break; } } // HACK: Convert the type into a oid_t // This ugly and I don't like it one bit... return std::make_tuple(column_name, static_cast<oid_t>(field_type), field_size); }
/** * @return true on success, false otherwise. */ bool CopyExecutor::DExecute() { // skip if we're done if (done) { return false; } while (children_[0]->Execute() == true) { // Get input a tile std::unique_ptr<LogicalTile> logical_tile(children_[0]->GetOutput()); LOG_DEBUG("Looping over the output tile.."); // Get physical schema of the tile std::unique_ptr<catalog::Schema> output_schema( logical_tile->GetPhysicalSchema()); // vectors for prepared statement parameters int num_params = 0; std::vector<std::pair<type::TypeId, std::string>> bind_parameters; std::vector<type::Value> param_values; std::vector<int16_t> formats; std::vector<int32_t> types; // Construct result format as varchar auto col_count = output_schema->GetColumnCount(); std::vector<std::vector<std::string>> answer_tuples; std::vector<int> result_format(col_count, 0); answer_tuples = logical_tile->GetAllValuesAsStrings(result_format, true); // Loop over the returned results for (auto &tuple : answer_tuples) { // Loop over the columns for (unsigned int col_index = 0; col_index < col_count; col_index++) { auto val = tuple[col_index]; auto origin_col_id = logical_tile->GetColumnInfo(col_index).origin_column_id; int len = val.length(); if (origin_col_id == num_param_col_id) { // num_param column num_params = std::stoi(val); Copy(val.c_str(), val.length(), false); } else if (origin_col_id == param_type_col_id) { // param_types column PELOTON_ASSERT(output_schema->GetColumn(col_index).GetType() == type::TypeId::VARBINARY); network::InputPacket packet(len, val); // Read param types types.resize(num_params); //TODO: Instead of passing packet to executor, some data structure more generic is need network::PostgresProtocolHandler::ReadParamType(&packet, num_params, types); // Write all the types to output file for (int i = 0; i < num_params; i++) { std::string type_str = std::to_string(types[i]); Copy(type_str.c_str(), type_str.length(), false); } } else if (origin_col_id == param_format_col_id) { // param_formats column PELOTON_ASSERT(output_schema->GetColumn(col_index).GetType() == type::TypeId::VARBINARY); network::InputPacket packet(len, val); // Read param formats formats.resize(num_params); //TODO: Instead of passing packet to executor, some data structure more generic is need network::PostgresProtocolHandler::ReadParamFormat(&packet, num_params, formats); } else if (origin_col_id == param_val_col_id) { // param_values column PELOTON_ASSERT(output_schema->GetColumn(col_index).GetType() == type::TypeId::VARBINARY); network::InputPacket packet(len, val); bind_parameters.resize(num_params); param_values.resize(num_params); //TODO: Instead of passing packet to executor, some data structure more generic is need network::PostgresProtocolHandler::ReadParamValue(&packet, num_params, types, bind_parameters, param_values, formats); // Write all the values to output file for (int i = 0; i < num_params; i++) { auto param_value = param_values[i]; LOG_TRACE("param_value.GetTypeId(): %s", TypeIdToString(param_value.GetTypeId()).c_str()); // Avoid extra copy for varlen types if (param_value.GetTypeId() == type::TypeId::VARBINARY) { const char *data = param_value.GetData(); Copy(data, param_value.GetLength(), false); } else if (param_value.GetTypeId() == type::TypeId::VARCHAR) { const char *data = param_value.GetData(); // Don't write the NULL character for varchar Copy(data, param_value.GetLength() - 1, false); } else { // Convert integer / double types to string before copying auto param_str = param_value.ToString(); Copy(param_str.c_str(), param_str.length(), false); } } } else { // For other columns, just copy the content to local buffer bool end_of_line = col_index == col_count - 1; Copy(val.c_str(), val.length(), end_of_line); } } } LOG_DEBUG("Done writing to csv file for this tile"); } LOG_INFO("Done copying all logical tiles"); FlushBuffer(); FFlushFsync(); // Sync and close fclose(file_handle_.file); done = true; return true; }