1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #include "mysqlc_general.hxx"
20 #include "mysqlc_resultsetmetadata.hxx"
21 
22 #include <sal/log.hxx>
23 #include <rtl/ustring.hxx>
24 
25 using com::sun::star::sdbc::SQLException;
26 
27 using com::sun::star::uno::Any;
28 using com::sun::star::uno::Reference;
29 using com::sun::star::uno::XInterface;
30 
31 using namespace rtl;
32 
33 namespace mysqlc_sdbc_driver
34 {
allocateSqlVar(void ** mem,enum_field_types eType,unsigned nSize)35 void allocateSqlVar(void** mem, enum_field_types eType, unsigned nSize)
36 {
37     assert(mem);
38     switch (eType)
39     {
40         case MYSQL_TYPE_LONG:
41         case MYSQL_TYPE_INT24:
42             *mem = malloc(sizeof(sal_Int32));
43             break;
44         case MYSQL_TYPE_SHORT:
45             *mem = malloc(sizeof(sal_Int16));
46             break;
47         case MYSQL_TYPE_BIT:
48         case MYSQL_TYPE_TINY:
49             *mem = malloc(sizeof(sal_Int8));
50             break;
51         case MYSQL_TYPE_LONGLONG:
52             *mem = malloc(sizeof(sal_Int64));
53             break;
54         case MYSQL_TYPE_FLOAT:
55             *mem = malloc(sizeof(float));
56             break;
57         case MYSQL_TYPE_DOUBLE:
58             *mem = malloc(sizeof(double));
59             break;
60         case MYSQL_TYPE_DATE:
61         case MYSQL_TYPE_TIME:
62         case MYSQL_TYPE_DATETIME:
63         case MYSQL_TYPE_TIMESTAMP:
64         case MYSQL_TYPE_YEAR: // FIXME below
65         case MYSQL_TYPE_NEWDATE:
66         case MYSQL_TYPE_ENUM:
67         case MYSQL_TYPE_SET:
68         case MYSQL_TYPE_GEOMETRY:
69             *mem = malloc(sizeof(MYSQL_TIME));
70             break;
71         case MYSQL_TYPE_STRING:
72         case MYSQL_TYPE_VAR_STRING:
73         case MYSQL_TYPE_VARCHAR:
74         case MYSQL_TYPE_DECIMAL:
75         case MYSQL_TYPE_NEWDECIMAL:
76             *mem = malloc(sizeof(char) * nSize);
77             break;
78         case MYSQL_TYPE_NULL:
79         case MYSQL_TYPE_BLOB:
80         case MYSQL_TYPE_TINY_BLOB:
81         case MYSQL_TYPE_MEDIUM_BLOB:
82         case MYSQL_TYPE_LONG_BLOB:
83             *mem = nullptr;
84             break;
85         default:
86             SAL_WARN("connectivity.mysqlc", "unknown enum_field_type");
87     }
88 }
89 
throwFeatureNotImplementedException(const sal_Char * _pAsciiFeatureName,const css::uno::Reference<XInterface> & _rxContext)90 void throwFeatureNotImplementedException(const sal_Char* _pAsciiFeatureName,
91                                          const css::uno::Reference<XInterface>& _rxContext)
92 {
93     const OUString sMessage
94         = OUString::createFromAscii(_pAsciiFeatureName) + ": feature not implemented.";
95     throw SQLException(sMessage, _rxContext, "HYC00", 0, Any());
96 }
97 
throwInvalidArgumentException(const sal_Char * _pAsciiFeatureName,const css::uno::Reference<XInterface> & _rxContext)98 void throwInvalidArgumentException(const sal_Char* _pAsciiFeatureName,
99                                    const css::uno::Reference<XInterface>& _rxContext)
100 {
101     const OUString sMessage
102         = OUString::createFromAscii(_pAsciiFeatureName) + ": invalid arguments.";
103     throw SQLException(sMessage, _rxContext, "HYC00", 0, Any());
104 }
105 
throwSQLExceptionWithMsg(const char * msg,unsigned int errorNum,const css::uno::Reference<css::uno::XInterface> & _context,const rtl_TextEncoding encoding)106 void throwSQLExceptionWithMsg(const char* msg, unsigned int errorNum,
107                               const css::uno::Reference<css::uno::XInterface>& _context,
108                               const rtl_TextEncoding encoding)
109 {
110     OString errorMsg{ msg };
111     // TODO error code?
112     throw SQLException(OStringToOUString(errorMsg, encoding), _context, OUString(), errorNum,
113                        Any());
114 }
115 
mysqlToOOOType(int eType,int charsetnr)116 sal_Int32 mysqlToOOOType(int eType, int charsetnr) noexcept
117 {
118     // charset number 63 indicates binary
119     switch (eType)
120     {
121         case MYSQL_TYPE_BIT:
122             return css::sdbc::DataType::VARCHAR;
123 
124         case MYSQL_TYPE_TINY:
125             return css::sdbc::DataType::TINYINT;
126 
127         case MYSQL_TYPE_SHORT:
128             return css::sdbc::DataType::SMALLINT;
129 
130         case MYSQL_TYPE_INT24:
131         case MYSQL_TYPE_LONG:
132             return css::sdbc::DataType::INTEGER;
133 
134         case MYSQL_TYPE_LONGLONG:
135             return css::sdbc::DataType::BIGINT;
136 
137         case MYSQL_TYPE_FLOAT:
138             return css::sdbc::DataType::REAL;
139 
140         case MYSQL_TYPE_DOUBLE:
141             return css::sdbc::DataType::DOUBLE;
142 
143         case MYSQL_TYPE_DECIMAL:
144         case MYSQL_TYPE_NEWDECIMAL:
145             return css::sdbc::DataType::DECIMAL;
146 
147         case MYSQL_TYPE_STRING:
148             if (charsetnr == 63)
149                 return css::sdbc::DataType::BINARY;
150             return css::sdbc::DataType::CHAR;
151 
152         case MYSQL_TYPE_ENUM:
153         case MYSQL_TYPE_SET:
154         case MYSQL_TYPE_VAR_STRING:
155             if (charsetnr == 63)
156                 return css::sdbc::DataType::VARBINARY;
157             return css::sdbc::DataType::VARCHAR;
158 
159         case MYSQL_TYPE_BLOB:
160             if (charsetnr == 63)
161                 return css::sdbc::DataType::LONGVARBINARY;
162             return css::sdbc::DataType::LONGVARCHAR;
163 
164         case MYSQL_TYPE_TIMESTAMP:
165         case MYSQL_TYPE_DATETIME:
166             return css::sdbc::DataType::TIMESTAMP;
167 
168         case MYSQL_TYPE_DATE:
169             return css::sdbc::DataType::DATE;
170 
171         case MYSQL_TYPE_TIME:
172             return css::sdbc::DataType::TIME;
173 
174         case MYSQL_TYPE_GEOMETRY:
175             return css::sdbc::DataType::VARCHAR;
176 
177         case MYSQL_TYPE_NULL:
178             return css::sdbc::DataType::SQLNULL;
179     }
180 
181     OSL_FAIL("mysqlToOOOType: unhandled case, falling back to VARCHAR");
182     return css::sdbc::DataType::VARCHAR;
183 }
184 
mysqlStrToOOOType(const OUString & sType)185 sal_Int32 mysqlStrToOOOType(const OUString& sType)
186 {
187     // TODO other types.
188     if (sType.equalsIgnoreAsciiCase("tiny") || sType.equalsIgnoreAsciiCase("tinyint"))
189         return css::sdbc::DataType::TINYINT;
190     if (sType.equalsIgnoreAsciiCase("smallint") || sType.equalsIgnoreAsciiCase("mediumint"))
191         return css::sdbc::DataType::SMALLINT;
192     if (sType.equalsIgnoreAsciiCase("longtext"))
193         return css::sdbc::DataType::LONGVARCHAR;
194     if (sType.equalsIgnoreAsciiCase("int"))
195         return css::sdbc::DataType::INTEGER;
196     if (sType.equalsIgnoreAsciiCase("varchar") || sType.equalsIgnoreAsciiCase("set")
197         || sType.equalsIgnoreAsciiCase("enum"))
198         return css::sdbc::DataType::VARCHAR;
199     if (sType.equalsIgnoreAsciiCase("bigint"))
200         return css::sdbc::DataType::BIGINT;
201     if (sType.equalsIgnoreAsciiCase("blob") || sType.equalsIgnoreAsciiCase("longblob"))
202         return css::sdbc::DataType::BLOB;
203     if (sType.equalsIgnoreAsciiCase("varbinary"))
204         return css::sdbc::DataType::VARBINARY;
205     if (sType.equalsIgnoreAsciiCase("char"))
206         return css::sdbc::DataType::CHAR;
207     if (sType.equalsIgnoreAsciiCase("text"))
208         return css::sdbc::DataType::CLOB;
209     if (sType.equalsIgnoreAsciiCase("binary"))
210         return css::sdbc::DataType::BINARY;
211     if (sType.equalsIgnoreAsciiCase("time"))
212         return css::sdbc::DataType::TIME;
213     if (sType.equalsIgnoreAsciiCase("date"))
214         return css::sdbc::DataType::DATE;
215     if (sType.equalsIgnoreAsciiCase("datetime") || sType.equalsIgnoreAsciiCase("timestamp"))
216         return css::sdbc::DataType::TIMESTAMP;
217     if (sType.equalsIgnoreAsciiCase("decimal"))
218         return css::sdbc::DataType::DECIMAL;
219     if (sType.equalsIgnoreAsciiCase("real") || sType.equalsIgnoreAsciiCase("float"))
220         return css::sdbc::DataType::REAL;
221     if (sType.equalsIgnoreAsciiCase("double"))
222         return css::sdbc::DataType::DOUBLE;
223     if (sType.equalsIgnoreAsciiCase("bit") || sType.equalsIgnoreAsciiCase("bool")
224         || sType.equalsIgnoreAsciiCase("boolean"))
225         return css::sdbc::DataType::BOOLEAN;
226     OSL_FAIL("Unknown type name from string, failing back to varchar.");
227     return css::sdbc::DataType::VARCHAR;
228 }
229 
mysqlTypeToStr(unsigned type,unsigned flags)230 OUString mysqlTypeToStr(unsigned type, unsigned flags)
231 {
232     bool isUnsigned = (flags & UNSIGNED_FLAG) != 0;
233     bool isZerofill = (flags & ZEROFILL_FLAG) != 0;
234     switch (type)
235     {
236         case MYSQL_TYPE_BIT:
237             return OUString{ "BIT" };
238         case MYSQL_TYPE_DECIMAL:
239         case MYSQL_TYPE_NEWDECIMAL:
240             return isUnsigned ? (isZerofill ? OUString{ "DECIMAL UNSIGNED ZEROFILL" }
241                                             : OUString{ "DECIMAL UNSIGNED" })
242                               : OUString{ "DECIMAL" };
243         case MYSQL_TYPE_TINY:
244             return isUnsigned ? (isZerofill ? OUString{ "TINYINT UNSIGNED ZEROFILL" }
245                                             : OUString{ "TINYINT UNSIGNED" })
246                               : OUString{ "TINYINT" };
247         case MYSQL_TYPE_SHORT:
248             return isUnsigned ? (isZerofill ? OUString{ "SMALLINT UNSIGNED ZEROFILL" }
249                                             : OUString{ "SMALLINT UNSIGNED" })
250                               : OUString{ "SMALLINT" };
251         case MYSQL_TYPE_LONG:
252             return isUnsigned ? (isZerofill ? OUString{ "INT UNSIGNED ZEROFILL" }
253                                             : OUString{ "INT UNSIGNED" })
254                               : OUString{ "INT" };
255         case MYSQL_TYPE_FLOAT:
256             return isUnsigned ? (isZerofill ? OUString{ "FLOAT UNSIGNED ZEROFILL" }
257                                             : OUString{ "FLOAT UNSIGNED" })
258                               : OUString{ "FLOAT" };
259         case MYSQL_TYPE_DOUBLE:
260             return isUnsigned ? (isZerofill ? OUString{ "DOUBLE UNSIGNED ZEROFILL" }
261                                             : OUString{ "DOUBLE UNSIGNED" })
262                               : OUString{ "DOUBLE" };
263         case MYSQL_TYPE_NULL:
264             return OUString{ "NULL" };
265         case MYSQL_TYPE_TIMESTAMP:
266             return OUString{ "TIMESTAMP" };
267         case MYSQL_TYPE_LONGLONG:
268             return isUnsigned ? (isZerofill ? OUString{ "BIGINT UNSIGNED ZEROFILL" }
269                                             : OUString{ "BIGINT UNSIGNED" })
270                               : OUString{ "BIGINT" };
271         case MYSQL_TYPE_INT24:
272             return isUnsigned ? (isZerofill ? OUString{ "MEDIUMINT UNSIGNED ZEROFILL" }
273                                             : OUString{ "MEDIUMINT UNSIGNED" })
274                               : OUString{ "MEDIUMINT" };
275         case MYSQL_TYPE_DATE:
276             return OUString{ "DATE" };
277         case MYSQL_TYPE_TIME:
278             return OUString{ "TIME" };
279         case MYSQL_TYPE_DATETIME:
280             return OUString{ "DATETIME" };
281         case MYSQL_TYPE_TINY_BLOB:
282         {
283             return OUString{ "TINYBLOB" };
284         }
285         case MYSQL_TYPE_MEDIUM_BLOB:
286         {
287             return OUString{ "MEDIUMBLOB" };
288         }
289         case MYSQL_TYPE_LONG_BLOB:
290         {
291             return OUString{ "LONGBLOB" };
292         }
293         case MYSQL_TYPE_BLOB:
294         {
295             return OUString{ "BLOB" };
296         }
297         case MYSQL_TYPE_VARCHAR:
298         case MYSQL_TYPE_VAR_STRING:
299             if (flags & ENUM_FLAG)
300             {
301                 return OUString{ "ENUM" };
302             }
303             if (flags & SET_FLAG)
304             {
305                 return OUString{ "SET" };
306             }
307             return OUString{ "VARCHAR" };
308         case MYSQL_TYPE_STRING:
309             if (flags & ENUM_FLAG)
310             {
311                 return OUString{ "ENUM" };
312             }
313             if (flags & SET_FLAG)
314             {
315                 return OUString{ "SET" };
316             }
317             return OUString{ "CHAR" };
318         case MYSQL_TYPE_YEAR:
319             return OUString{ "YEAR" };
320         case MYSQL_TYPE_GEOMETRY:
321             return OUString{ "GEOMETRY" };
322         default:
323             return OUString{ "UNKNOWN" };
324     }
325 }
326 
convert(const::std::string & _string,const rtl_TextEncoding encoding)327 OUString convert(const ::std::string& _string, const rtl_TextEncoding encoding)
328 {
329     return OUString(_string.c_str(), _string.size(), encoding);
330 }
331 
332 } /* namespace */
333 
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
335