1 /* $Id: parameters.cpp 535289 2017-05-08 13:38:35Z ivanov $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author:  Vladimir Soussov
27  *
28  * File Description:  Param container implementation
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/ncbimisc.hpp>
34 #include <dbapi/driver/util/parameters.hpp>
35 #include <dbapi/error_codes.hpp>
36 #include <dbapi/driver/exception.hpp>
37 
38 
39 #define NCBI_USE_ERRCODE_X   Dbapi_DrvrUtil
40 
41 
42 BEGIN_NCBI_SCOPE
43 
44 namespace impl {
45 
46 ////////////////////////////////////////////////////////////////////////////////
SParam(void)47 CDB_Params::SParam::SParam(void) :
48     m_Param(NULL),
49     m_Status(0)
50 {
51 }
52 
~SParam(void)53 CDB_Params::SParam::~SParam(void)
54 {
55     DeleteParam();
56 }
57 
58 
59 void
Bind(const string & param_name,CDB_Object * param,bool is_out)60 CDB_Params::SParam::Bind(const string& param_name, CDB_Object* param, bool is_out)
61 {
62     DeleteParam();
63 
64     m_Param = param;
65     m_Name = param_name;
66     m_Status |= fBound | (is_out ? fOutput : 0) ;
67 }
68 
69 void
Set(const string & param_name,CDB_Object * param,bool is_out)70 CDB_Params::SParam::Set(const string& param_name, CDB_Object* param, bool is_out)
71 {
72     if ((m_Status & fSet) != 0) {
73         if (m_Param->GetType() == param->GetType()) {
74             // types are the same
75             m_Param->AssignValue(*param);
76         } else {
77             // we need to delete the old one
78             DeleteParam();
79 
80             m_Param = param->Clone();
81         }
82     } else {
83         m_Param = param->Clone();
84     }
85 
86     m_Name = param_name;
87     m_Status |= fSet | (is_out ? fOutput : 0);
88 }
89 
90 
91 ////////////////////////////////////////////////////////////////////////////////
CDB_Params(void)92 CDB_Params::CDB_Params(void)
93 : m_Locked(false)
94 {
95 }
96 
97 
98 bool
GetParamNumInternal(const string & param_name,unsigned int & param_num) const99 CDB_Params::GetParamNumInternal(const string& param_name, unsigned int& param_num) const
100 {
101     // try to find this name
102     for (param_num = 0;  param_num < m_Params.size(); ++param_num) {
103         const SParam& param = m_Params[param_num];
104         if (param.m_Status != 0 && param_name == param.m_Name) {
105             // We found it ...
106             return true;
107         }
108     }
109 
110     return false;
111 }
112 
113 
114 unsigned int
GetParamNum(const string & param_name) const115 CDB_Params::GetParamNum(const string& param_name) const
116 {
117     unsigned int param_no = 0;
118 
119     if (!GetParamNumInternal(param_name, param_no)) {
120         // Parameter not found ...
121         DATABASE_DRIVER_ERROR("Invalid parameter's name: " + param_name, 122510 );
122     }
123 
124     return param_no;
125 }
126 
127 unsigned int
GetParamNum(unsigned int param_no,const string & param_name)128 CDB_Params::GetParamNum(unsigned int param_no, const string& param_name)
129 {
130     if (param_no == CDB_Params::kNoParamNumber) {
131         if (!param_name.empty()) {
132             // try to find this name
133             if (!GetParamNumInternal(param_name, param_no)) {
134                 // Parameter not found ...
135 		CHECK_DRIVER_ERROR(IsLocked(), "Parameters are locked. New bindins are not allowed.", 20001);
136                 m_Params.resize(m_Params.size() + 1);
137                 return (unsigned int)(m_Params.size() - 1);
138             }
139         }
140     } else {
141         if (param_no >= m_Params.size()) {
142 	    CHECK_DRIVER_ERROR(IsLocked(), "Parameters are locked. New bindins are not allowed.", 20001);
143             m_Params.resize(param_no + 1);
144         }
145     }
146 
147     return param_no;
148 }
149 
150 
BindParam(unsigned int param_no,const string & param_name,CDB_Object * param,bool is_out)151 bool CDB_Params::BindParam(unsigned int param_no, const string& param_name,
152                            CDB_Object* param, bool is_out)
153 {
154     param_no = GetParamNum(param_no, param_name);
155     m_Params[param_no].Bind(param_name, param, is_out);
156     return true;
157 }
158 
159 
SetParam(unsigned int param_no,const string & param_name,CDB_Object * param,bool is_out)160 bool CDB_Params::SetParam(unsigned int param_no, const string& param_name,
161                           CDB_Object* param, bool is_out)
162 {
163     param_no = GetParamNum(param_no, param_name);
164     m_Params[param_no].Set(param_name, param, is_out);
165     return true;
166 }
167 
168 
SemiShallowClone(void) const169 CDB_Params* CDB_Params::SemiShallowClone(void) const
170 {
171     unique_ptr<CDB_Params> result(new CDB_Params);
172     SParam empty_param;
173     ITERATE (deque<SParam>, it, m_Params) {
174         result->m_Params.push_back(empty_param);
175         SParam& p = result->m_Params.back();
176 
177         p.m_Name   = it->m_Name;
178         p.m_Param  = ((it->m_Param == NULL) ? NULL
179                       : it->m_Param->ShallowClone());
180         p.m_Status = (it->m_Status & ~fBound) | fSet;
181     }
182     return result.release();
183 }
184 
185 
~CDB_Params()186 CDB_Params::~CDB_Params()
187 {
188 }
189 
190 
191 string
g_SubstituteParam(const string & query,const string & name,const string & val)192 g_SubstituteParam(const string& query, const string& name, const string& val)
193 {
194     string result = query;
195     size_t name_len = name.length();
196     size_t val_len = val.length();
197     size_t len = result.length();
198     char q = 0;
199 
200     for (size_t pos = 0;  pos < len;  pos++) {
201         if (q) {
202             if (result[pos] == q)
203                 q = 0;
204             continue;
205         }
206         if (result[pos] == '"' || result[pos] == '\'') {
207             q = result[pos];
208             continue;
209         }
210         if (NStr::Compare(result, pos, name_len, name) == 0
211             &&  (pos == 0  ||  !isalnum((unsigned char) result[pos - 1]))
212             &&  (pos + name_len >= result.size()
213                  ||  (!isalnum((unsigned char) result[pos + name_len])
214                       &&  result[pos + name_len] != '_')))
215         {
216             result.replace(pos, name_len, val);
217             len = result.length();
218             pos += val_len;
219         }
220     }
221 
222     return result;
223 }
224 
225 }
226 
227 END_NCBI_SCOPE
228 
229 
230