Skip to content

Commit 3ec2ab0

Browse files
committed
From start to connection info
1 parent 8b53669 commit 3ec2ab0

File tree

4 files changed

+1053
-1
lines changed

4 files changed

+1053
-1
lines changed

README.md

+70
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,76 @@
11
# LibPQ
22

3+
LibPQ.jl is a Julia wrapper for the PostgreSQL `libpq` C library.
4+
35
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://iamed2.github.io/LibPQ.jl/stable)
46
[![Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://iamed2.github.io/LibPQ.jl/latest)
57
[![Build Status](https://travis-ci.org/iamed2/LibPQ.jl.svg?branch=master)](https://travis-ci.org/iamed2/LibPQ.jl)
68
[![CodeCov](https://codecov.io/gh/iamed2/LibPQ.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/iamed2/LibPQ.jl)
9+
10+
## Features
11+
12+
### Goals
13+
14+
*Note that these are goals and do not represent the current state of this package*
15+
16+
LibPQ.jl aims to wrap `libpq` as documented in the PostgreSQL documentation, including all non-deprecated functionality and handling all documented error conditions.
17+
Where possible, asynchronous functionality will be wrapped in idiomatic Julia control flow.
18+
All Oids returned in query results will have type conversions defined, as long as I can find documentation on their structure.
19+
Some effort will be made to integrate with other packages (e.g., [https://github.com/JuliaData/DataStreams.jl](DataStreams.jl)) to facilitate conversion from query results to a malleable format.
20+
21+
Above all, I am doing this for fun and I do not expect to hold this package to any particular standard of completeness or support.
22+
23+
### Non-Goals
24+
25+
LibPQ.jl will not attempt to conform to a standard database interface, though anyone is welcome to write a PostgreSQL.jl library to wrap this package.
26+
27+
This package will not:
28+
29+
* parse SQL
30+
* emit SQL
31+
* provide an interface for handling transactions or cursors
32+
* provide abstractions over common SQL patterns
33+
34+
### Possible Goals
35+
36+
This package may not:
37+
38+
* install libpq or PostgreSQL
39+
* test on multiple install configurations
40+
* aim to support any particular versions of libpq or PostgreSQL
41+
* support conversion from some Oid to some type
42+
* provide easy access to every possible connection method
43+
* be as memory-efficient as possible (memory-safety will be prioritized)
44+
45+
While I may never get to any of these, I welcome tested, documented contributions!
46+
47+
## Licenses
48+
49+
### `libpq` Source and PostgreSQL Documentation
50+
51+
```
52+
PostgreSQL is Copyright © 1996-2017 by the PostgreSQL Global Development Group.
53+
54+
Postgres95 is Copyright © 1994-5 by the Regents of the University of California.
55+
56+
Permission to use, copy, modify, and distribute this software and its
57+
documentation for any purpose, without fee, and without a written agreement is
58+
hereby granted, provided that the above copyright notice and this paragraph
59+
and the following two paragraphs appear in all copies.
60+
61+
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
62+
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
63+
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
64+
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
65+
SUCH DAMAGE.
66+
67+
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
68+
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
69+
A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN “AS-IS” BASIS,
70+
AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
71+
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
72+
```
73+
74+
### Everything Else
75+
76+
The license for the remainder of this package appears in [LICENSE](./LICENSE).

deps/wrap.jl

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
ENV["PATH"] = "/usr/local/opt/llvm/bin:$(ENV["PATH"])"
2+
3+
using Clang
4+
5+
cd(Pkg.dir("LibPQ", "src", "headers"))
6+
7+
context = wrap_c.init(;
8+
clang_includes=["/usr/local/opt/libpq/include"],
9+
common_file="libpq_common.jl",
10+
)
11+
12+
context.headers = [
13+
"/usr/local/opt/libpq/include/libpq-fe.h",
14+
]
15+
16+
run(context)

src/LibPQ.jl

+90-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,94 @@
11
module LibPQ
22

3-
# Package code goes here.
3+
module libpq_c
4+
function __init__()
5+
const global LIBPQ_HANDLE = :libpq
6+
end
7+
8+
include(joinpath(@__DIR__, "headers", "libpq-fe.jl"))
9+
end
10+
11+
@enum ConninfoDiplay Normal Password Debug
12+
13+
function Base.parse(::Type{ConninfoDiplay}, str::AbstractString)::ConninfoDiplay
14+
if length(str) < 1
15+
Normal
16+
elseif first(str) == '*'
17+
Password
18+
elseif first(str) == 'D'
19+
Debug
20+
else
21+
error("Unexpected dispchar in PQconninfoOption")
22+
end
23+
end
24+
25+
function unsafe_nullable_string(ptr::Cstring)::Nullable{String}
26+
ptr == C_NULL ? Nullable() : unsafe_string(ptr)
27+
end
28+
29+
struct ConnectionOption
30+
keyword::String
31+
envvar::Nullable{String}
32+
compiled::Nullable{String}
33+
val::Nullable{String}
34+
label::String
35+
disptype::ConninfoDiplay
36+
dispsize::Int
37+
end
38+
39+
function ConnectionOption(pq_opt::libpq_c.PQconninfoOption)
40+
ConnectionOption(
41+
unsafe_string(pq_opt.keyword),
42+
unsafe_nullable_string(pq_opt.envvar),
43+
unsafe_nullable_string(pq_opt.compiled),
44+
unsafe_nullable_string(pq_opt.val),
45+
unsafe_string(pq_opt.label),
46+
parse(ConninfoDiplay, unsafe_string(pq_opt.dispchar)),
47+
pq_opt.dispsize,
48+
)
49+
end
50+
51+
struct Connection
52+
conn::Ptr{libpq_c.PGconn}
53+
end
54+
55+
function Connection(str::AbstractString)
56+
Connection(libpq_c.PQconnectdb(str))
57+
end
58+
59+
function conninfo(jl_conn::Connection)
60+
ci_array = Vector{ConnectionOption}()
61+
62+
ci_ptr = libpq_c.PQconninfo(jl_conn.conn)
63+
ci_ptr == C_NULL && error("libpq could not allocate memory for connection info")
64+
65+
ci_opt_idx = 1
66+
ci_opt = unsafe_load(ci_ptr, ci_opt_idx)
67+
while ci_opt.keyword != C_NULL
68+
push!(ci_array, ConnectionOption(ci_opt))
69+
70+
ci_opt_idx += 1
71+
ci_opt = unsafe_load(ci_ptr, ci_opt_idx)
72+
end
73+
74+
libpq_c.PQconninfoFree(ci_ptr)
75+
76+
return ci_array
77+
end
78+
79+
function Base.show(io::IO, jl_conn::Connection)
80+
print("PostgreSQL connection with parameters:")
81+
for ci_opt in conninfo(jl_conn)
82+
if !isnull(ci_opt.val) && ci_opt.disptype != Debug
83+
print("\n ", ci_opt.keyword, " = ")
84+
85+
if ci_opt.disptype == Password
86+
print("*" ^ ci_opt.dispsize)
87+
else
88+
print(get(ci_opt.val))
89+
end
90+
end
91+
end
92+
end
493

594
end

0 commit comments

Comments
 (0)