age
age copied to clipboard
Write Swift Driver for AGE
- Ensure the Swift driver is quality controlled and secure
- Check for consistency and robustness
I can help with a Swift Driver. Been developing iOS apps in ObjC/C/C++ and Swift since way back. Some of my iOS libs are used in 1000s of iOS apps, like this one: https://www.appsight.io/sdk/typhoon
Besides the driver, can help to set up an executable specification (BDD style tests) to ensure the two points above.
Hey, I am Fahad Zaheer, excited to work on this project
Hi this is Steve Shin from Vancouver Team.
Is there a short way to prepare the statements and execute them, if you are trying to run multiple queries and you are not concerned with the results that are generated by those statements.
Forexample I want to execute these two statements, is there any short way to write these two statements and execute them.
do {
let load_age_statement = try connection.prepareStatement(text: "Load 'age';")
let set_path_statement = try connection.prepareStatement(text: "SET search_path = ag_catalog, '$user', public;")
var cursor = try load_age_statement.execute()
load_age_statement.close()
cursor = try set_path_statement.execute()
}catch{
print(error)
}
Greetings! I just finished some initial work on a Swift driver for Apache AGE. The core project includes the antlr4 parsing with a visitor to create the Swift data structures. I translated some test cases from other projects as well. Project can be found here: https://github.com/joshjacob/SwiftAge
I also have a sample app using the PostgresNIO project. This is the underlying project to the Vapor ORM package but doesn't contain any ORM code. However, it is written with SwiftNIO which would be more performant in a server environment than other Swift PostgreSQL drivers. The example code has some code to take the data from PostgresNIO and pass it through the parser. This would ideally be part of the core project and implemented as an extension to PostgresNIO similar to other drivers. It's a start and does connect, query and parse AGE. Here is the examples project: https://github.com/joshjacob/SwiftAgeExamples
@joshjacob that's great!! I'm eager to take a look. awesome
I just pushed an update to https://github.com/joshjacob/SwiftAge that includes extension methods to run graph queries and return parsed Agtype results. The README and test cases show examples of running and handling results from these extension methods.
@joshjacob awesome, great work. do you have further stuff you hope to add down the line?
@dehowef The parsing of returned data is in a good spot. There are a few outstanding issues with a Path object and some better error/exception handling left to do.
Currently I'm looking at how some of the other drivers use parameters and binding. I'm still in the initial stages of researching how that works.
Once those functional aspects are complete I would plan for some more examples/demos. Any input/feedback would be appreciated.
Good to hear. One thing I'd pay particular attention to is how the query string from user input is handled/constructed by the driver-- it's best to do so in a way that prevents malicious/unintended user input. The Python and Go Drivers both ensure that the user-inputted strings are sanitized to protect against attacks. You can look at the buildCypher function in the Python code as an example of how we did that using PsycoPG's included mogrify function. Cheers~
@dehowef For safe parameter handling, the solution I landed on is built on PostgresNIO's string interpolation. This code:
let params: Dictionary<String,AGValue> = ["newName": "Little'Bobby'Tables"]
let paramsWrapper: AGValueWrapper = AGValueWrapper.init(value: params)
let agRows = try await connection.execCypher(
"SELECT * FROM cypher('test_graph_1', $$ CREATE (v:Person {name: $newName}) RETURN v $$, \( paramsWrapper )) as (v agtype);",
logger: logger)
will send the following query to Postgres:
SELECT * FROM cypher('test_graph_1', $$ CREATE (v:Person {name: $newName}) RETURN v $$, $1) as (v agtype);
with the $1
parameter being a jsonb encoding of that Dictionary. Let me know if you see any concerns with that approach.
@dehowef For safe parameter handling, the solution I landed on is built on PostgresNIO's string interpolation. This code:
let params: Dictionary<String,AGValue> = ["newName": "Little'Bobby'Tables"] let paramsWrapper: AGValueWrapper = AGValueWrapper.init(value: params) let agRows = try await connection.execCypher( "SELECT * FROM cypher('test_graph_1', $$ CREATE (v:Person {name: $newName}) RETURN v $$, \( paramsWrapper )) as (v agtype);", logger: logger)
will send the following query to Postgres:
SELECT * FROM cypher('test_graph_1', $$ CREATE (v:Person {name: $newName}) RETURN v $$, $1) as (v agtype);
with the
$1
parameter being a jsonb encoding of that Dictionary. Let me know if you see any concerns with that approach.
That's awesome to know. Great work! Thank you for your contribution
We also have a way to directly pass in parameters to the cypher function. Just fyi.