-
-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes LISTEN
to quote channel name
#466
Fixes LISTEN
to quote channel name
#466
Conversation
6ceb243
to
b93882e
Compare
This behavior appears to have been introduced in v1.18.0. Interestingly, by watching SQL logs it appears that version also changed |
b93882e
to
950fd71
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! See comments!
@@ -594,7 +594,7 @@ final class PostgresChannelHandler: ChannelDuplexHandler { | |||
private func makeStartListeningQuery(channel: String, context: ChannelHandlerContext) -> PSQLTask { | |||
let promise = context.eventLoop.makePromise(of: PSQLRowStream.self) | |||
let query = ExtendedQueryContext( | |||
query: PostgresQuery(unsafeSQL: "LISTEN \(channel);"), | |||
query: PostgresQuery(unsafeSQL: "LISTEN \"\(channel)\";"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
query: PostgresQuery(unsafeSQL: "LISTEN \"\(channel)\";"), | |
query: PostgresQuery(unsafeSQL: #"LISTEN "\#(channel)";"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks!
@@ -642,7 +642,7 @@ final class PostgresChannelHandler: ChannelDuplexHandler { | |||
private func makeUnlistenQuery(channel: String, context: ChannelHandlerContext) -> PSQLTask { | |||
let promise = context.eventLoop.makePromise(of: PSQLRowStream.self) | |||
let query = ExtendedQueryContext( | |||
query: PostgresQuery(unsafeSQL: "UNLISTEN \(channel);"), | |||
query: PostgresQuery(unsafeSQL: "UNLISTEN \"\(channel)\";"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
query: PostgresQuery(unsafeSQL: "UNLISTEN \"\(channel)\";"), | |
query: PostgresQuery(unsafeSQL: #"UNLISTEN "\#(channel)";"#), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. Done
func testNotificationWithKeywordChannelName() { | ||
var conn: PostgresConnection? | ||
XCTAssertNoThrow(conn = try PostgresConnection.test(on: eventLoop).wait()) | ||
defer { XCTAssertNoThrow( try conn?.close().wait() ) } | ||
|
||
var receivedNotifications: [PostgresMessage.NotificationResponse] = [] | ||
conn?.addListener(channel: "default") { context, notification in | ||
receivedNotifications.append(notification) | ||
} | ||
XCTAssertNoThrow(_ = try conn?.simpleQuery("LISTEN \"default\"").wait()) | ||
XCTAssertNoThrow(_ = try conn?.simpleQuery("NOTIFY \"default\"").wait()) | ||
XCTAssertNoThrow(_ = try conn?.simpleQuery("SELECT 1").wait()) | ||
XCTAssertEqual(receivedNotifications.count, 1) | ||
XCTAssertEqual(receivedNotifications.first?.channel, "default") | ||
XCTAssertEqual(receivedNotifications.first?.payload, "") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this test interact with the code that you changed? Maybe we want to change AsyncPostgresConnectionTests.testListenAndNotify
to something like this:
func testListenAndNotify() async throws {
let channelNames = [
"foo",
"default"
]
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
let eventLoop = eventLoopGroup.next()
for channelName in channelNames {
try await self.withTestConnection(on: eventLoop) { connection in
let stream = try await connection.listen(channelName)
var iterator = stream.makeAsyncIterator()
try await self.withTestConnection(on: eventLoop) { other in
try await other.query(#"NOTIFY "\#(unescaped: channelName)", 'bar';"#, logger: .psqlTest)
try await other.query(#"NOTIFY "\#(unescaped: channelName)", 'foo';"#, logger: .psqlTest)
}
let first = try await iterator.next()
XCTAssertEqual(first?.payload, "bar")
let second = try await iterator.next()
XCTAssertEqual(second?.payload, "foo")
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My change was related to the quoting that occurs in the LISTEN
SQL query caused by addListener
. So before the changes, line 237 of this new test would fail on the PostgreSQL side when running LISTEN default;
with the error:
ERROR: syntax error at or near "default" at character 8
STATEMENT: LISTEN default;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm totally happy to combine it into testListenAndNotify
though if you prefer it that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I've made your recommended changes to testListenAndNotify
and removed the testNotificationWithKeywordChannelName
test
@NeedleInAJayStack Does this mean you actually used the old |
950fd71
to
0908fc7
Compare
Yeah, we were using the old LISTEN API. However, my comment was more related to these tests, and specifically that the lines with |
I'm able to recreate the
I'm able to recreate these errors on |
f37c348
to
30abfd3
Compare
30abfd3
to
75ee49f
Compare
75ee49f
to
478723f
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #466 +/- ##
=========================================
+ Coverage 0 61.73% +61.73%
=========================================
Files 0 125 +125
Lines 0 10024 +10024
=========================================
+ Hits 0 6188 +6188
- Misses 0 3836 +3836
|
This adjusts the SQL
LISTEN
statement called byPostgresConnection.addListener
to quote the channel name.For example, previously
addListener("abc")
would runLISTEN abc;
and it will now runLISTEN "abc";
As far as I can tell, this only matters when the channel name is a reserved Postgres keyword, like
default
.