diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e978134..3c911dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ on: branches: [main] tags: ["*"] pull_request: + concurrency: group: ${{ github.workflow }}-${{ github.ref || github.run_id }} cancel-in-progress: true @@ -46,6 +47,15 @@ jobs: ${{ runner.os }}- - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + env: + POSTGRES_USER: ${{ secrets.POSTGRES_USER }} + POSTGRES_HOST: ${{ secrets.POSTGRES_HOST }} + POSTGRES_PORT: ${{ secrets.POSTGRES_PORT }} + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} + MYSQL_USER: ${{ secrets.MYSQL_USER }} + MYSQL_HOST: ${{ secrets.MYSQL_HOST }} + MYSQL_PORT: ${{ secrets.MYSQL_PORT }} + MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }} - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: diff --git a/.github/workflows/invalidations.yml b/.github/workflows/invalidations.yml deleted file mode 100644 index af4c158..0000000 --- a/.github/workflows/invalidations.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Invalidations - -on: - pull_request: - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: always. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - evaluate: - # Only run on PRs to the default branch. - # In the PR trigger above branches can be specified only explicitly whereas this check should work for master, main, or any other default branch - if: github.base_ref == github.event.repository.default_branch - runs-on: ubuntu-latest - steps: - - uses: julia-actions/setup-julia@v1 - with: - version: '1' - - uses: actions/checkout@v3 - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-invalidations@v1 - id: invs_pr - - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.repository.default_branch }} - - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-invalidations@v1 - id: invs_default - - - name: Report invalidation counts - run: | - echo "Invalidations on default branch: ${{ steps.invs_default.outputs.total }} (${{ steps.invs_default.outputs.deps }} via deps)" >> $GITHUB_STEP_SUMMARY - echo "This branch: ${{ steps.invs_pr.outputs.total }} (${{ steps.invs_pr.outputs.deps }} via deps)" >> $GITHUB_STEP_SUMMARY - - name: Check if the PR does increase number of invalidations - if: steps.invs_pr.outputs.total > steps.invs_default.outputs.total - run: exit 1 \ No newline at end of file diff --git a/Project.toml b/Project.toml index e73cf82..4f93717 100644 --- a/Project.toml +++ b/Project.toml @@ -1,16 +1,18 @@ name = "DBConnector" uuid = "5242bac9-aa14-4800-b46b-fcd14df13057" -version = "1.0.0" +authors = ["Jacob Zelko ", "Fareeda Abdelazeez"] +version = "0.1.0" [deps] DBInterface = "a10d1c49-ce27-4219-8d33-6db1a4562965" -JDBC = "6042db11-3c3d-5e84-8dba-9cbf74c9ba48" LibPQ = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1" MySQL = "39abe10b-433b-5dbd-92d4-e302a9df00cd" -ODBC = "be6f12e9-ca4f-5eb2-a339-a4f995cc0291" SQLite = "0aa819cd-b072-5ff4-a722-6bc24af294d9" [compat] +DBInterface = "2.5" +LibPQ = "1.15" +SQLite = "1.6" julia = "1.6" [extras] diff --git a/docs/make.jl b/docs/make.jl index fd29b00..38198fe 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,5 +1,32 @@ -using Documenter, Example +using DBConnector +using Documenter -makedocs(modules = [Example], sitename = "Example.jl") +makedocs(; + modules = [DBConnector], + authors = "Jacob Zelko (aka TheCedarPrince) and contributors", + repo = "https://github.com/JuliaHealth/DBConnector.jl/blob/{commit}{path}#L{line}", + sitename = "DBConnector.jl", + format = Documenter.HTML(; + prettyurls = get(ENV, "CI", "false") == "true", + canonical = "https://JuliaHealth.github.io/DBConnector.jl", + assets = String[], + edit_link = "dev", + footer = "Created by [Jacob Zelko](https://jacobzelko.com) & [Georgia Tech Research Institute](https://www.gtri.gatech.edu). [License](https://github.com/JuliaHealth/OMOPCDMCohortCreator.jl/blob/main/LICENSE)" + ), + pages = [ + "Home" => "index.md", + "Tutorials" => [ + "SQLite.md", + "MySQL.md", + "postgreSQL.md" + ], + "API" => "api.md", + "Contributing" => "contributing.md" + ], +) -deploydocs(repo = "github.com/quinnj/Example.jl.git", push_preview = true) +deploydocs(; + repo = "github.com/JuliaHealth/DBConnector.jl", + push_preview = true, + devbranch = "main", +) \ No newline at end of file diff --git a/docs/src/Tutorials/MySQL.md b/docs/src/Tutorials/MySQL.md new file mode 100644 index 0000000..66a5315 --- /dev/null +++ b/docs/src/Tutorials/MySQL.md @@ -0,0 +1,73 @@ +# MySQL Connection Tutorial + +```@contents +Pages = ["MySQL.md"] +``` + +This tutorial presents a step by step guide on using DBConnector to connect a MySQL database. + +### Prerequisites + +Basic knowledge of Julia (such as installing packages into environments and working with the Julia REPL and Julia files) is necessary; you can learn all [that here](https://pkgdocs.julialang.org/v1/getting-started/). + +Get your database's : + + 1- username + 2- password + 3- host + 5- Database name + + optional: + - port (3306 by default) + - unix_socket + - client_flag + - opts=opts + + +## Environment Set-Up + +For this tutorial, you will need to activate an environment; to get into package mode within your Julia REPL, write `]`: + +```julia-repl +pkg> activate TUTORIAL +``` + + +### Packages + + + +You will need the following packages for this tutorial which you can install in package mode: + +"]" sets package mode + +```julia-repl +TUTORIAL> add DBConnector +``` + +"Backspace" to return to Julia mode + +``` +using DBConnector + +conn= _dbconnect(MySQL.Connection, host, user, password, db=db) + +``` +In case you want to use the optional strings: + +``` +using DBConnector + +conn= _dbconnect(MySQL.Connection, host, user, password, db="the database name", port = 3306, unix_socket=unix_socket, client_flag=client_flag, opts=opts ) + +``` + +Now you are connected! + +Note: It produces error only in case the path is incorrect credentials + +### Packages Used in Analysis + +Package descriptions: + +- [`SQLite`](https://github.com/JuliaDatabases/SQLite.jl) - A Julia interface to the SQLite library \ No newline at end of file diff --git a/docs/src/Tutorials/SQLite.md b/docs/src/Tutorials/SQLite.md new file mode 100644 index 0000000..81e9a07 --- /dev/null +++ b/docs/src/Tutorials/SQLite.md @@ -0,0 +1,49 @@ +# SQLite Connection Tutorial + +```@contents +Pages = ["SQLite.md"] +``` + +This tutorial presents a step by step guide on using DBConnector to connect a SQLite database. + +### Prerequisites + +Basic knowledge of Julia (such as installing packages into environments and working with the Julia REPL and Julia files) is necessary; you can learn all [that here](https://pkgdocs.julialang.org/v1/getting-started/). + +Get your database's file path + +## Environment Set-Up + +For this tutorial, you will need to activate an environment; to get into package mode within your Julia REPL, write `]`: + +```julia-repl +pkg> activate TUTORIAL +``` + + +### Packages + + + +You will need the following packages for this tutorial which you can install in package mode: + +"]" sets package mode + +```julia-repl +TUTORIAL> add DBConnector +``` + +"Backspace" to return to Julia mode + +``` +conn= _dbconnect(SQLite.DB, "../test/data/sqlite.db") +``` +Now you are connected! and if the file wasn't exist it will be created! + +Note: It produces error only in case the path is incorrect + +### Packages Used in Analysis + +Package descriptions: + +- [`SQLite`](https://github.com/JuliaDatabases/SQLite.jl) - A Julia interface to the SQLite library \ No newline at end of file diff --git a/docs/src/Tutorials/postgreSQL.md b/docs/src/Tutorials/postgreSQL.md new file mode 100644 index 0000000..c427fae --- /dev/null +++ b/docs/src/Tutorials/postgreSQL.md @@ -0,0 +1,84 @@ +# PostgreSQL Connection Tutorial + +```@contents +Pages = ["PostgreSQL.md"] +``` + +This tutorial presents a step by step guide on using DBConnector to connect to PostgreSQL database using LibPQ library. + +### Prerequisites + +Basic knowledge of Julia (such as installing packages into environments and working with the Julia REPL and Julia files) is necessary; you can learn all [that here](https://pkgdocs.julialang.org/v1/getting-started/). + +Get your database's : + + 1- username + 2- password + + + optional: + - host + - Database name + - port (5432 by default) + +Note: If you have additional keys that are necessary to be added, Jump to Method 2: + +## Environment Set-Up + +For this tutorial, you will need to activate an environment; to get into package mode within your Julia REPL, write `]`: + +```julia-repl +pkg> activate TUTORIAL +``` + + +### Packages + + + +You will need the following packages for this tutorial which you can install in package mode: + +"]" sets package mode + +```julia-repl +TUTORIAL> add DBConnector +``` + +"Backspace" to return to Julia mode + +``` +using DBConnector + +conn= _dbconnect(LibPQ.Connection; host = host, user = user, password = password, db=db) + +``` +In case you want to use the optional strings: + +``` +using DBConnector + +conn= _dbconnect(LibPQ.Connection; host = host, user = user, password = password, db="the database name", port = 5432) + +``` + + + +Now you are connected! + +Note: It produces error only in case the path is incorrect credentials + +# Method 2 + +create your own connection string as this example: + +``` +connection_string = "postgresql://username:password@unix:/path/to/socket/directory/database_name" + +conn= _dbconnect(LibPQ.Connection, connection_string) +``` + +### Packages Used in Analysis + +Package descriptions: + +- [LibPQ](https://github.com/chris-b1/LibPQ.jl#dbinterface) - A Julia interface to the LibPQ library \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md index b1cee35..b29e1e4 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,7 +1,18 @@ -# Example +# Welcome to the `DBConnector.jl` Docs + +> Get your credentials and connect to databases in one step with DBConnector! + + +To get started, visit the section as well as visit the visit the [Tutorials](@ref) section to see all the functions available. +If you want to contribute, please check out our guide! + +## Main Features 🔧 + +The biggest features of this package are: + + - "SQLite" functions [SQLite](@ref) a database + - "MySQL" functions to [MySQL](@ref) a database + - "PostgreSQL" functions to [postgreSQL](@ref) database connections + -Example Julia package repo. -```@autodocs -Modules = [Example] -``` diff --git a/docs/src/tutorials.md b/docs/src/tutorials.md new file mode 100644 index 0000000..a8a4cff --- /dev/null +++ b/docs/src/tutorials.md @@ -0,0 +1,11 @@ +# Tutorials + +```@contents +Pages = ["tutorials.md"] +``` + +These tutorials are designed to equip new users with how to get started with DBConnector + + - "SQLite" functions [SQLite](@ref) a database + - "MySQL" functions to [MySQL](@ref) a database + - "PostgreSQL" functions to [postgreSQL](@ref) database connections \ No newline at end of file diff --git a/src/DBConnector.jl b/src/DBConnector.jl index 2fa46b1..48efeb2 100644 --- a/src/DBConnector.jl +++ b/src/DBConnector.jl @@ -3,15 +3,12 @@ module DBConnector using DBInterface using LibPQ using SQLite -using ODBC -using JDBC using MySQL +import MySQL: API include("postgresql.jl") include("sqlite.jl") include("mysql.jl") -include("odbc.jl") -include("jdbc.jl") function DBConnection(dbms; kws...) @@ -25,17 +22,6 @@ function DBConnection(dbms; kws...) end -function DBConnection(;driver_path, connection_string, connectivity, kws...) - - if lowercase(connectivity) == "odbc" - _odbcconnect(connection_string, ; kws...) - elseif lowercase(connectivity) == "jdbc" - _jdbcconnect(driver_path, connection_string, ; kws...) - else - println("Connection not made; please specify if this is an JDBC or ODBC connection") - end -end - export DBConnection end diff --git a/src/jdbc.jl b/src/jdbc.jl deleted file mode 100644 index 1627904..0000000 --- a/src/jdbc.jl +++ /dev/null @@ -1,36 +0,0 @@ -""" -Dispatch for JDBC interface to DBInterface `connect` function -""" -function DBInterface.connect(::Type{JDBC.Connection}, args...; connection_string, driver, kws...) - JDBC.usedriver(driver) - try - JDBC.init() - catch - println("JVM already initialized") - end - JDBC.Connection(connection_string) -end - -""" -Dispatch for LibPQ interface to DBInterface `prepare` function -TODO: Not fully implemented yet -""" -# DBInterface.prepare(conn::JDBC.Connection, args...; kws...) = -# JDBC.prepareStatement(conn, args...; kws...) - -""" -Workaround for LibPQ interface to DBInterface's `execute` function -""" -function DBInterface.execute(conn::Union{JDBC.Connection, JDBC.JPreparedStatement}, args...; kws...) - csr = JDBC.cursor(conn) - JDBC.execute!(csr, args..., kws...) - JDBC.Source(csr) -end - - -function _jdbcconnect(driver_path, connection_string; kws...) - - return DBInterface.connect(JDBC.Connection, driver = driver_path, connection_string = connection_string) - -end - diff --git a/src/mysql.jl b/src/mysql.jl index 151c87e..70a0e17 100644 --- a/src/mysql.jl +++ b/src/mysql.jl @@ -1,5 +1,87 @@ -function _dbconnect(conn_obj::Type{MySQL.Connection}, kwargs) +function _dbconnect(conn_obj::Type{MySQL.Connection}; kwargs...) - return DBInterface.connect(conn_obj; kwargs...) + if haskey(kwargs, :host) && haskey(kwargs, :user) + host = kwargs[:host] + kwargs = filter(kvp -> first(kvp) != :host, kwargs) + user = kwargs[:user] + kwargs = filter(kvp -> first(kvp) != :user, kwargs) + if isempty(kwargs) + return DBInterface.connect(conn_obj,host, user) + elseif haskey(kwargs, :password) + password=kwargs[:password] + kwargs = filter(kvp -> first(kvp) != :password, kwargs) + if isempty(kwargs) + return DBInterface.connect(conn_obj,host, user, password) + elseif haskey(kwargs, :db) + db = kwargs[:db] + kwargs = filter(kvp -> first(kvp) != :db, kwargs) + if isempty(kwargs) + return DBInterface.connect(conn_obj,host, user, password; kwargs) + elseif haskey(kwargs, :port) + db = kwargs[:port] + kwargs = filter(kvp -> first(kvp) != :port, kwargs) + if isempty(kwargs) + return DBInterface.connect(conn_obj,host, user; kwargs) + end + end + end + elseif haskey(kwargs, :db) + db = kwargs[:db] + kwargs = filter(kvp -> first(kvp) != :db, kwargs) + if isempty(kwargs) + return DBInterface.connect(conn_obj,host, user; kwargs) + elseif haskey(kwargs, :port) + db = kwargs[:port] + kwargs = filter(kvp -> first(kvp) != :port, kwargs) + if isempty(kwargs) + return DBInterface.connect(conn_obj,host, user; kwargs) + end + end + end + + else + error("Invalid arguments, make sure that keyword user and host exists") + end +end + + # if !haskey(kwargs, "unix_socket") + # unix_socket = API.MYSQL_DEFAULT_SOCKET + # kwargs.push(unix_socket) + #end +""" + if haskey(kwargs, :host) + + host = kwargs[:host] + kwargs = filter(kvp -> first(kvp) != :host, kwargs) + if haskey(kwargs, :user) + user = kwargs[:user] + kwargs = filter(kvp -> first(kvp) != :user, kwargs) + elseif haskey(kwargs, :username) + user = kwargs[:username] + kwargs = filter(kvp -> first(kvp) != :username, kwargs) + else + error("Invalid arguments, make sure that keyword user exists") + end + else + error("Invalid arguments, make sure that keyword host exists") + end + if haskey(kwargs, :password) + password=kwargs[:password] + kwargs = filter(kvp -> first(kvp) != :password, kwargs) + elseif isempty(kwargs) + return DBInterface.connect(conn_obj,host, user) + else + return DBInterface.connect(conn_obj,host, user; kwargs) + end + if isempty(kwargs) + return DBInterface.connect(conn_obj,host, user, password) + else + + return DBInterface.connect(conn_obj,host, user, password; kwargs) + + end + return DBInterface.connect(conn_obj; kwargs...) + #return DBInterface.connect(conn_obj,host, user, password, db=db, port=port, unix_socket=unix_socket, client_flag=client_flag, opts=opts ) end +""" \ No newline at end of file diff --git a/src/odbc.jl b/src/odbc.jl deleted file mode 100644 index 5f77785..0000000 --- a/src/odbc.jl +++ /dev/null @@ -1,11 +0,0 @@ -function _odbcconnect(driver_path; kwargs...) - - ODBC.adddriver("DBDRIVER", driver_path) - conn_string = "Driver=DBDRIVER;" - for k in kwargs - conn_string = conn_string * "$(string(k.first))=$(k.second);" - end - - return DBInterface.connect(ODBC.Connection, conn_string[1:end-1]) - -end diff --git a/src/postgresql.jl b/src/postgresql.jl index 7eb6293..9be12e3 100644 --- a/src/postgresql.jl +++ b/src/postgresql.jl @@ -1,26 +1,88 @@ +""" +Workaround for LibPQ interface to DBInterface's `prepare` function; not supported in LibPQ.jl package currently +""" +DBInterface.prepare(conn::LibPQ.Connection, args...; kws...) = + LibPQ.prepare(conn, args...; kws...) + + """ Dispatch for LibPQ interface to DBInterface `connect` function; not supported in LibPQ.jl package currently """ DBInterface.connect(::Type{LibPQ.Connection}, args...; kws...) = LibPQ.Connection(args...; kws...) + """ + This LibPQ connection function creates a connection string using + 1- username (user) + 2- hostname (host) + 3- password + 4- database (db) + 5- port + + Cases handles: + 1- user and host + 2- user, host, db + 3- user, host, password + 4- user, host, password, db + 5- user, host, password, db, port + 6- user, host, db, port + + adding other keywords can't be handled yet + """ + function _dbconnect(conn_obj::Type{LibPQ.Connection}; kwargs...) - conn_string = "" - for k in kwargs - conn_string = conn_string * "$(string(k.first))=$(k.second) " - end - - conn_string = strip(conn_string) - return DBInterface.connect(conn_obj, conn_string) + if haskey(kwargs, :host) && haskey(kwargs, :user) + host = kwargs[:host] + kwargs = filter(kvp -> first(kvp) != :host, kwargs) + user = kwargs[:user] + kwargs = filter(kvp -> first(kvp) != :user, kwargs) + if isempty(kwargs) + conn_string = "postgresql://$user@$host" + return DBInterface.connect(conn_obj, conn_string) + elseif haskey(kwargs, :password) + password=kwargs[:password] + kwargs = filter(kvp -> first(kvp) != :password, kwargs) + if isempty(kwargs) + conn_string = "postgresql://$user:$password@$host" + return DBInterface.connect(conn_obj, conn_string) + elseif haskey(kwargs, :db) + db = kwargs[:db] + kwargs = filter(kvp -> first(kvp) != :db, kwargs) + if isempty(kwargs) + conn_string = "postgresql://$(user):$(password)@$(host)/$(db)?user=$(user)" + return DBInterface.connect(conn_obj, conn_string) + elseif haskey(kwargs, :port) + db = kwargs[:port] + kwargs = filter(kvp -> first(kvp) != :port, kwargs) + if isempty(kwargs) + conn_string = "postgresql://$user:$password@$host:$port/$db" + return DBInterface.connect(conn_obj, conn_string) + end + end + end + elseif haskey(kwargs, :db) + db = kwargs[:db] + kwargs = filter(kvp -> first(kvp) != :db, kwargs) + if isempty(kwargs) + conn_string = "postgresql://$user@$host/$db" + return DBInterface.connect(conn_obj, conn_string) + elseif haskey(kwargs, :port) + db = kwargs[:port] + kwargs = filter(kvp -> first(kvp) != :port, kwargs) + if isempty(kwargs) + conn_string = "postgresql://$user@$host:$port/$db" + return DBInterface.connect(conn_obj, conn_string) + end + end + + else + error("Invalid arguments, make sure that keyword user and host exist") + end +end end -""" -Workaround for LibPQ interface to DBInterface's `prepare` function; not supported in LibPQ.jl package currently -""" -DBInterface.prepare(conn::LibPQ.Connection, args...; kws...) = - LibPQ.prepare(conn, args...; kws...) """ Workaround for LibPQ interface to DBInterface's `execute` function; not supported in LibPQ.jl package currently @@ -29,3 +91,22 @@ DBInterface.execute(conn::Union{LibPQ.Connection, LibPQ.Statement}, args...; kws LibPQ.execute(conn, args...; kws...) + +function _dbconnect(conn_obj::Type{LibPQ.Connection}, conn_string :: String) + + return DBInterface.connect(conn_obj, conn_string) + +end +""" +function _dbconnect(conn_obj::Type{LibPQ.Connection}; kwargs...) + conn_string = "" + for k in kwargs + conn_string = conn_string * "(string(k.first))=(k.second) " + end + + conn_string = strip(conn_string) + + return DBInterface.connect(conn_obj, conn_string) + +end +""" \ No newline at end of file diff --git a/src/sqlite.jl b/src/sqlite.jl index a35d5ad..8295f37 100644 --- a/src/sqlite.jl +++ b/src/sqlite.jl @@ -1,5 +1,7 @@ -function _dbconnect(connector::Type{SQLite.DB}; file_path) +using SQLite - return connector(file_path.second) +function _dbconnect(connector::Type{SQLite.DB}, file_path::String) + + return connector(file_path) end diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 0000000..a563133 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,6 @@ +[deps] +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +LibPQ = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1" +MySQL = "39abe10b-433b-5dbd-92d4-e302a9df00cd" +SQLite = "0aa819cd-b072-5ff4-a722-6bc24af294d9" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/data/sqlite.db b/test/data/sqlite.db new file mode 100644 index 0000000..7c5d231 Binary files /dev/null and b/test/data/sqlite.db differ diff --git a/test/runtests.jl b/test/runtests.jl index 35f99ea..8795fc0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,38 @@ -using Test, Example +using Test +using DataFrames +using SQLite +using MySQL +using LibPQ +using DBConnector -@test hello("Julia") == "Hello, Julia" -@test domath(2.0) ≈ 7.0 +@testset "_dbconnect function for SQLite" begin + + conn= DBConnector._dbconnect(SQLite.DB, "../test/data/sqlite.db") + @test @isdefined conn + output = DBInterface.execute(conn, "SELECT age FROM PERSON WHERE name = 'John Doe';") |> DataFrame + out = output[1,1] + expected_output = 30; + @test out == expected_output + +end + +@testset "_dbconnect function for LibPQ" begin + + conn= DBConnector._dbconnect(LibPQ.Connection, host = ENV["POSTGRES_HOST"],user = ENV["POSTGRES_USER"], password = ENV["POSTGRES_PASSWORD"], db = "omop") + + @test @isdefined conn + +end +""" +@testset "_dbconnect function for MySQL" begin + + #conn = DBConnector._dbconnect(MySQL.Connection, ENV["MYSQL_HOST"], ENV["MYSQL_USER"], ENV["MYSQL_PASSWORD"], db="MySQL") + conn = DBConnector._dbconnect(MySQL.Connection, "199.180.155.65","fareeda", "GSoCPass"; db="MySQL") + @test @isdefined conn + @test typeof(conn) == MySQL.Connection + @test isopen(conn) + close(conn) + +end + +"""