# An experimental Julia library: copyout csv from postgresql using rust and Clang.jl

**URL:** https://discourse.julialang.org/t/an-experimental-julia-library-copyout-csv-from-postgresql-using-rust-and-clang-jl/121100
**Category:** New to Julia
**Created:** [October 9, 2024, 9:57am UTC](https://discourse.julialang.org/t/an-experimental-julia-library-copyout-csv-from-postgresql-using-rust-and-clang-jl/121100 "2024-10-09T09:57:53Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![bluebug](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bluebug/32/212160_2.png) [@bluebug](https://discourse.julialang.org/u/bluebug)
#### Post date: [October 9, 2024, 9:57am UTC](https://discourse.julialang.org/t/an-experimental-julia-library-copyout-csv-from-postgresql-using-rust-and-clang-jl/121100/1 "2024-10-09T09:57:54Z")

</div>

copyout csv from postgresql, using rust postgres/cbindgen and Clang.jl to interop rust and julia together, without jirs.

Any suggestions for sharing complex data structures from Rust to Julia? like:

```rust
#[repr(C)]
pub enum DTypes {
    I8 = 0,
    I32 = 1,
    I64 = 2,
    F32 = 3,
    F64 = 4,
    Str = 5,
}

#[repr(C)]
pub struct DFrame {
    pub width: u32,
    pub height: u32,
    pub fields: *mut *const u8, // field names
    pub types: *mut DTypes, // field types
    pub values: *mut *const c_void, // field values
}

```

### Purpose:

Use the rust postgres library to generate a postgresql client that can be quickly imported, and provide a copyout method to quickly obtain csv results.

### Prerequisites:

1. Rust environment
2. Julia environment with Clang.jl
3. Postgresql database
4. Modify the database link and test code in build.jl

### Compile method:

using global julia env

1. build step by step

```julia
include("build.jl")

build_rs()
build_jl()
test()

```

1. or build once

```cmd
julia build.jl

```

### howto:

Refer to the test code in build.jl

### changelog:

- 2024-10-09 v0.1.1:

- 2024-10-03 v0.1.0: initial version  
[https://github.com/bluebug/libpq\_rsjl](https://source)

---

<div class="post-metadata">

### Author: ![bluebug](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bluebug/32/212160_2.png) [@bluebug](https://discourse.julialang.org/u/bluebug)
#### Post date: [October 10, 2024, 3:19pm UTC](https://discourse.julialang.org/t/an-experimental-julia-library-copyout-csv-from-postgresql-using-rust-and-clang-jl/121100/2 "2024-10-10T15:19:16Z")

</div>

- 2024-10-10 v0.2.0:
  - add pq\_query\_native(rs)/pq\_query(jl) function to get dframe from postgresql
  - add pq\_free\_dframe(rs) function to release dframe, but not sure if the rust code releases the memory correctly💣
  - add test code for dframe in build.jl
  - call unsafe\_string only when call copyout.body

help need:

how to view `Cstring` without copy? using `unsafe_string` causing copy.

```julia
unsafe_string(s:Cstring)

```

---

<div class="post-metadata">

### Author: ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)
#### Post date: [October 10, 2024, 6:08pm UTC](https://discourse.julialang.org/t/an-experimental-julia-library-copyout-csv-from-postgresql-using-rust-and-clang-jl/121100/3 "2024-10-10T18:08:00Z")

</div>

I think you can use VectorStrings.jl for that!

---

<div class="post-metadata">

### Author: ![bluebug](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bluebug/32/212160_2.png) [@bluebug](https://discourse.julialang.org/u/bluebug)
#### Post date: [October 11, 2024, 7:17am UTC](https://discourse.julialang.org/t/an-experimental-julia-library-copyout-csv-from-postgresql-using-rust-and-clang-jl/121100/4 "2024-10-11T07:17:11Z")

</div>

Thanks, according to your suggestion, I found the library StringViews.jl, and now I can view CString without copying.

```julia
using StringViews

Base.length(cs::Cstring) = ccall(:strlen, Cint, (Cstring,), cs)
CStringView(cs::Cstring) = StringView(unsafe_wrap(Array, Ptr{UInt8}(cs), length(cs)))
Base.write(io::IO, cs::Cstring) = write(io, CStringView(cs))
Base.print(io::IO, cs::Cstring) = (write(io, CStringView(cs)); nothing)
Base.show(io::IO, cs::Cstring) = (write(io, CStringView(cs)); nothing)

Base.length(cs::Ptr{UInt8}) = ccall(:strlen, Cint, (Ptr{UInt8},), cs)
CStringView(cs::Ptr{UInt8}) = StringView(unsafe_wrap(Array, cs, length(cs)))
Base.write(io::IO, cs::Ptr{UInt8}) = write(io, CStringView(cs))
Base.print(io::IO, cs::Ptr{UInt8}) = (write(io, CStringView(cs)); nothing)
Base.show(io::IO, cs::Ptr{UInt8}) = (write(io, CStringView(cs)); nothing)

export CStringView

```
