Repository navigation
Conversation
A row that cannot be converted to a Python object is reported by discarding the rest of the result stream and raising. Callers reach that discard both before the results have been requested and part way through consuming them, so it drains the stream and asks the server for it only when nothing has asked yet. A second pull mid-stream is refused by the session, which left the connection unusable and the raised error claiming the query might not have run.
Memgraph returns spatial values as bolt point structures, which mgclient decodes but pymgclient had no Python type for, so any query returning a point raised "encountered a mg_value of unknown type". Queries now yield mgclient.Point2D and mgclient.Point3D, and both can be passed back as query parameters. A point carries the identifier of the spatial reference system it is expressed in, so the two coordinates are named x_longitude and y_latitude (and z_height) to read correctly under both the Cartesian and the WGS84 systems Memgraph supports. The types compare and hash by value.
A cursor may bound its pull with a row count, in which case the server answers the batch with has_more set and keeps the rest of the stream. The discard that follows a row-conversion failure now pulls again until the server reports the stream finished, so the query is really done with before the connection is handed back as ready.
A point can be built with keyword arguments as well as positionally, which leaves room to add a field later without disturbing existing calls.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this does
Adds
mgclient.Point2Dandmgclient.Point3Dso spatial values can be read from and sent to Memgraph, and fixes the result-discard path that turned an unconvertible row into a crash.Point support
Memgraph returns spatial values as bolt point structures. mgclient has decoded them for some time, but
mg_value_to_py_objecthad no case for either, so any query returning a point raisedRuntimeError: encountered a mg_value of unknown type.A point carries the identifier of the spatial reference system it is expressed in, so the coordinates are named
x_longitude,y_latitudeandz_height: the same field means a Cartesian axis or a WGS84 angle depending on the srid, and the names read correctly under both. The types compare and hash by value, and the constructors take their arguments positionally or by keyword.The API follows the shape worked out on the earlier
add-spatial-typesbranch, with one correction: the srid for a Cartesian 3D point is 9157, not 9757. The four srids are confirmed against a running server and named as constants in the tests.Not crashing on a row that will not convert
When a row cannot be converted to a Python object, the rest of the stream is discarded and the error raised. Two things were wrong with that path, and a point value reached both of them.
connection_discard_allasserted the connection wasCONN_STATUS_EXECUTING, butconnection_fetchcalls it whileCONN_STATUS_FETCHING. With asserts live that aborted the process. Under-DNDEBUG, which is how the wheels are built, the assert is compiled out and the function went on to pull a second time on a session that was already streaming, which the session refuses: the connection was left unusable and the error claimed the query might not have run.A cursor may also bound its pull with a row count, so draining the current batch is not always the end of the stream. The discard now pulls again while the server reports
has_more, and only then hands the connection back as ready.Both are reachable by any value type mgclient decodes and pymgclient does not, so this is not specific to points: it is what a version skew between the two looks like.
Testing
test_types.pycovers the types with no server: attributes, equality across every field, hashing,strandrepr, readonly attributes, keyword arguments, and srid validation including the limits of the wire format.test_glue.pycovers both directions against a real Memgraph, in both coordinate systems, nested in lists and maps, and stored as a node property.93 pass and 14 skip on Memgraph 3.x, in a release build and in an assert-enabled one. The skips are the SSL and HA-cluster suites, which need their own servers. 20k point round trips show no memory growth.
The discard fix has no automated test. Once every mgclient type is handled the path is unreachable from Python, since it only triggers on that version skew. It was verified by hand by temporarily removing the point case to force a conversion failure again, checking that the eager, lazy, multi-row and in-transaction paths all raise cleanly and leave the connection usable.
Worth a maintainer's eye
CHANGELOG.rstis untouched. It currently stops at 1.5.1 while the tags reach v1.6.0, so the right heading for these entries is a call about the release process rather than something to guess at.Point2DandPoint3Dare near-identical implementations. That matches howNode,RelationshipandPathare each written by hand in this file, so it is left alone rather than made the one place that generates its slots from a macro.tp_hashand returnNotImplementedfor a mismatched type.Node,RelationshipandPathdo neither, so equal instances of those hash differently andnode < "foo"evaluates toFalseinstead of raising. Pre-existing and untouched here, but the point types now sit next to three siblings that get it wrong.