Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
dCache
cta
Commits
00d6de65
Commit
00d6de65
authored
May 16, 2019
by
Steven Murray
Browse files
Added rdbms::Stmt::bindDouble() and rdbms::Rset::columnDouble()
parent
c27bff0d
Changes
30
Hide whitespace changes
Inline
Side-by-side
cta.spec.in
View file @
00d6de65
...
...
@@ -279,9 +279,11 @@ Unit tests and system tests with virtual tape drives
%{_libdir}/libctacommonunittests.so*
%{_libdir}/libctadbconfigcatalogueunittests.so*
%{_libdir}/libctadbconfigconnunittests.so*
%{_libdir}/libctadbconfigstmtunittests.so*
%{_libdir}/libctaexceptionunittests.so*
%{_libdir}/libctainmemorycatalogueunittests.so*
%{_libdir}/libctainmemoryconnunittests.so*
%{_libdir}/libctainmemorystmtunittests.so*
%{_libdir}/libctaobjectstoreunittests.so*
%{_libdir}/libctardbmsunittests.so*
%{_libdir}/libctardbmswrapperunittests.so*
...
...
rdbms/CMakeLists.txt
View file @
00d6de65
...
...
@@ -43,7 +43,6 @@ install (TARGETS ctardbms DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
set
(
RDBMS_UNIT_TESTS_LIB_SRC_FILES
ConnPoolTest.cpp
ConnTest.cpp
LoginTest.cpp
RdbmsTest.cpp
StmtPoolTest.cpp
)
...
...
@@ -72,6 +71,20 @@ target_link_libraries (ctainmemoryconnunittests
install
(
TARGETS ctainmemoryconnunittests DESTINATION usr/
${
CMAKE_INSTALL_LIBDIR
}
)
set
(
IN_MEMORY_STMT_UNIT_TESTS_LIB_SRC_FILES
StmtTest.cpp
InMemoryVersionOfStmtTest.cpp
)
add_library
(
ctainmemorystmtunittests SHARED
${
IN_MEMORY_STMT_UNIT_TESTS_LIB_SRC_FILES
}
)
set_property
(
TARGET ctainmemorystmtunittests PROPERTY SOVERSION
"
${
CTA_SOVERSION
}
"
)
set_property
(
TARGET ctainmemorystmtunittests PROPERTY VERSION
"
${
CTA_LIBVERSION
}
"
)
target_link_libraries
(
ctainmemorystmtunittests
ctardbms
)
install
(
TARGETS ctainmemorystmtunittests DESTINATION usr/
${
CMAKE_INSTALL_LIBDIR
}
)
set
(
DBCONFIG_CONN_UNIT_TESTS_LIB_SRC_FILES
ConnTest.cpp
DbConfigVersionOfConnTest.cpp
)
...
...
@@ -85,3 +98,17 @@ target_link_libraries (ctadbconfigconnunittests
ctardbms
)
install
(
TARGETS ctadbconfigconnunittests DESTINATION usr/
${
CMAKE_INSTALL_LIBDIR
}
)
set
(
DBCONFIG_STMT_UNIT_TESTS_LIB_SRC_FILES
StmtTest.cpp
DbConfigVersionOfStmtTest.cpp
)
add_library
(
ctadbconfigstmtunittests SHARED
${
DBCONFIG_STMT_UNIT_TESTS_LIB_SRC_FILES
}
)
set_property
(
TARGET ctadbconfigstmtunittests PROPERTY SOVERSION
"
${
CTA_SOVERSION
}
"
)
set_property
(
TARGET ctadbconfigstmtunittests PROPERTY VERSION
"
${
CTA_LIBVERSION
}
"
)
target_link_libraries
(
ctadbconfigstmtunittests
ctardbms
)
install
(
TARGETS ctadbconfigstmtunittests DESTINATION usr/
${
CMAKE_INSTALL_LIBDIR
}
)
rdbms/DbConfigVersionOfStmtTest.cpp
0 → 100644
View file @
00d6de65
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include
"rdbms/StmtTest.hpp"
#include
"tests/RdbmsUnitTestsCmdLineArgs.hpp"
namespace
{
/**
* Creates Login objects from a database configuration file passed on the
* command-line to the unit-tests program.
*/
class
DbConfigFileVersionOfStmtTestLoginFactory
:
public
cta
::
rdbms
::
LoginFactory
{
public:
/**
* Destructor.
*/
virtual
~
DbConfigFileVersionOfStmtTestLoginFactory
()
{
}
/**
* Returns a newly created Login object.
*
* @return A newly created Login object.
*/
virtual
cta
::
rdbms
::
Login
create
()
{
return
cta
::
rdbms
::
Login
::
parseFile
(
g_cmdLineArgs
.
dbConfigPath
);
}
};
// class OracleLoginFactory
DbConfigFileVersionOfStmtTestLoginFactory
g_dbConfigFileVersionOfStmtTestLoginFactory
;
}
// anonymous namespace
namespace
unitTests
{
INSTANTIATE_TEST_CASE_P
(
DbConfigFile
,
cta_rdbms_StmtTest
,
::
testing
::
Values
(
dynamic_cast
<
cta
::
rdbms
::
LoginFactory
*>
(
&
g_dbConfigFileVersionOfStmtTestLoginFactory
)));
}
// namespace unitTests
rdbms/InMemoryVersionOfStmtTest.cpp
0 → 100644
View file @
00d6de65
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include
"rdbms/StmtTest.hpp"
namespace
unitTests
{
namespace
{
/**
* Creates Login objects for in-memory catalogue databases.
*/
class
RdbmsInMemoryLoginFactory
:
public
cta
::
rdbms
::
LoginFactory
{
public:
/**
* Destructor.
*/
virtual
~
RdbmsInMemoryLoginFactory
()
{
}
/**
* Returns a newly created Login object.
*
* @return A newly created Login object.
*/
virtual
cta
::
rdbms
::
Login
create
()
{
return
cta
::
rdbms
::
Login
(
cta
::
rdbms
::
Login
::
DBTYPE_IN_MEMORY
,
""
,
""
,
""
,
""
,
0
);
}
};
// class RdbmsInMemoryLoginFactory
RdbmsInMemoryLoginFactory
g_inMemoryLoginFactory
;
}
// anonymous namespace
INSTANTIATE_TEST_CASE_P
(
InMemory
,
cta_rdbms_StmtTest
,
::
testing
::
Values
(
dynamic_cast
<
cta
::
rdbms
::
LoginFactory
*>
(
&
g_inMemoryLoginFactory
)));
}
// namespace unitTests
rdbms/Rset.cpp
View file @
00d6de65
...
...
@@ -192,5 +192,36 @@ optional<uint64_t> Rset::columnOptionalUint64(const std::string &colName) const
return
m_impl
->
columnOptionalUint64
(
colName
);
}
//------------------------------------------------------------------------------
// columnDouble
//------------------------------------------------------------------------------
double
Rset
::
columnDouble
(
const
std
::
string
&
colName
)
const
{
try
{
if
(
nullptr
==
m_impl
)
{
throw
exception
::
Exception
(
"This result set is invalid"
);
}
const
optional
<
double
>
col
=
columnOptionalDouble
(
colName
);
if
(
col
)
{
return
col
.
value
();
}
else
{
throw
NullDbValue
(
std
::
string
(
"Database column "
)
+
colName
+
" contains a null value"
);
}
}
catch
(
exception
::
Exception
&
ex
)
{
throw
exception
::
Exception
(
std
::
string
(
__FUNCTION__
)
+
" failed: "
+
ex
.
getMessage
().
str
());
}
}
//------------------------------------------------------------------------------
// columnOptionalDouble
//------------------------------------------------------------------------------
optional
<
double
>
Rset
::
columnOptionalDouble
(
const
std
::
string
&
colName
)
const
{
if
(
nullptr
==
m_impl
)
{
throw
exception
::
Exception
(
std
::
string
(
__FUNCTION__
)
+
" failed: "
"This result set is invalid"
);
}
return
m_impl
->
columnOptionalDouble
(
colName
);
}
}
// namespace rdbms
}
// namespace cta
rdbms/Rset.hpp
View file @
00d6de65
...
...
@@ -166,6 +166,27 @@ public:
*/
optional
<
bool
>
columnOptionalBool
(
const
std
::
string
&
colName
)
const
;
/**
* Returns the value of the specified column as a double.
*
* This method will throw an exception if the value of the specified column
* is nullptr.
*
* @param colName The name of the column.
* @return The value of the specified column.
*/
double
columnDouble
(
const
std
::
string
&
colName
)
const
;
/**
* Returns the value of the specified column as a double.
*
* This method will return a null column value as an optional with no value.
*
* @param colName The name of the column.
* @return The value of the specified column.
*/
optional
<
double
>
columnOptionalDouble
(
const
std
::
string
&
colName
)
const
;
private:
/**
...
...
rdbms/Stmt.cpp
View file @
00d6de65
...
...
@@ -128,6 +128,28 @@ void Stmt::bindOptionalUint64(const std::string ¶mName, const optional<uint6
}
}
//-----------------------------------------------------------------------------
// bindDouble
//-----------------------------------------------------------------------------
void
Stmt
::
bindDouble
(
const
std
::
string
&
paramName
,
const
double
paramValue
)
{
if
(
nullptr
!=
m_stmt
)
{
return
m_stmt
->
bindDouble
(
paramName
,
paramValue
);
}
else
{
throw
exception
::
Exception
(
std
::
string
(
__FUNCTION__
)
+
" failed: Stmt does not contain a cached statement"
);
}
}
//-----------------------------------------------------------------------------
// bindOptionalDouble
//-----------------------------------------------------------------------------
void
Stmt
::
bindOptionalDouble
(
const
std
::
string
&
paramName
,
const
optional
<
double
>
&
paramValue
)
{
if
(
nullptr
!=
m_stmt
)
{
return
m_stmt
->
bindOptionalDouble
(
paramName
,
paramValue
);
}
else
{
throw
exception
::
Exception
(
std
::
string
(
__FUNCTION__
)
+
" failed: Stmt does not contain a cached statement"
);
}
}
//-----------------------------------------------------------------------------
// bindBool
//-----------------------------------------------------------------------------
...
...
rdbms/Stmt.hpp
View file @
00d6de65
...
...
@@ -119,6 +119,22 @@ public:
*/
void
bindOptionalUint64
(
const
std
::
string
&
paramName
,
const
optional
<
uint64_t
>
&
paramValue
);
/**
* Binds an SQL parameter.
*
* @param paramName The name of the parameter.
* @param paramValue The value to be bound.
*/
void
bindDouble
(
const
std
::
string
&
paramName
,
const
double
paramValue
);
/**
* Binds an SQL parameter.
*
* @param paramName The name of the parameter.
* @param paramValue The value to be bound.
*/
void
bindOptionalDouble
(
const
std
::
string
&
paramName
,
const
optional
<
double
>
&
paramValue
);
/**
* Binds an SQL parameter.
*
...
...
rdbms/StmtTest.cpp
0 → 100644
View file @
00d6de65
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include
"common/exception/Exception.hpp"
#include
"common/make_unique.hpp"
#include
"rdbms/ConnPool.hpp"
#include
"rdbms/StmtTest.hpp"
#include
<gtest/gtest.h>
namespace
unitTests
{
//------------------------------------------------------------------------------
// Setup
//------------------------------------------------------------------------------
void
cta_rdbms_StmtTest
::
SetUp
()
{
using
namespace
cta
::
rdbms
;
if
(
!
m_connPool
)
{
const
cta
::
rdbms
::
Login
login
=
GetParam
()
->
create
();
const
uint64_t
maxNbConns
=
1
;
m_connPool
=
cta
::
make_unique
<
ConnPool
>
(
login
,
maxNbConns
);
}
m_conn
=
m_connPool
->
getConn
();
ASSERT_EQ
(
AutocommitMode
::
AUTOCOMMIT_ON
,
m_conn
.
getAutocommitMode
());
try
{
m_conn
.
executeNonQuery
(
"DROP TABLE STMT_TEST"
);
}
catch
(...)
{
// Do nothing
}
m_conn
.
executeNonQuery
(
"CREATE TABLE STMT_TEST(DOUBLE_COL FLOAT)"
);
}
//------------------------------------------------------------------------------
// TearDown
//------------------------------------------------------------------------------
void
cta_rdbms_StmtTest
::
TearDown
()
{
using
namespace
cta
::
rdbms
;
try
{
m_conn
.
executeNonQuery
(
"DROP TABLE STMT_TEST"
);
}
catch
(...)
{
// Do nothing
}
}
TEST_P
(
cta_rdbms_StmtTest
,
insert_with_bindDouble
)
{
using
namespace
cta
::
rdbms
;
const
double
insertValue
=
1.234
;
// Insert a row into the test table
{
const
char
*
const
sql
=
"INSERT INTO STMT_TEST("
"DOUBLE_COL) "
"VALUES("
":DOUBLE_COL)"
;
auto
stmt
=
m_conn
.
createStmt
(
sql
);
stmt
.
bindDouble
(
":DOUBLE_COL"
,
insertValue
);
stmt
.
executeNonQuery
();
}
// Select the row back from the table
{
const
char
*
const
sql
=
"SELECT "
"DOUBLE_COL AS DOUBLE_COL "
"FROM "
"STMT_TEST"
;
auto
stmt
=
m_conn
.
createStmt
(
sql
);
auto
rset
=
stmt
.
executeQuery
();
ASSERT_TRUE
(
rset
.
next
());
const
auto
selectValue
=
rset
.
columnOptionalDouble
(
"DOUBLE_COL"
);
ASSERT_TRUE
((
bool
)
selectValue
);
const
double
diff
=
insertValue
-
selectValue
.
value
();
ASSERT_TRUE
(
0.000001
>
diff
);
ASSERT_FALSE
(
rset
.
next
());
}
}
}
// namespace unitTests
rdbms/StmtTest.hpp
0 → 100644
View file @
00d6de65
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include
"rdbms/LoginFactory.hpp"
#include
"rdbms/Conn.hpp"
#include
<gtest/gtest.h>
#include
<memory>
namespace
unitTests
{
class
cta_rdbms_StmtTest
:
public
::
testing
::
TestWithParam
<
cta
::
rdbms
::
LoginFactory
*>
{
protected:
/**
* The database connection pool.
*/
std
::
unique_ptr
<
cta
::
rdbms
::
ConnPool
>
m_connPool
;
/**
* The database connection.
*/
cta
::
rdbms
::
Conn
m_conn
;
virtual
void
SetUp
();
virtual
void
TearDown
();
};
// cta_rdbms_StmtTest
}
// namespace unitTests
rdbms/wrapper/Mysql.hpp
View file @
00d6de65
...
...
@@ -99,6 +99,7 @@ class Mysql {
enum
buffer_types
{
placeholder_uint64
,
placeholder_string
,
placeholder_double
,
};
virtual
std
::
string
show
()
=
0
;
...
...
@@ -113,6 +114,7 @@ class Mysql {
// following is to access data
virtual
uint64_t
get_uint64
()
=
0
;
virtual
std
::
string
get_string
()
=
0
;
virtual
double
get_double
()
=
0
;
// helper
virtual
bool
reset
()
=
0
;
};
...
...
@@ -155,6 +157,10 @@ class Mysql {
return
std
::
to_string
(
val
);
}
double
get_double
()
{
return
val
;
}
bool
reset
()
{
return
false
;
}
...
...
@@ -210,6 +216,12 @@ class Mysql {
return
std
::
string
(
val
,
val
+*
get_length
());
}
// note: allow users try to convert from string to int,
// but users need to catch the exception.
double
get_double
()
{
return
std
::
stod
(
val
);
}
bool
reset
()
{
memset
(
val
,
0
,
buf_sz
);
...
...
@@ -218,6 +230,54 @@ class Mysql {
};
struct
Placeholder_Double
:
Placeholder
{
double
val
;
Placeholder_Double
()
:
Placeholder
(),
val
(
0
)
{
}
std
::
string
show
()
override
{
std
::
stringstream
ss
;
ss
<<
"['"
<<
idx
<<
"' '"
<<
is_null
<<
"' '"
<<
length
<<
"' '"
<<
val
<<
"' '"
<<
get_buffer_length
()
<<
"']"
;
return
ss
.
str
();
}
buffer_types
get_buffer_type
()
override
{
return
placeholder_double
;
}
void
*
get_buffer
()
override
{
return
&
val
;
}
unsigned
long
get_buffer_length
()
override
{
return
sizeof
(
double
);
}
bool
get_is_unsigned
()
override
{
return
true
;
}
uint64_t
get_uint64
()
override
{
return
val
;
}
std
::
string
get_string
()
override
{
return
std
::
to_string
(
val
);
}
double
get_double
()
override
{
return
val
;
}
bool
reset
()
{
return
false
;
}
};
struct
FieldsInfo
{
FieldsInfo
(
MYSQL_RES
*
result_metadata
);
...
...
rdbms/wrapper/MysqlRset.cpp
View file @
00d6de65
...
...
@@ -134,6 +134,25 @@ optional<uint64_t> MysqlRset::columnOptionalUint64(const std::string &colName) c
return
optional
<
uint64_t
>
(
holder
->
get_uint64
());
}
//------------------------------------------------------------------------------
// columnOptionalDouble
//------------------------------------------------------------------------------
optional
<
double
>
MysqlRset
::
columnOptionalDouble
(
const
std
::
string
&
colName
)
const
{
if
(
not
m_fields
.
exists
(
colName
))
{
throw
exception
::
Exception
(
std
::
string
(
__FUNCTION__
)
+
" column does not exist: "
+
colName
);
return
nullopt
;
}
Mysql
::
Placeholder
*
holder
=
m_stmt
.
columnHolder
(
colName
);
// m_holders[idx];
// the value can be null
if
(
holder
->
get_is_null
()
and
*
holder
->
get_is_null
())
{
return
nullopt
;
}
return
optional
<
double
>
(
holder
->
get_double
());
}
}
// namespace wrapper
}
// namespace rdbms
}
// namespace cta
rdbms/wrapper/MysqlRset.hpp
View file @
00d6de65
...
...
@@ -96,6 +96,16 @@ public:
*/
optional
<
uint64_t
>
columnOptionalUint64
(
const
std
::
string
&
colName
)
const
override
;
/**
* Returns the value of the specified column as a double.
*
* This method will return a null column value as an optional with no value.
*
* @param colName The name of the column.
* @return The value of the specified column.
*/
optional
<
double
>
columnOptionalDouble
(
const
std
::
string
&
colName
)
const
override
;
private:
/**
...
...
rdbms/wrapper/MysqlStmt.cpp
View file @
00d6de65
...
...
@@ -189,14 +189,59 @@ void MysqlStmt::bindOptionalUint64(const std::string ¶mName, const optional<
const
unsigned
int
paramIdx
=
getParamIdx
(
paramName
);
// starts from 1.
const
unsigned
int
idx
=
paramIdx
-
1
;
Mysql
::
Placeholder_
Uint64
*
holder
=
dynamic_cast
<
Mysql
::
Placeholder_
Uint64
*>
(
m_placeholder
[
idx
]);
Mysql
::
Placeholder_
Double
*
holder
=
dynamic_cast
<
Mysql
::
Placeholder_
Double
*>
(
m_placeholder
[
idx
]);
// if already exists, try to reuse
if
(
!
holder
and
m_placeholder
[
idx
])
{
throw
exception
::
Exception
(
std
::
string
(
__FUNCTION__
)
+
" can't cast from Placeholder to Placeholder_Uint64. "
);
}
if
(
!
holder
)
{
holder
=
new
Mysql
::
Placeholder_Uint64
();
holder
=
new
Mysql
::
Placeholder_Double
();
holder
->
idx
=
idx
;
holder
->
length
=
sizeof
(
uint64_t
);
}
if
(
paramValue
)
{
holder
->
val
=
paramValue
.
value
();
}
else
{
holder
->
is_null
=
true
;
}
// delete m_placeholder[idx]; // remove the previous placeholder
m_placeholder
[
idx
]
=
holder
;
}
catch
(
exception
::
Exception
&
ex
)
{
throw
exception
::
Exception
(
std
::
string
(
__FUNCTION__
)
+
" failed for SQL statement "
+
getSqlForException
()
+
": "
+
ex
.
getMessage
().
str
());
}
}
//------------------------------------------------------------------------------
// bindDouble
//------------------------------------------------------------------------------
void
MysqlStmt
::
bindDouble
(
const
std
::
string
&
paramName
,
const
double
paramValue
)
{
try
{
bindOptionalDouble
(
paramName
,
paramValue
);
}
catch
(
exception
::
Exception
&
ex
)
{
throw
exception
::
Exception
(
std
::
string
(
__FUNCTION__
)
+
" failed: "
+
ex
.
getMessage
().
str
());
}
}