/* Populates a wire protocol message for a delete event. */ int update_frame_with_delete_raw(avro_value_t *frame_val, Oid relid, bytea *key_bin, bytea *old_bin) { int err = 0; avro_value_t msg_val, union_val, record_val, relid_val, key_val, oldrow_val, branch_val; check(err, avro_value_get_by_index(frame_val, 0, &msg_val, NULL)); check(err, avro_value_append(&msg_val, &union_val, NULL)); check(err, avro_value_set_branch(&union_val, PROTOCOL_MSG_DELETE, &record_val)); check(err, avro_value_get_by_index(&record_val, 0, &relid_val, NULL)); check(err, avro_value_get_by_index(&record_val, 1, &key_val, NULL)); check(err, avro_value_get_by_index(&record_val, 2, &oldrow_val, NULL)); check(err, avro_value_set_long(&relid_val, relid)); if (key_bin) { check(err, avro_value_set_branch(&key_val, 1, &branch_val)); check(err, avro_value_set_bytes(&branch_val, VARDATA(key_bin), VARSIZE(key_bin) - VARHDRSZ)); } else { check(err, avro_value_set_branch(&key_val, 0, NULL)); } if (old_bin) { check(err, avro_value_set_branch(&oldrow_val, 1, &branch_val)); check(err, avro_value_set_bytes(&branch_val, VARDATA(old_bin), VARSIZE(old_bin) - VARHDRSZ)); } else { check(err, avro_value_set_branch(&oldrow_val, 0, NULL)); } return err; }
int schema_traverse(const avro_schema_t schema, json_t *json, json_t *dft, avro_value_t *current_val, int quiet, int strjson, size_t max_str_sz) { json = json ? json : dft; if (!json) { fprintf(stderr, "ERROR: Avro schema does not match JSON\n"); return 1; } switch (schema->type) { case AVRO_RECORD: { if (!json_is_object(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON object for Avro record, got something else\n"); return 1; } int len = avro_schema_record_size(schema), i; for (i=0; i<len; i++) { const char *name = avro_schema_record_field_name(schema, i); avro_schema_t field_schema = avro_schema_record_field_get_by_index(schema, i); json_t *json_val = json_object_get(json, name); json_t *dft = avro_schema_record_field_default_get_by_index(schema, i); avro_value_t field; avro_value_get_by_index(current_val, i, &field, NULL); if (schema_traverse(field_schema, json_val, dft, &field, quiet, strjson, max_str_sz)) return 1; } } break; case AVRO_LINK: /* TODO */ fprintf(stderr, "ERROR: AVRO_LINK is not implemented\n"); return 1; break; case AVRO_STRING: if (!json_is_string(json)) { if (json && strjson) { /* -j specified, just dump the remaining json as string */ char * js = json_dumps(json, JSON_COMPACT|JSON_SORT_KEYS|JSON_ENCODE_ANY); if (max_str_sz && (strlen(js) > max_str_sz)) js[max_str_sz] = 0; /* truncate the string - this will result in invalid JSON! */ avro_value_set_string(current_val, js); free(js); break; } if (!quiet) fprintf(stderr, "ERROR: Expecting JSON string for Avro string, got something else\n"); return 1; } else { const char *js = json_string_value(json); if (max_str_sz && (strlen(js) > max_str_sz)) { /* truncate the string */ char *jst = malloc(strlen(js)); strcpy(jst, js); jst[max_str_sz] = 0; avro_value_set_string(current_val, jst); free(jst); } else avro_value_set_string(current_val, js); } break; case AVRO_BYTES: if (!json_is_string(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON string for Avro string, got something else\n"); return 1; } /* NB: Jansson uses null-terminated strings, so embedded nulls are NOT supported, not even escaped ones */ const char *s = json_string_value(json); avro_value_set_bytes(current_val, (void *)s, strlen(s)); break; case AVRO_INT32: if (!json_is_integer(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON integer for Avro int, got something else\n"); return 1; } avro_value_set_int(current_val, json_integer_value(json)); break; case AVRO_INT64: if (!json_is_integer(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON integer for Avro long, got something else\n"); return 1; } avro_value_set_long(current_val, json_integer_value(json)); break; case AVRO_FLOAT: if (!json_is_number(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON number for Avro float, got something else\n"); return 1; } avro_value_set_float(current_val, json_number_value(json)); break; case AVRO_DOUBLE: if (!json_is_number(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON number for Avro double, got something else\n"); return 1; } avro_value_set_double(current_val, json_number_value(json)); break; case AVRO_BOOLEAN: if (!json_is_boolean(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON boolean for Avro boolean, got something else\n"); return 1; } avro_value_set_boolean(current_val, json_is_true(json)); break; case AVRO_NULL: if (!json_is_null(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON null for Avro null, got something else\n"); return 1; } avro_value_set_null(current_val); break; case AVRO_ENUM: // TODO ??? break; case AVRO_ARRAY: if (!json_is_array(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON array for Avro array, got something else\n"); return 1; } else { int i, len = json_array_size(json); avro_schema_t items = avro_schema_array_items(schema); avro_value_t val; for (i=0; i<len; i++) { avro_value_append(current_val, &val, NULL); if (schema_traverse(items, json_array_get(json, i), NULL, &val, quiet, strjson, max_str_sz)) return 1; } } break; case AVRO_MAP: if (!json_is_object(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON object for Avro map, got something else\n"); return 1; } else { avro_schema_t values = avro_schema_map_values(schema); void *iter = json_object_iter(json); avro_value_t val; while (iter) { avro_value_add(current_val, json_object_iter_key(iter), &val, 0, 0); if (schema_traverse(values, json_object_iter_value(iter), NULL, &val, quiet, strjson, max_str_sz)) return 1; iter = json_object_iter_next(json, iter); } } break; case AVRO_UNION: { int i; avro_value_t branch; for (i=0; i<avro_schema_union_size(schema); i++) { avro_value_set_branch(current_val, i, &branch); avro_schema_t type = avro_schema_union_branch(schema, i); if (!schema_traverse(type, json, NULL, &branch, 1, strjson, max_str_sz)) break; } if (i==avro_schema_union_size(schema)) { fprintf(stderr, "ERROR: No type in the Avro union matched the JSON type we got\n"); return 1; } break; } case AVRO_FIXED: if (!json_is_string(json)) { if (!quiet) fprintf(stderr, "ERROR: Expecting JSON string for Avro fixed, got something else\n"); return 1; } /* NB: Jansson uses null-terminated strings, so embedded nulls are NOT supported, not even escaped ones */ const char *f = json_string_value(json); if (avro_value_set_fixed(current_val, (void *)f, strlen(f))) { fprintf(stderr, "ERROR: Setting Avro fixed value FAILED\n"); return 1; } break; default: fprintf(stderr, "ERROR: Unknown type: %d\n", schema->type); return 1; } return 0; }