use apache_avro::{
AvroResult, Reader, Schema, Writer, read_marker,
types::{Record, Value},
};
use apache_avro_test_helper::TestResult;
const SCHEMA: &str = r#"{
"type": "record",
"name": "append_to_existing_file",
"fields": [
{"name": "a", "type": "int"}
]
}"#;
#[test]
fn avro_3630_append_to_an_existing_file() -> TestResult {
let schema = Schema::parse_str(SCHEMA).expect("Cannot parse the schema");
let bytes = get_avro_bytes(&schema);
let marker = read_marker(&bytes[..]);
let mut writer = Writer::append_to(&schema, bytes, marker);
writer
.append(create_datum(&schema, 2))
.expect("An error occurred while appending more data");
let new_bytes = writer.into_inner().expect("Cannot get the new bytes");
let reader = Reader::new(&*new_bytes).expect("Cannot read the new bytes");
let mut i = 1;
for value in reader {
check(&value, i);
i += 1
}
Ok(())
}
#[test]
fn avro_4031_append_to_file_using_multiple_writers() -> TestResult {
let schema = Schema::parse_str(SCHEMA).expect("Cannot parse the schema");
let mut first_writer = Writer::builder().schema(&schema).writer(Vec::new()).build();
first_writer.append(create_datum(&schema, -42))?;
let mut resulting_bytes = first_writer.into_inner()?;
let first_marker = read_marker(&resulting_bytes);
let mut second_writer = Writer::builder()
.schema(&schema)
.has_header(true)
.marker(first_marker)
.writer(Vec::new())
.build();
second_writer.append(create_datum(&schema, 42))?;
resulting_bytes.append(&mut second_writer.into_inner()?);
let values: Vec<_> = Reader::new(&resulting_bytes[..])?.collect();
check(&values[0], -42);
check(&values[1], 42);
Ok(())
}
fn get_avro_bytes(schema: &Schema) -> Vec<u8> {
let mut writer = Writer::new(schema, Vec::new());
writer
.append(create_datum(schema, 1))
.expect("An error while appending data");
writer.into_inner().expect("Cannot get the Avro bytes")
}
fn create_datum(schema: &Schema, value: i32) -> Record<'_> {
let mut datum = Record::new(schema).unwrap();
datum.put("a", value);
datum
}
fn check(value: &AvroResult<Value>, expected: i32) {
match value {
Ok(value) => match value {
Value::Record(fields) => match &fields[0] {
(_, Value::Int(actual)) => assert_eq!(&expected, actual),
_ => panic!("The field value type must be an Int: {:?}!", &fields[0]),
},
_ => panic!("The value type must be a Record: {value:?}!"),
},
Err(e) => panic!("Error while reading the data: {e:?}"),
}
}