-
-
Notifications
You must be signed in to change notification settings - Fork 323
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
db.dropcolumn: Circumvent length limit for sqlite3 SQL STDIN string #3273
db.dropcolumn: Circumvent length limit for sqlite3 SQL STDIN string #3273
Conversation
(Backport to 8.3 would be nice - I am not allowed to add labels) |
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.
This is really great upgrade!
driver=driver, | ||
) | ||
|
||
if sqlite3_version >= "3.35.0": |
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.
Testing versions is a pain:
>>> "10.0.0" >= "3.35.0"
False
>>> [int(i) for i in "10.0.0".split(".")] >= [int(i) for i in "3.35.0".split(".")]
True
but:
>>> [int(i) for i in "4.0.0-dev".split(".")] >= [int(i) for i in "3.35.0".split(".")]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
ValueError: invalid literal for int() with base 10: '0-dev'
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.
Testing only major and minor version (3.35) should be enough and skip the patch/minor part which is not really relevant to this.
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.
Now comparing major and minor versions as arrays of INTs in recent commit.
In a little concerned about the old and new code in there. I never did SQL in Python, but if a code equivalent to that was done in C# and PHP, what looks like concatenation of strings to create a SQL query, would be vulnerable to SQL injection. I would expect that placeholders would be used and the parameters would be binded then executed. |
Co-authored-by: Vaclav Petras <wenzeslaus@gmail.com>
How could this look like? I read in some stackoverflow posts (no documentation quote at hand) that binding table or column names is not possible (for sqlite3), only values. if table not in gscript.read_command("db.tables"):
gscript.fatal(_("Table <%s> not found in db.tables") % column) but I am not sure if this is how |
flags="c", | ||
database=database, | ||
driver=driver, | ||
).split(".")[0:2] |
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.
See maxsplit parameter which avoids the need for indexing later.
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 don't see the option to select only the first items when using maxsplit, or am I overseeing something? It will split until the given index but then adding all following into one item. This will cause the problem you described above:
>>> sqlite3_version = "4.0.0-dev"
>>> sqlite3_version.split('.',1)
['4', '0.0-dev']
>>> [int(i) for i in sqlite3_version.split('.',1)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
ValueError: invalid literal for int() with base 10: '0.0-dev'
>>> sqlite3_version.split('.',2)
['4', '0', '0-dev']
>>> [int(i) for i in sqlite3_version.split('.',2)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
ValueError: invalid literal for int() with base 10: '0-dev'
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.
@mmacata You're right, maxsplit
might be used to limit the resulting list to three parts, eg:
>>> sqlite3_version = "4.0.0-dev"
>>> sqlite3_version.split('.', maxsplit=3)[:2]
['4', '0']
but the index is needed. Although that seems to me to be over doing things. Index should be enough.
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.
@wenzeslaus do you also agee? Can this be merged as is?
I think this question on sql safety is out of scope for this PR. |
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.
Looks good to me!
I'll merge this if no objections. |
…3273) * db.dropcolumn: support more recent sqlite3 drop column command * use sqlite_version() * Update scripts/db.dropcolumn/db.dropcolumn.py * enhance version comparison Co-authored-by: Vaclav Petras <wenzeslaus@gmail.com>
…SGeo#3273) * db.dropcolumn: support more recent sqlite3 drop column command * use sqlite_version() * Update scripts/db.dropcolumn/db.dropcolumn.py * enhance version comparison Co-authored-by: Vaclav Petras <wenzeslaus@gmail.com>
This PR supports a more recent sqlite3 command to drop a column within db.dropcolumn.
In sqlite3 3.35.0, the DROP COLUMN command was added. This PR makes use of the command if the sqlite3 version is high enough.
Background is a failing
db.in.ogr
command for a CSV file containing many columns:And with further debugging:
So the created SQL string becomes too long to be passed via stdin in
"db.execute", input="-", database=database, driver=driver, stdin=sql
command. This PR circumvents this by using the newer sqlite3 syntax if available.