Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
cta
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
dCache
cta
Commits
3adfeac6
Commit
3adfeac6
authored
8 years ago
by
Steven Murray
Browse files
Options
Downloads
Patches
Plain Diff
Added unit-tests for OcciRset::bind()
parent
5ad5eb78
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
catalogue/OcciRset.hpp
+4
-4
4 additions, 4 deletions
catalogue/OcciRset.hpp
catalogue/OcciRsetTest.cpp
+26
-5
26 additions, 5 deletions
catalogue/OcciRsetTest.cpp
catalogue/OcciStmt.cpp
+98
-6
98 additions, 6 deletions
catalogue/OcciStmt.cpp
catalogue/OcciStmt.hpp
+17
-0
17 additions, 0 deletions
catalogue/OcciStmt.hpp
with
145 additions
and
15 deletions
catalogue/OcciRset.hpp
+
4
−
4
View file @
3adfeac6
...
...
@@ -151,8 +151,8 @@ private:
/**
* Forward declaration of the nested class ColumnNameIdx that is intentionally
* hidden in the cpp file of the
Sqlite
Rset class. The class is hidden in
* order to enable the
Sqlite
Rset class to be used by code compiled against
* hidden in the cpp file of the
Occi
Rset class. The class is hidden in
* order to enable the
Occi
Rset class to be used by code compiled against
* the CXX11 ABI and used by code compiled against the pre-CXX11 ABI.
*/
class
ColumnNameToIdx
;
...
...
@@ -168,8 +168,8 @@ private:
/**
* Forward declaration of the nest class TextColumnCache that is intentionally
* hidden in the cpp file of the
Sqlite
Rset class. The class is hidden in
* order to enable the
Sqlite
Rset class to be used by code compiled against
* hidden in the cpp file of the
Occi
Rset class. The class is hidden in
* order to enable the
Occi
Rset class to be used by code compiled against
* the CXX11 ABI and used by code compiled against the pre-CXX11 ABI.
*/
class
TextColumnCache
;
...
...
This diff is collapsed.
Click to expand it.
catalogue/OcciRsetTest.cpp
+
26
−
5
View file @
3adfeac6
...
...
@@ -95,9 +95,8 @@ TEST_F(cta_catalogue_OcciRsetTest, executeQuery_uint32_t) {
ASSERT_FALSE
(
rset
->
next
());
}
// TODO - Implement 64-bit int test because the current code will fail
// TODO - Implement 64-bit int
executeQuery
test because the current code will fail
/*
TEST_F
(
cta_catalogue_OcciRsetTest
,
bind_c_string
)
{
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
...
...
@@ -110,12 +109,34 @@ TEST_F(cta_catalogue_OcciRsetTest, bind_c_string) {
dbLogin
.
database
.
c_str
()));
const
char
*
const
sql
=
"SELECT DUMMY FROM DUAL WHERE DUMMY = :DUMMY"
;
std
::
unique_ptr
<
DbStmt
>
stmt
(
conn
->
createStmt
(
sql
));
stmt
->
bind
(
":DUMMY"
,
"X"
);
std
::
unique_ptr
<
DbRset
>
rset
(
stmt
->
executeQuery
());
ASSERT_TRUE
(
rset
->
next
());
const uint32_t i = rset->columnUint64("I"
);
ASSERT_EQ(
1234, i
);
std
::
string
text
(
rset
->
columnText
(
"DUMMY"
)
);
ASSERT_EQ
(
std
::
string
(
"X"
),
text
);
ASSERT_FALSE
(
rset
->
next
());
}
*/
TEST_F
(
cta_catalogue_OcciRsetTest
,
bind_uint32_t
)
{
using
namespace
cta
;
using
namespace
cta
::
catalogue
;
const
DbLogin
dbLogin
=
DbLogin
::
readFromFile
(
g_cmdLineArgs
.
oraDbConnFile
);
OcciEnv
env
;
std
::
unique_ptr
<
OcciConn
>
conn
(
env
.
createConn
(
dbLogin
.
username
.
c_str
(),
dbLogin
.
password
.
c_str
(),
dbLogin
.
database
.
c_str
()));
const
char
*
const
sql
=
"SELECT :N AS AN_UNSIGNED_INT FROM DUAL"
;
std
::
unique_ptr
<
DbStmt
>
stmt
(
conn
->
createStmt
(
sql
));
stmt
->
bind
(
":N"
,
1234
);
std
::
unique_ptr
<
DbRset
>
rset
(
stmt
->
executeQuery
());
ASSERT_TRUE
(
rset
->
next
());
const
uint32_t
n
=
rset
->
columnUint64
(
"AN_UNSIGNED_INT"
);
ASSERT_EQ
(
1234
,
n
);
ASSERT_FALSE
(
rset
->
next
());
}
// TODO - Implement 64-bit int bind test because the current code will fail
}
// namespace unitTests
This diff is collapsed.
Click to expand it.
catalogue/OcciStmt.cpp
+
98
−
6
View file @
3adfeac6
...
...
@@ -24,11 +24,94 @@
#include
"catalogue/OcciStmt.hpp"
#include
<cstring>
#include
<iostream>
#include
<map>
#include
<sstream>
#include
<stdexcept>
namespace
cta
{
namespace
catalogue
{
class
OcciStmt
::
ParamNameToIdx
{
public:
/**
* Constructor.
*
* Parses the specified SQL statement to populate an internal map from SQL
* parameter name to parameter index.
*
* @param sql The SQL statement to be parsed for SQL parameter names.
*/
ParamNameToIdx
(
const
char
*
const
sql
)
{
bool
waitingForAParam
=
true
;
std
::
ostringstream
paramName
;
unsigned
int
paramIdx
=
1
;
for
(
const
char
*
ptr
=
sql
;
;
ptr
++
)
{
if
(
waitingForAParam
)
{
if
(
'\0'
==
*
ptr
)
{
break
;
}
else
if
(
':'
==
*
ptr
)
{
waitingForAParam
=
false
;
paramName
<<
":"
;
}
}
else
{
if
(
!
isValidParamNameChar
(
*
ptr
))
{
if
(
paramName
.
str
().
empty
())
{
throw
std
::
runtime_error
(
"Parse error: Empty SQL parameter name"
);
}
if
(
m_nameToIdx
.
find
(
paramName
.
str
())
!=
m_nameToIdx
.
end
())
{
throw
std
::
runtime_error
(
"Parse error: SQL parameter "
+
paramName
.
str
()
+
" is a duplicate"
);
}
m_nameToIdx
[
paramName
.
str
()]
=
paramIdx
;
paramName
.
clear
();
paramIdx
++
;
waitingForAParam
=
true
;
}
if
(
'\0'
==
*
ptr
)
{
break
;
}
if
(
':'
==
*
ptr
)
{
throw
std
::
runtime_error
(
"Parse error: Consecutive SQL parameter names are not permitted"
);
}
else
{
paramName
<<
*
ptr
;
}
}
}
}
/**
* Returns the index of teh specified SQL parameter.
*
* @param paramNAme The name of the SQL parameter.
* @return The index of the SQL parameter.
*/
unsigned
int
getIdx
(
const
char
*
const
paramName
)
const
{
auto
itor
=
m_nameToIdx
.
find
(
paramName
);
if
(
itor
==
m_nameToIdx
.
end
())
{
throw
std
::
runtime_error
(
std
::
string
(
__FUNCTION__
)
+
" failed: The SQL parameter "
+
paramName
+
" does not exist"
);
}
return
itor
->
second
;
}
private
:
/**
* Map from SQL parameter name to parameter index.
*/
std
::
map
<
std
::
string
,
unsigned
int
>
m_nameToIdx
;
bool
isValidParamNameChar
(
const
char
c
)
{
return
(
'0'
<=
c
&&
c
<=
'9'
)
||
(
'A'
<=
c
&&
c
<=
'Z'
)
||
(
'a'
<=
c
&&
c
<=
'z'
)
||
c
==
'_'
;
}
};
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
...
...
@@ -48,6 +131,8 @@ OcciStmt::OcciStmt(const char *const sql, OcciConn &conn, oracle::occi::Statemen
m_sql
.
reset
(
new
char
[
sqlLen
+
1
]);
std
::
memcpy
(
m_sql
.
get
(),
sql
,
sqlLen
);
m_sql
[
sqlLen
]
=
'\0'
;
m_paramNameToIdx
.
reset
(
new
ParamNameToIdx
(
sql
));
}
//------------------------------------------------------------------------------
...
...
@@ -84,16 +169,24 @@ const char *OcciStmt::getSql() const {
// bind
//------------------------------------------------------------------------------
void
OcciStmt
::
bind
(
const
char
*
paramName
,
const
uint64_t
paramValue
)
{
std
::
runtime_error
ex
(
std
::
string
(
__FUNCTION__
)
+
" is not implemented"
);
throw
ex
;
try
{
const
unsigned
paramIdx
=
m_paramNameToIdx
->
getIdx
(
paramName
);
m_stmt
->
setUInt
(
paramIdx
,
paramValue
);
}
catch
(
std
::
exception
&
ne
)
{
throw
std
::
runtime_error
(
std
::
string
(
__FUNCTION__
)
+
" failed: "
+
ne
.
what
());
}
}
//------------------------------------------------------------------------------
// bind
//------------------------------------------------------------------------------
void
OcciStmt
::
bind
(
const
char
*
paramName
,
const
char
*
paramValue
)
{
std
::
runtime_error
ex
(
std
::
string
(
__FUNCTION__
)
+
" is not implemented"
);
throw
ex
;
try
{
const
unsigned
paramIdx
=
m_paramNameToIdx
->
getIdx
(
paramName
);
m_stmt
->
setString
(
paramIdx
,
paramValue
);
}
catch
(
std
::
exception
&
ne
)
{
throw
std
::
runtime_error
(
std
::
string
(
__FUNCTION__
)
+
" failed: "
+
ne
.
what
());
}
}
//------------------------------------------------------------------------------
...
...
@@ -105,8 +198,7 @@ DbRset *OcciStmt::executeQuery() {
try
{
return
new
OcciRset
(
*
this
,
m_stmt
->
executeQuery
());
}
catch
(
std
::
exception
&
ne
)
{
throw
std
::
runtime_error
(
std
::
string
(
__FUNCTION__
)
+
" failed for SQL statement "
+
getSql
()
+
": "
+
ne
.
what
());
throw
std
::
runtime_error
(
std
::
string
(
__FUNCTION__
)
+
" failed for SQL statement "
+
getSql
()
+
": "
+
ne
.
what
());
}
}
...
...
This diff is collapsed.
Click to expand it.
catalogue/OcciStmt.hpp
+
17
−
0
View file @
3adfeac6
...
...
@@ -139,6 +139,23 @@ private:
*/
std
::
unique_ptr
<
char
[]
>
m_sql
;
/**
* Forward declaration of the nested class ParamNameToIdx that is intentionally
* hidden in the cpp file of the OcciStmt class. The class is hidden in
* order to enable the OcciStmt class to be used by code compiled against
* the CXX11 ABI and used by code compiled against the pre-CXX11 ABI.
*/
class
ParamNameToIdx
;
/**
* Map from SQL parameter name to parameter index.
*
* Please note that the type of the map is intentionally forward declared in
* order to avoid std::string being used. This is to aid with working with
* pre and post CXX11 ABIs.
*/
std
::
unique_ptr
<
ParamNameToIdx
>
m_paramNameToIdx
;
/**
* The database connection.
*/
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment