diff --git a/Project.toml b/Project.toml index 7eed695..c114bd2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,10 @@ name = "JDBC" uuid = "6042db11-3c3d-5e84-8dba-9cbf74c9ba48" -version = "0.5.0" +version = "0.5.1" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +Decimals = "abce61dc-4473-55a0-ba07-351d65e31d42" JavaCall = "494afd89-becb-516b-aafa-70d2670c0337" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" diff --git a/src/JDBC.jl b/src/JDBC.jl index 15da065..792fdb9 100644 --- a/src/JDBC.jl +++ b/src/JDBC.jl @@ -1,12 +1,12 @@ #This file is part of JDBC.jl. License is MIT. module JDBC using JavaCall -using Dates +using Dates, Decimals export DriverManager, createStatement, prepareStatement, prepareCall, executeQuery, setFetchSize, getInt, getFloat, getString, getShort, getByte, getTime, getTimestamp, getDate, - getBoolean, getNString, getURL, setInt, setFloat, setString, setShort, setByte, setBoolean, - getMetaData, getColumnCount, getColumnType, getColumnName, executeUpdate, execute, commit, + getBoolean, getNString, getURL, getBigDecimal, setInt, setFloat, setString, setShort, setByte, setBoolean, + setBigDecimal, getMetaData, getColumnCount, getColumnType, getColumnName, executeUpdate, execute, commit, rollback, setAutoCommit, getResultSet @@ -32,6 +32,7 @@ const JStatement = @jimport java.sql.Statement const JPreparedStatement = @jimport java.sql.PreparedStatement const JCallableStatement = @jimport java.sql.CallableStatement const JConnection = @jimport java.sql.Connection +const JBigDecimal = @jimport java.math.BigDecimal const COLUMN_NO_NULLS = 0 const COLUMN_NULLABLE = 1 @@ -40,6 +41,10 @@ const COLUMN_NULLABLE_UNKNOWN = 2 init() = JavaCall.init() destroy() = JavaCall.destroy() + +JBigDecimal(x::Decimal) = JBigDecimal((JString,), string(x)) +Decimals.Decimal(x::JBigDecimal) = decimal(jcall(x, "toPlainString", JString, ())) + """ ``` createStatement(connection::JConnection) @@ -283,8 +288,7 @@ for s in [("String", :JString), ("Float", :jfloat), ("Double", :jdouble), ("Byte", :jbyte), - ("URL", :(@jimport(java.net.URL))), - ("BigDecimal", :(@jimport(java.math.BigDecimal)))] + ("URL", :(@jimport(java.net.URL)))] m = Symbol(string("get", s[1])) n = Symbol(string("set", s[1])) v = quote @@ -295,6 +299,25 @@ for s in [("String", :JString), eval(v) end +# this requires a special conversion +function getBigDecimal_raw(rs::Union{JResultSet, JCallableStatement}, fld::AbstractString) + jcall(rs, "getBigDecimal", JBigDecimal, (JString,), fld) +end +function getBigDecimal_raw(rs::Union{JResultSet, JCallableStatement}, fld::Integer) + jcall(rs, "getBigDecimal", JBigDecimal, (jint,), fld) +end +function setBigDecimal_raw(stmt::Union{JPreparedStatement, JCallableStatement}, idx::Integer, v) + jcall(stmt, "setBigDecimal", Nothing, (jint, JBigDecimal), idx, v) +end + +getBigDecimal(rs::Union{JResultSet,JCallableStatement}, fld) = Decimal(getBigDecimal_raw(rs, fld)) +function setBigDecimal(stmt::Union{JPreparedStatement,JCallableStatement}, idx::Integer, v::AbstractString) + setBigDecimal_raw(stmt, idx, JBigDecimal((JString,), v)) +end +function setBigDecimal(stmt::Union{JPreparedStatement,JCallableStatement}, idx::Integer, v::Decimal) + setBigDecimal_raw(stmt, idx, JBigDecimal(v)) +end + """ ``` getDate(rs::Union{JResultSet, JCallableStatement}, fld::AbstractString) @@ -548,7 +571,7 @@ global const get_method_dict = Dict( # JDBC_COLTYPE_CLOB => 2005, # JDBC_COLTYPE_DATALINK => 70, JDBC_COLTYPE_DATE => getDate, - JDBC_COLTYPE_DECIMAL => getFloat, + JDBC_COLTYPE_DECIMAL => getBigDecimal, # JDBC_COLTYPE_DISTINCT => 2001, JDBC_COLTYPE_DOUBLE => getDouble, JDBC_COLTYPE_FLOAT => getFloat, @@ -560,7 +583,7 @@ global const get_method_dict = Dict( JDBC_COLTYPE_NCHAR => getNString, # JDBC_COLTYPE_NCLOB => 2011, # JDBC_COLTYPE_NULL => 0, - JDBC_COLTYPE_NUMERIC => getDouble, + JDBC_COLTYPE_NUMERIC => getBigDecimal, JDBC_COLTYPE_NVARCHAR => getNString, # JDBC_COLTYPE_OTHER => 1111, JDBC_COLTYPE_REAL => getFloat, diff --git a/src/tables.jl b/src/tables.jl index f2baa90..8360297 100644 --- a/src/tables.jl +++ b/src/tables.jl @@ -7,14 +7,14 @@ const column_types = Dict( JDBC_COLTYPE_BOOLEAN=>Bool, JDBC_COLTYPE_CHAR=>String, JDBC_COLTYPE_DATE=>Date, - JDBC_COLTYPE_DECIMAL=>Float64, + JDBC_COLTYPE_DECIMAL=>Decimal, JDBC_COLTYPE_DOUBLE=>Float64, JDBC_COLTYPE_FLOAT=>Float32, JDBC_COLTYPE_INTEGER=>Int32, JDBC_COLTYPE_LONGNVARCHAR=>String, JDBC_COLTYPE_LONGVARCHAR=>String, JDBC_COLTYPE_NCHAR=>String, - JDBC_COLTYPE_NUMERIC=>Float64, + JDBC_COLTYPE_NUMERIC=>Decimal, JDBC_COLTYPE_NVARCHAR=>String, JDBC_COLTYPE_REAL=>Float64, JDBC_COLTYPE_ROWID=>Int64, diff --git a/test/runtests.jl b/test/runtests.jl index 645d3a7..8a6fd7b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,6 +4,7 @@ using JDBC using DataFrames using Test using Dates +using Decimals import Pkg derby_driver_path = joinpath(dirname(pathof(JDBC)),"..","test","derby.jar") @@ -94,23 +95,28 @@ stmt = createStatement(conn) executeUpdate(stmt, "CREATE TABLE FIRSTTABLE (ID INT PRIMARY KEY, - NAME VARCHAR(12))") -ppstmt = prepareStatement(conn, "insert into firsttable values (?, ?)") + NAME VARCHAR(12), + VALUE DECIMAL(5,2))") +ppstmt = prepareStatement(conn, "insert into firsttable values (?, ?, ?)") setInt(ppstmt, 1,10) setString(ppstmt, 2,"TEN") +setBigDecimal(ppstmt, 3, decimal("10.38")) executeUpdate(ppstmt) setInt(ppstmt, 1,20) setString(ppstmt, 2,"TWENTY") +setBigDecimal(ppstmt, 3, decimal("-1.72e2")) executeUpdate(ppstmt) -rs=executeQuery(stmt, "select * from FIRSTTABLE") +rs = executeQuery(stmt, "select * from FIRSTTABLE") ft = JDBC.load(DataFrame, rs) @testset "Query3" begin - @test size(ft) == (2,2) + @test size(ft) == (2,3) @test ft[1, :ID] == 10 @test ft[1, :NAME] == "TEN" + @test ft[1, :VALUE] == decimal("10.38") @test ft[2, :ID] == 20 @test ft[2, :NAME] == "TWENTY" + @test ft[2, :VALUE] == decimal("-1.72e2") end close(rs)