@Override public void processMessage(ByteBuffer buffer, ReplicationMessageProcessor processor, TypeRegistry typeRegistry) throws SQLException, InterruptedException { try { if (!buffer.hasArray()) { throw new IllegalStateException("Invalid buffer received from PG server during streaming replication"); } final byte[] source = buffer.array(); final byte[] content = Arrays.copyOfRange(source, buffer.arrayOffset(), source.length); final Document message = DocumentReader.floatNumbersAsTextReader().read(content); LOGGER.debug("Message arrived for decoding {}", message); final long txId = message.getLong("xid"); final String timestamp = message.getString("timestamp"); final long commitTime = dateTime.systemTimestamp(timestamp); final Array changes = message.getArray("change"); Iterator<Entry> it = changes.iterator(); while (it.hasNext()) { Value value = it.next().getValue(); processor.process(new Wal2JsonReplicationMessage(txId, commitTime, value.asDocument(), containsMetadata, !it.hasNext(), typeRegistry)); } } catch (final IOException e) { throw new ConnectException(e); } }
default void forEach(BiConsumer<Path, Value> consumer) { Path root = Path.root(); stream().forEach((field) -> { Path path = root.append(field.getName().toString()); Value value = field.getValue(); if (value.isDocument()) { value.asDocument().forEach((p, v) -> { consumer.accept(path.append(p), v); }); } else if (value.isArray()) { value.asArray().forEach((entry) -> { consumer.accept(path.append(Integer.toString(entry.getIndex())), entry.getValue()); }); } else { consumer.accept(path, value); } }); }
@Override public boolean equals(Object obj) { if ( obj == this ) return true; if ( obj instanceof Array.Entry ) { Array.Entry that = (Array.Entry)obj; return this.getIndex() == that.getIndex() && Objects.equals(this.getValue(),that.getValue()); } return false; }
/** * Create a new test specification that is a copy of this specification except with the test data read from * the specified input stream. The supplied stream is read and variables substituted when the {@link #testData() test * data} is {@link TestData#read() read}. * * @param stream the supplier to the stream of test data; may not be null * @return the new test specification; never null */ public TestSpecification readJsonTestData(InputStreamSupplier stream) { Function<TestSpecification, TestData> supplier = (spec) -> { // We need the variables from the TestSpecification that will own this data ... AvailableVariables variables = spec.variables(); return () -> { // Copy the content into a temporary file and replace variables line by line ... File tmpFile = replaceVariables(stream.get(), variables); Array arrayOfDocuments = ArrayReader.defaultReader().readArray(tmpFile); return Iterators.readOnly(arrayOfDocuments.iterator(), (entry) -> { Value value = entry.getValue(); return value.asDocument(); }); }; }; return new TestSpecification(name, config, env, supplier, variables); }
@Override public void processMessage(ByteBuffer buffer, ReplicationMessageProcessor processor, TypeRegistry typeRegistry) throws SQLException, InterruptedException { try { if (!buffer.hasArray()) { throw new IllegalStateException("Invalid buffer received from PG server during streaming replication"); } final byte[] source = buffer.array(); final byte[] content = Arrays.copyOfRange(source, buffer.arrayOffset(), source.length); final Document message = DocumentReader.floatNumbersAsTextReader().read(content); LOGGER.debug("Message arrived for decoding {}", message); final long txId = message.getLong("xid"); final String timestamp = message.getString("timestamp"); final long commitTime = dateTime.systemTimestamp(timestamp); final Array changes = message.getArray("change"); Iterator<Entry> it = changes.iterator(); while (it.hasNext()) { Value value = it.next().getValue(); processor.process(new Wal2JsonReplicationMessage(txId, commitTime, value.asDocument(), containsMetadata, !it.hasNext(), typeRegistry)); } } catch (final IOException e) { throw new ConnectException(e); } }
default void forEach(BiConsumer<Path, Value> consumer) { Path root = Path.root(); stream().forEach((field) -> { Path path = root.append(field.getName().toString()); Value value = field.getValue(); if (value.isDocument()) { value.asDocument().forEach((p, v) -> { consumer.accept(path.append(p), v); }); } else if (value.isArray()) { value.asArray().forEach((entry) -> { consumer.accept(path.append(Integer.toString(entry.getIndex())), entry.getValue()); }); } else { consumer.accept(path, value); } }); }
/** * Sets on this object all key/value pairs from the supplied map. If the supplied map is null, this method does nothing. * * @param entries the entries that are to be used to modify this array * @return this array to allow for chaining methods */ default Array putAll(Iterable<Entry> entries) { if (entries != null) { entries.forEach(entry -> { if (entry != null) { Value value = entry.getValue().clone(); setValue(entry.getIndex(), value); } }); } return this; }
default Iterable<Value> values() { return Iterators.around(Iterators.around(this, (entry) -> entry.getValue())); }
@Override public int compareTo(Array.Entry that) { if ( this == that ) return 0; if ( this.getIndex() != that.getIndex() ) return this.getIndex() - that.getIndex(); return Value.compareTo(this.getValue(),that.getValue()); } }
public static TableChanges fromArray(Array array) { TableChanges tableChanges = new TableChanges(); for (Entry entry : array) { TableChange change = TableChange.fromDocument(entry.getValue().asDocument()); if (change.getType() == TableChangeType.CREATE) { tableChanges.create(change.table); } } return tableChanges; }
@Override public boolean equals(Object obj) { if ( obj == this ) return true; if ( obj instanceof Array.Entry ) { Array.Entry that = (Array.Entry)obj; return this.getIndex() == that.getIndex() && Objects.equals(this.getValue(),that.getValue()); } return false; }
Iterator<Array.Entry> docs = expected.iterator(); while (docs.hasNext()) { Document doc = docs.next().getValue().asDocument(); if (doc.has(CONTROL_KEY)) {
/** * Create a new test specification that is a copy of this specification except with the test data read from * the specified input stream. The supplied stream is read and variables substituted when the {@link #testData() test * data} is {@link TestData#read() read}. * * @param stream the supplier to the stream of test data; may not be null * @return the new test specification; never null */ public TestSpecification readJsonTestData(InputStreamSupplier stream) { Function<TestSpecification, TestData> supplier = (spec) -> { // We need the variables from the TestSpecification that will own this data ... AvailableVariables variables = spec.variables(); return () -> { // Copy the content into a temporary file and replace variables line by line ... File tmpFile = replaceVariables(stream.get(), variables); Array arrayOfDocuments = ArrayReader.defaultReader().readArray(tmpFile); return Iterators.readOnly(arrayOfDocuments.iterator(), (entry) -> { Value value = entry.getValue(); return value.asDocument(); }); }; }; return new TestSpecification(name, config, env, supplier, variables); }
/** * Sets on this object all key/value pairs from the supplied map. If the supplied map is null, this method does nothing. * * @param entries the entries that are to be used to modify this array * @return this array to allow for chaining methods */ default Array putAll(Iterable<Entry> entries) { if (entries != null) { entries.forEach(entry -> { if (entry != null) { Value value = entry.getValue().clone(); setValue(entry.getIndex(), value); } }); } return this; }
protected List<Document> readResources(String prefix, String... resources) throws IOException { List<Document> documents = new ArrayList<>(); for (String resource : resources) { String content = Testing.Files.readResourceAsString(prefix + resource); Array array = null; try { Document doc = DocumentReader.defaultReader().read(content); array = doc.getArray("entityChanges"); } catch (IOException e) { array = ArrayReader.defaultReader().readArray(content); } array.forEach(entry -> documents.add(entry.getValue().asDocument())); } return documents; }
default Iterable<Value> values() { return Iterators.around(Iterators.around(this, (entry) -> entry.getValue())); }
@Override public int compareTo(Array.Entry that) { if ( this == that ) return 0; if ( this.getIndex() != that.getIndex() ) return this.getIndex() - that.getIndex(); return Value.compareTo(this.getValue(),that.getValue()); } }
public static TableChanges fromArray(Array array) { TableChanges tableChanges = new TableChanges(); for (Entry entry : array) { TableChange change = TableChange.fromDocument(entry.getValue().asDocument()); if (change.getType() == TableChangeType.CREATE) { tableChanges.create(change.table); } } return tableChanges; }