Skip to content

Commit

Permalink
Fix tests and impl
Browse files Browse the repository at this point in the history
  • Loading branch information
radeusgd committed Jul 19, 2022
1 parent 56b57ed commit 4688314
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from Standard.Base import all

from Standard.Base.Data.Numbers import Parse_Error

import Standard.Database.Data.Dialect
import Standard.Database.Connection.Connection
from Standard.Database.Connection.Credentials as Credentials_Module import Credentials
Expand All @@ -21,7 +23,7 @@ type PostgreSQL
- credentials: The credentials to use for the connection (defaults to PGPass or No Authentication).
- use_ssl: Whether to use SSL (defaults to `Prefer`).
- client_cert: The client certificate to use or `Nothing` if not needed.
type PostgreSQL (host:Text = Environment.get_or_else "PGHOST" "localhost") (port:Integer = Environment.get_or_else "PGPORT" 5432) (database:Text = Environment.get_or_else "PGDATABASE" "") (credentials:(Credentials|Nothing)=Nothing) (use_ssl:SSL_Mode=Prefer) (client_cert:(Client_Certificate|Nothing)=Nothing)
type PostgreSQL (host:Text=default_postgres_host) (port:Integer=default_postgres_port) (database:Text=default_postgres_database) (credentials:(Credentials|Nothing)=Nothing) (use_ssl:SSL_Mode=Prefer) (client_cert:(Client_Certificate|Nothing)=Nothing)

## Build the Connection resource.

Expand Down Expand Up @@ -83,3 +85,16 @@ ssl_mode_to_jdbc_properties use_ssl = case use_ssl of
Full_Verification cert_file ->
if cert_file.is_nothing then [Pair 'sslmode' 'verify-full'] else
[Pair 'sslmode' 'verify-full', Pair 'sslrootcert' (File.new cert_file).absolute.path]

## PRIVATE
default_postgres_host = Environment.get_or_else "PGHOST" "localhost"

## PRIVATE
default_postgres_port =
hardcoded_port = 5432
case Environment.get "PGPORT" of
Nothing -> hardcoded_port
port -> Integer.parse port . catch Parse_Error (_->hardcoded_port)

## PRIVATE
default_postgres_database = Environment.get_or_else "PGDATABASE" ""
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@ polyglot java import java.lang.StringBuilder as Java_String_Builder
- host: The hostname of the database server.
- port: The port of the database server.
- database: The database to connect to.
read : Text -> Integer -> Text -> [Pair Text Text]
read host port database =
read : Text -> Integer -> Text -> Text -> [Pair Text Text]
read host port database username=Nothing =
pgpass_file = locate
if pgpass_file.is_nothing || (verify pgpass_file . not) then [] else
entries = parse_file pgpass_file
# TODO possibly? determine username from env
found = entries.find entry->
entry.matches host port database
entry.matches host port database username
case found.catch Nothing of
Nothing -> []
entry -> [Pair 'user' entry.username, Pair 'password' entry.password]
Expand All @@ -51,7 +50,7 @@ type Pgpass_Entry
Text -> port
self.port==normalized_port
database_match = self.database==wildcard || self.database==database
username_match = username==Nothing || self.username==wildcard || self.username=username
username_match = username==Nothing || self.username==wildcard || self.username==username
host_match && port_match && database_match && username_match

## PRIVATE
Expand Down Expand Up @@ -98,7 +97,7 @@ parse_line line =
existing_entries.append current_entry.toString
current_entry.setLength 0
characters = line.characters
go ix is_escape = case ix>=line.length of
go ix is_escape = case ix>=characters.length of
True ->
if is_escape then
# Handle the trailing escape character.
Expand All @@ -110,19 +109,19 @@ parse_line line =
True ->
if is_escape then
current_entry.append '\\'
go (ix+1) is_escape.not
@Tail_Call go (ix+1) is_escape.not
False -> case c==':' of
True ->
case is_escape of
True -> current_entry.append ':'
False -> next_entry
go (ix+1) False
@Tail_Call go (ix+1) False
False ->
if is_escape then
# Handle escape character followed by other characters.
current_entry.append '\\'
# Any other character is just appended and escape is reset.
current_entry.append c
go (ix+1) False
@Tail_Call go (ix+1) False
go 0 False
existing_entries.to_vector
46 changes: 31 additions & 15 deletions test/Table_Tests/src/Database/Postgresql_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -202,43 +202,59 @@ connection_setup_spec = Test.group "[PostgreSQL] Connection setup" <|
c3.database . should_equal "ensoDB"
c3.jdbc_url . should_equal "jdbc:postgresql://192.168.0.1:1000/ensoDB"

## Currently we require the port to be numeric. When we support
Unix-sockets, we may lift that restriction.
c4 = Environment.unsafe_with_environment_override "PGPORT" "foobar" <|
PostgreSQL
c4.host . should_equal "localhost"
c4.port . should_equal 5432
c4.database . should_equal ""
c4.jdbc_url . should_equal "jdbc:postgresql://localhost:5432"

add_ssl props = props+[Pair 'sslmode' 'prefer']
Test.specify "should use the given credentials" <|
c = PostgreSQL credentials=(Credentials "myuser" "mypass")
c.jdbc_url . should_equal "jdbc:postgresql://localhost:5432"
c.jdbc_properties . should_equal [Pair "user" "myuser", Pair "password" "mypass"]
c.jdbc_properties . should_equal <| add_ssl [Pair "user" "myuser", Pair "password" "mypass"]

Test.specify "should fallback to environment variables and fill-out missing information based on the PGPASS file (if available)" <|
c1 = PostgreSQL
c1.jdbc_url . should_equal "jdbc:postgresql://localhost:5432"

c1.jdbc_properties . should_equal []
Environment.unsafe_with_environment_override "PGPASS" "somepassword" <|
c1.jdbc_properties . should_equal <| add_ssl []
Environment.unsafe_with_environment_override "PGPASSWORD" "somepassword" <|
c1.jdbc_properties . should_fail_with Illegal_State_Error
c1.jdbc_properties.catch.message . should_equal "PGPASSWORD is set, but PGUSER is not."

Environment.unsafe_with_environment_override "PGUSER" "someuser" <|
c1.jdbc_properties . should_equal [Pair "user" "someuser", Pair "password" "somepassword"]
c1.jdbc_properties . should_equal <| add_ssl [Pair "user" "someuser", Pair "password" "somepassword"]

c2 = PostgreSQL "192.168.4.0" 1234 "foo"
c3 = PostgreSQL "::1" 55999 "database_name"
c4 = PostgreSQL "::1" 55999 "otherDB"
c2.jdbc_properties . should_equal []
c3.jdbc_properties . should_equal []
c4.jdbc_properties . should_equal []
c2.jdbc_properties . should_equal <| add_ssl []
c3.jdbc_properties . should_equal <| add_ssl []
c4.jdbc_properties . should_equal <| add_ssl []

Environment.unsafe_with_environment_override "PGPASS" pgpass_file.absolute.path <|
c2.jdbc_properties . should_equal [Pair "user" "bar", Pair "password" "baz"]
c3.jdbc_properties . should_equal [Pair "user" "user_that_has_no_password", Pair "password" ""]
c4.jdbc_properties . should_equal [Pair "user" "*", Pair "password" "fallback_password"]
Environment.unsafe_with_environment_override "PGPASSFILE" pgpass_file.absolute.path <|
c2.jdbc_properties . should_equal <| add_ssl [Pair "user" "bar", Pair "password" "baz"]
c3.jdbc_properties . should_equal <| add_ssl [Pair "user" "user_that_has_no_password", Pair "password" ""]
c4.jdbc_properties . should_equal <| add_ssl [Pair "user" "*", Pair "password" "fallback_password"]

Environment.unsafe_with_environment_override "PGUSER" "bar" <|
c2.jdbc_properties . should_equal <| add_ssl [Pair "user" "bar", Pair "password" "baz"]
[c3, c4].each c->
c.jdbc_properties . should_equal <|
add_ssl [Pair "user" "*", Pair "password" "fallback_password"]

Environment.unsafe_with_environment_override "PGUSER" "other user" <|
c2.jdbc_properties . should_equal []
c3.jdbc_properties . should_equal []
c4.jdbc_properties . should_equal [Pair "user" "other user", Pair "password" "fallback_password"]
[c2, c3, c4].each c->
c.jdbc_properties . should_equal <|
add_ssl [Pair "user" "*", Pair "password" "fallback_password"]

Environment.unsafe_with_environment_override "PGPASSWORD" "other password" <|
[c2, c3, c4].each c->
c.jdbc_properties . should_equal [Pair "user" "other user", Pair "password" "other password"]
c.jdbc_properties . should_equal <| add_ssl [Pair "user" "other user", Pair "password" "other password"]

spec =
table_spec
Expand Down

0 comments on commit 4688314

Please sign in to comment.