Diesel: [question] why diesel mysql does not support connection to Unix domain socket?

Created on 25 Mar 2020  路  14Comments  路  Source: diesel-rs/diesel

diesel mysql supports only database url of form mysql://host[:port] yet.

https://github.com/diesel-rs/diesel/blob/00f7de703aea02659bddad8d168b9fe6d4aee276/diesel/src/mysql/connection/url.rs#L92-L98

Is there any reason socket connection is excluded?

Most helpful comment

Because anything else is just not implemented yet, probably because nobody asked for it. I think we would be happily taking a PR changing this.

All 14 comments

Because anything else is just not implemented yet, probably because nobody asked for it. I think we would be happily taking a PR changing this.

Hi @p-alik ,

It seems that the MySQL client library (used by diesel) already caters for the use of Unix sockets within the constrains of the URL syntax accepted by diesel: https://dev.mysql.com/doc/refman/5.7/en/mysql-real-connect.html

I've successfully connected to a MySQL service listening only on Unix socket by:

  • Leaving the TCP port out of the URL (e.g. mysql://\
  • Defining the MYSQL_UNIX_PORT environment variable with the full path of the socket file (e.g. /var/run/mysqld/mysqld.sock)

I hope this helps.

Hi @alfonso-eusebio,
as mentioned in mysql_real_connect documentation:

  • If host is NULL or the string "localhost", a connection to the local host is assumed:

    • On Unix, the client connects using a Unix socket file. The unix_socket parameter or the MYSQL_UNIX_PORT environment variable may be used to specify the socket name.

So I guess there is no need to provide MYSQL_UNIX_PORT at all, if connecting to localhost.

I'm working on a PR for the issue. My aim is to provide socket path via DATABASE_URL in slightly different form:
DATABASE_URL="file:///var/run/mysqld/mysqld.sock;username=foo;password=bar;database=your-db". But maybe the form should be discussed.

I'm not sure if introducing a new url scheme is really the right way to go here. For example postgres/libpq has choosen the following way: postgresql://%2Fvar%2Flib%2Fpostgresql/dbname, so we should probably go with something similar here.
Beside of that I think specifying username, password and other params should follow the normal pattern scheme://user:password@host?param1=foo&param2=bar

Thank you for your feedback, @weiznich!

Beside of that I think specifying username, password and other params should follow the normal pattern scheme://user:password@host?param1=foo&param2=bar

I'm afraid url crate, or underlying specification, doesn't support the syntax for file scheme. Even result of postgresql://%2Fvar%2Flib%2Fpostgresql/dbname looks strange to me because it interpret %2Fvar ... as a host Some("%2Fvar%2Flib%2Fpostgresql").
See playground

Some("%2Fvar%2Flib%2Fpostgresql") is just the url encoded string for /var/lib/postgresql. It seems like it is possible to combine that with the normal user:password syntax.
See the following playground

@weiznich, I meant "%2Fvar%2Flib%2Fpostgresql" doesn't look like a valid host representation.
But maybe it is a valid opaque host defined in Hosts (domains and IP addresses) specification. The specification contains an empty host.
What do you think about following url "mysql://user:password@''/var/run/mysqld.sock?database=dbname"? It seems to be much readable to me. I added it into playground code.

Another possibility would be to just allow setting the path to the socket file via a seperate query parameter: mysql://user:password@host?unix_socket=/path/to/socket&database=dbname and just specify/document if that parameter is present the unix socket file is used instead a tcp socket. I think I would prefer this variant.

The last one looks very good to me also.

should query_paris be validated it contains only subset of database and unix_socket?

What's the current behaviour here? Does the current implementation allow arbitrary query parameters here? If so we should continue to allow that, if not we should check that it only contains unix_socket (Just seen that database is part of the path in the old implementation, that should be the case for the new one too.)

how to deal with two database values?

As written above: I've just noticed that this can happen. I would just say that we continue to not allow passing a database value as query parameter, so this just cannot happen (Sorry for not seeing this earlier)

how to set host to None in order to connect over socket only?

I would just document that host needs to be localhost if a unix_socket should be used and maybe check that in the implementation. That makes the url much more readable, than skipping the host part.

should query_paris be validated it contains only subset of database and unix_socket?

What's the current behaviour here? Does the current implementation allow arbitrary query parameters here? If so we should continue to allow that, if not we should check that it only contains unix_socket (Just seen that database is part of the path in the old implementation, that should be the case for the new one too.)

Current implementation doesn't validate query parameters at all. Hence I'll add a lookup for unix_socket only.

how to deal with two database values?

As written above: I've just noticed that this can happen. I would just say that we continue to not allow passing a database value as query parameter, so this just cannot happen (Sorry for not seeing this earlier)

OK

how to set host to None in order to connect over socket only?

I would just document that host needs to be localhost if a unix_socket should be used and maybe check that in the implementation. That makes the url much more readable, than skipping the host part.

Unfortunately passing localhost wouldn't work for instance if you'll connect to a mysqld running in sandbox, which listen on it's own unix_socket. My intention is to set
https://github.com/diesel-rs/diesel/blob/00f7de703aea02659bddad8d168b9fe6d4aee276/diesel/src/mysql/connection/url.rs#L11
property to None in order to pass std::ptr::null_mut() to mysql_real_connect https://github.com/diesel-rs/diesel/blob/00f7de703aea02659bddad8d168b9fe6d4aee276/diesel/src/mysql/connection/raw.rs#L53

Unfortunately passing localhost wouldn't work for instance if you'll connect to a mysqld running in sandbox, which listen on it's own unix_socket. My intention is to set

localhost is just a placeholder in this case, it should not be really used to connect to the database. So basically internally threat the occurrence of unix_socket + some host in such a way that unix_socket is Some and host is None.

Fixed by #2372

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Fuckoffee picture Fuckoffee  路  3Comments

orionz picture orionz  路  3Comments

jimmycuadra picture jimmycuadra  路  3Comments

ivan picture ivan  路  4Comments

pjenvey picture pjenvey  路  4Comments