-
-
Notifications
You must be signed in to change notification settings - Fork 51
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
Fix bug where already-quoted search path components could get double-quoted when creating the migrations table. #47
Conversation
There were the following issues with this Pull Request
You may need to change the commit messages to comply with the repository contributing guidelines. 🤖 This comment was generated by commitlint[bot]. Please report issues here. Happy coding! |
bba89f4
to
15faa5a
Compare
…components could get double-quoted when creating the mirations table. Postgres's `SHOW search_path` returns the search path as a comma-separated string with spaces, like `"$user", public, "another-quoted-schema"`, so checking whether the _first character_ of a search path component is `"` is not sufficient. Instead, just check whether the search path component contains quotes at all, and don't add any quotes if it does. Signed-off-by: Girffin Schneider <griffinschneider@gmail.com>
15faa5a
to
79436f3
Compare
Any outlook on when this can merge? This bug is giving me hell right now 😉 |
Sry went under the radar. This is missing a test, otherwise that might be fine to suggest. I doubt that anyone names their tables with an escaped quote, nor it should be allowed by most db systems using the pg wire protocol. |
My failure for this is far more simple.
Result: Side thought: if the schema name didn't need to be quoted in the output of |
Side Side note: The ... which also means it ends up unwittingly putting the migrations table in the wrong schema... |
@@ -219,7 +219,7 @@ var PgDriver = Base.extend({ | |||
var searchPathes = result[0].search_path.split(','); | |||
|
|||
for (var i = 0; i < searchPathes.length; ++i) { | |||
if (searchPathes[i].indexOf('"') !== 0) { | |||
if (searchPathes[i].indexOf('"') !== -1) { |
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.
The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.
So in this case shouldn't we use searchPathes[i].indexOf('"') === -1
instead? If the search_path does not have a " we will surround with one.
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 not convinced this quoting code is needed at all. The return from postgres of SHOW search_path
quotes anything that needs it, so it shouldn't be necessary to apply quoting to anything that came from that, only to the new entry being added.
... I think.
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.
If there is no BC then there is no need for quote at all. But the bug fix that is on this PR is still not fixing anything at all, it's still duplicating the quotes.
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.
yes that is true, b/c it would need to be === -1
. However I think it might be true that SHOW search_path
will actually not return anything that needs to be quoted. But can't guarantee it as well. Since the pg driver is also the base for pgwire drivers it could have side effects on those. Since I have no guarantee I will rather keep this to avoid a breaking change, but accept a bugfix for this of course.
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.
SHOW search_path;
could return "$user"
(with quotes) https://www.postgresql.org/docs/current/ddl-schemas.html. So this PR must be accepted to prevent throwing an exception.
[SQL] SET search_path TO "some_schema",""$user"","public"
[ERROR] AssertionError [ERR_ASSERTION]: ifError got unwanted exception: zero-length delimited identifier at or near """"
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.
we tried and merged it, but it causes the test suite to fail. this is breaking not fixing things. if anyone wants to jump on this again feel free to.
this change causes the exact error message the creator was getting. zero-length delimited identifier at or near """" test suite is finally running again now, just merged for testing and reverted |
The CI failure is sadly very difficult to interpret, it's hard to tell where the error is coming from at all :( Given that PG seems to return the search_path value always already quoted, I retain my earlier suggestion that this entire chunk of code can probably get deleted and just prepend the desired search path to the current one unconditionally. Having a schema listed multiple times in the search path doesn't seem to be an error, so this seems like it should be safe even in cases where it is redundant. |
Actually not really. The last commands executed with your attempted fix are
and without
The $user search path returned by SHOW search_path by postgres is
So the check for a starting quote, does its job as it should. If you want to try get this fix done, the test suite is working now again and is rewritten on lab. You can add global.verbose = true to the tests to temporarily see all the executed queries. |
I am not a fan of this search path logic anyways, so if there is a better way to handle, I would be glad to discuss 😅 |
Ultimately: Your change here caused the check if "first char is not a quote" to become, there is a quote anywhere in the string. Causing the quoting to be triggered. If you actually wanted to avoid quoting this was doing the inverse of it. |
This only works for the first element of the search path as written:
oops, the first char of the second element is ... a space due to not trimming the paths after splitting on commas. We can get more fun if we e.g. start with
I'm not the PR author ;)
Yep ... though as we can see with the formatting issue above, fixing this logic inversion would also have caused My proposal is to replace this entire block: https://github.com/db-migrate/pg/blob/master/index.js#L252-L272 With: return this.all(`SET search_path TO "${this.schema}", ${result[0].search_path}`); |
I didn't exactly scroll through and check :) |
The thing is, those things were added for a reason. I don't know them anymore, but I am certainly breaking someones setup if I'm going to remove this. Generally I would say it should be save to assume, the db returns a usable string that itself understands though. |
It is probably all this tango before, trying to get a version from various amounts of different postgres versions and variations. So I guess, we really can't remove this safely, just trying to actually make it work. |
The search path actually gets trimmed here. Line 257 in 00aa56b
This is probably just too late. |
yes its too late. added a test reproducing this, and putting trim before actually fixes this issue. |
fixed in 13e956b |
Postgres's
SHOW search_path
returns the search path as a comma-separated string with spaces, like"$user", public, "another-quoted-schema"
, so checking whether the first character of a search path component is"
is not sufficient. Instead, just check whether the search path component contains quotes at all, and don't add any quotes if it does.To reproduce the bug:
""
):