Ben, (comments inline)
On 18 May 2015, at 17:46, Ben Coman <btc@openInWorld.com> wrote:
On Mon, May 18, 2015 at 7:06 PM, Sven Van Caekenberghe <sven@stfx.eu> wrote:
On 18 May 2015, at 12:13, Guillermo Polito <guillermopolito@gmail.com> wrote:
Hi Sven, I'll take that into account. I did not think about using an empty host/port pair, maybe because of the extra slash.
Also, I do not need to convert the file name to a file reference. That is done in sqlite by the sqlite library itself, so it's less work for the driver. The only need I need to do is: - for nbsqlite get the file name - for opendbx get the full file name and split into directory + file name because they are two different arguments for the library.
I think that if you want to view (part of) a URL as a file system path and/or if you want to work with that path (splitting it directory/file for example), converting to a file reference is a good idea. ZnUrl can do file interpretation to some degree (#directory & #file, #isDirectoryPath & #isFilePath), but not very well (it is not its primary application).
ZnUrl>>#path is actually not the best selector to use. It uses the internal representation. Like #directory & #file, #isDirectoryPath & #isFilePath, these leak some internals. ZnUrl>>#pathString is better, and will give you a leading $/ while encoding everything correctly.
Also, relative File URLs simply do not exist.
This sparked my interest to read RFC3986 (https://tools.ietf.org/html/rfc3986#section-5.2.4) which says:
A relative reference that begins with a single slash character is termed an absolute-path reference. A relative reference that does not begin with a slash character is termed a relative-path reference."
The path segments "." and "..", also known as dot-segments, are defined for relative reference within the path name hierarchy. They are intended for use at the beginning of a relative-path reference to indicate relative position within the hierarchical tree of names."
Within a representation with a well defined Base URI of "http://a/b/c/d;p?q" a relative reference is transformed to its Target URI as follows. "g:h" = "g:h" "g" = "http://a/b/c/g" "./g" = "http://a/b/c/g" "../g" = "http://a/b/g" "/g" = "http://a/g"
So slightly as an aside, this makes me wonder if we should consider that when the Image is a opened as a file, its Base URI can be considered to be 'file:///b/c/Pharo.image' such that its reasonable to have the following relative references transformed as follows: 'g:h' asUrl asString "--> 'g:h' 'g' asUrl asString "--> 'file:///b/c/g' './g' asUrl asString "--> 'file:///b/c/g' '../g' asUrl asString "--> 'file:///b/g' '/g' asUrl asString "--> 'file:///g'
Effectively, the default scheme is #file rather than nil, as it is currently.
RFC3986 5.2.2. "Transform References" shows a non-strict case where it seems that following intuitive example is valid 'file:///./g' asUrl asString "--> file:///b/c/g' " per this line... T.path = merge(Base.path, R.path);
RFC3986 5.1.2. "Base URI from the Encapsulating Entity" indicates we could consider the Base URI for the sqlite3 scheme to derive from the Image's 'file:///b/c/Pharo.image' URI to be... 'sqlite3:///b/c/Pharo.image' such that per 5.2.2. the following would be valid... 'sqllite3:///./g' asUrl asString "--> sqllite3:///b/c/g' "
All that is from a patchy skim of RFC3986, so maybe I got it wrong, but maybe its a view worth considering.
I made the following commits: === Name: Zinc-Resource-Meta-Core-SvenVanCaekenberghe.53 Author: SvenVanCaekenberghe Time: 19 May 2015, 4:31:02.297452 pm UUID: 55fd5688-02f5-4ac7-b112-3ef2721000e5 Ancestors: Zinc-Resource-Meta-Core-SvenVanCaekenberghe.52 Extend the ZnUrl API a bit, for convenience: ZnUrl class>>#image returns a File URL to the current image (Thx Ben Coman) ZnUrl>>#+ as an alias for ZnUrl>>#withRelativeReference: ZnUrl>>#asFileUrl return a copy with the scheme changed to file:// ZnUrl>>#portIfAbsent: to handle missing ports Add some unit tests for the new API === Name: Zinc-Resource-Meta-Tests-SvenVanCaekenberghe.36 Author: SvenVanCaekenberghe Time: 19 May 2015, 4:31:30.415175 pm UUID: a4779a63-c75e-4cae-b35e-c9a5861a68eb Ancestors: Zinc-Resource-Meta-Tests-monty.35 Extend the ZnUrl API a bit, for convenience: ZnUrl class>>#image returns a File URL to the current image (Thx Ben Coman) ZnUrl>>#+ as an alias for ZnUrl>>#withRelativeReference: ZnUrl>>#asFileUrl return a copy with the scheme changed to file:// ZnUrl>>#portIfAbsent: to handle missing ports Add some unit tests for the new API === Name: Zinc-Resource-Meta-FileSystem-SvenVanCaekenberghe.8 Author: SvenVanCaekenberghe Time: 19 May 2015, 4:32:04.050748 pm UUID: a84ff5a8-584c-4160-93f2-0f305679a9e0 Ancestors: Zinc-Resource-Meta-FileSystem-SvenVanCaekenberghe.7 Add ZnFileUrlTests>>#testImage === This does not change the current default behaviour, but it makes it a lot easier to work with relative references: ZnUrl image + 'foo.txt' => "file:///Users/sven/Develop/Smalltalk/foo.txt" You just have to choose an appropriate base URL: 'postgresql://user:password@localhost:5432/default' asUrl + 'test' => "postgresql://user:password@localhost:5432/test" However, when you override the host, the port (actually the whole authority) is reset as well (according to my interpretation of the RFC anyway), that is why I added #portIfAbsent: 'postgresql://production/user-db' asUrl portIfAbsent: 5432 => 5432 I also added #asFileUrl to help in the common case of interpreting any scheme as referring to a file path. After that conversion, one will probably want to do an #asFileReference.
But there is #withRelativeReference: which follows the relevant specs (check the tests).
FileReference should also deal better with platform issue, ZnURL is much more abstract, by definition.
I hope this makes sense ;-)
Now, having a look at what we can do with znurl
In windows it looks that we are ok 'sqlite3:///c:/myDirectory/myfile.db' asUrl path. "'c:/myDirectory/myfile.db'" 'sqlite3:///c:\myDirectory\myfile.db' asUrl path. "'c:\myDirectory\myfile.db'"
See also #testWindowsDriveNamesInFileUrl
But in linux even if I put extra slashes it keeps removing them... And it makes difficult to recognize relative from absolute file paths:
"Relative path c/myDirectory/myfile.db OK" 'sqlite3:///c/myDirectory/myfile.db' asUrl path. "'c/myDirectory/myfile.db'"
"Absolute path /c/myDirectory/myfile.db not OK" 'sqlite3:///c/myDirectory/myfile.db' asUrl path. "'c/myDirectory/myfile.db'"
Adding Slashes 'sqlite3:////////c/myDirectory/myfile.db' asUrl path. "'c/myDirectory/myfile.db'"
An intuitive semantic would be... ''sqlite3:///./c/myDirectory/myfile.db' asUrl pathPrintString "--> /my/pharoImagePath/c/myDirectory/myfile.db"
Another concern is that garage as it is works in Pharo 3, 4 and 5. Then if we update Zn I'll have to add Zn to my dependencies and load the correct version accordingly, what do you think? (I prefer that to back porting)
Just depend on the latest stable release of Zinc, it is (still) supported for 2.0 and up.
Guille
El lun., 18 de may. de 2015 a la(s) 11:27 a. m., Sven Van Caekenberghe <sven@stfx.eu> escribió: Hi Guile,
On 18 May 2015, at 10:48, Guillermo Polito <guillermopolito@gmail.com> wrote:
Well, I wanted in general to have a single easy-to-learn way to build a database connection string for all drivers.
[driverid]://[host][:port]/[databasename]?[properties]
Then, for sqlite I would like to have:
sqlite3://myDirectory/myfile.db
or
sqlite3://memory
Now, for Garage 0.1 I was using ZnUrl to parse the connection strings and that is not working for urls like the following because if the schema is not 'file' then the parser fails to to transform the port (an empty string in this case for the parser) to an integer
sqlite3://c:/myDirectory/myfile.db
In bleeding edge I am using an alternative parser that does no conversions and allows urls like that one.
I understand the reasoning here, but I would suggest that you at least consider changing your mind. Over time, a lot of work went into ZnUrl, and many people used it and helped fixing many problems. Recently we tried to improve the situation for special schemes a bit (for git URLs). We're not yet there, but you (your use case) could help improving the situation.
I tried to take a principled approach regarding the specs (not that there is one clear spec, haha), but edge cases should still be possible.
Consider the following:
'postgresql://localhost:14433/test-db?username=john&password=123456' asUrl. 'postgresql://john:123456@localhost:14433/test-db?encoding=utf8' asUrl. 'postgresql://localhost/default' asUrl.
'sqlite3:///myDirectory/myfile.db' asUrl. 'sqlite3://memory' asUrl.
Would memory have a hierarchical structure? i.e. if I wanted to run two sqllite3 instances in memory?
'sqlite3:///c:/myDirectory/myfile.db' asUrl.
According to me, these all parse correctly. Of course, ZnUrl does not know or understand what is possibly special about any particular scheme (apart from HTTP(S)). Still, it is just an object that can be manipulated.
The default port can be computed along the lines of #portOrDefault, maybe we could add a #portIfAbsent: ?
Conversion to a file references can be done as follows:
'sqlite3:///c:/myDirectory/myfile.db' asUrl copy scheme: #file; asFileReference.
Which basically reads as: 'I know this is not a file:// URL proper, still I want to interpret it as if it were one'. Maybe we could add a #forceAsFileReference ?
Anyway, you get the idea. You know I am willing to help.
Sven
Looking through Zinc I notice that the schemes are symbols. Any plans to make these classes? To maybe(?) make it easier to extend to other schemes (http://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml) ? Or do you consider that outside the scope of Zinc ?
Well, it is a 'problem area' (design/implementation wise). Your suggestion makes sense though: to make the schemes objects so that they could implement specific behaviour (rather than making many subclasses of ZnUrl). I will think about this, thanks for the idea ! Sven
cheers -ben