1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
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/.
11 #include <rtl/ustrbuf.hxx>
12 #include <sal/log.hxx>
14 #include <com/sun/star/sdbc/DataType.hpp>
15 #include <com/sun/star/sdbc/SQLException.hpp>
16 #include <o3tl/string_view.hxx>
18 using namespace ::connectivity
;
20 using namespace ::com::sun::star
;
21 using namespace ::com::sun::star::sdbc
;
22 using namespace ::com::sun::star::uno
;
24 using namespace firebird
;
26 OUString
firebird::sanitizeIdentifier(std::u16string_view rIdentifier
)
28 std::u16string_view sRet
= o3tl::trim(rIdentifier
);
29 assert(sRet
.size() <= 31); // Firebird identifiers cannot be longer than this.
31 return OUString(sRet
);
34 OUString
firebird::StatusVectorToString(const ISC_STATUS_ARRAY
& rStatusVector
,
35 std::u16string_view rCause
)
38 const ISC_STATUS
* pStatus
= reinterpret_cast<const ISC_STATUS
*>(&rStatusVector
);
40 buf
.append("firebird_sdbc error:");
43 char msg
[512]; // Size is based on suggestion in docs.
44 while(fb_interpret(msg
, sizeof(msg
), &pStatus
))
46 // TODO: verify encoding
48 + OUString(msg
, strlen(msg
), RTL_TEXTENCODING_UTF8
));
53 SAL_WARN("connectivity.firebird", "ignore fb_interpret exception");
55 buf
.append(OUString::Concat("\ncaused by\n'") + rCause
+ "'\n");
57 OUString error
= buf
.makeStringAndClear();
58 SAL_WARN("connectivity.firebird", error
);
62 void firebird::evaluateStatusVector(const ISC_STATUS_ARRAY
& rStatusVector
,
63 std::u16string_view rCause
,
64 const uno::Reference
< XInterface
>& _rxContext
)
66 if (IndicatesError(rStatusVector
))
68 OUString error
= StatusVectorToString(rStatusVector
, rCause
);
69 throw SQLException(error
, _rxContext
, OUString(), 1, Any());
73 static sal_Int32
lcl_getNumberType( short aType
, NumberSubType aSubType
)
77 case NumberSubType::Numeric
:
78 return DataType::NUMERIC
;
79 case NumberSubType::Decimal
:
80 return DataType::DECIMAL
;
85 return DataType::SMALLINT
;
87 return DataType::INTEGER
;
89 return DataType::DOUBLE
;
91 return DataType::BIGINT
;
93 assert(false); // not a number
98 static sal_Int32
lcl_getCharColumnType( short aType
, std::u16string_view sCharset
)
103 if( sCharset
== u
"OCTETS")
104 return DataType::BINARY
;
106 return DataType::CHAR
;
108 if( sCharset
== u
"OCTETS")
109 return DataType::VARBINARY
;
111 return DataType::VARCHAR
;
118 sal_Int32
firebird::ColumnTypeInfo::getSdbcType() const
120 short aType
= m_aType
& ~1; // Remove last bit -- it is used to denote whether column
121 // can store Null, not needed for type determination
122 short aSubType
= m_aSubType
;
126 if(aType
== SQL_SHORT
|| aType
== SQL_LONG
|| aType
== SQL_DOUBLE
127 || aType
== SQL_INT64
)
129 // if scale is set without subtype then imply numeric
130 if( static_cast<NumberSubType
>(aSubType
) == NumberSubType::Other
)
131 aSubType
= static_cast<short>(NumberSubType::Numeric
);
139 return lcl_getCharColumnType(aType
, m_sCharsetName
);
144 return lcl_getNumberType(aType
, static_cast<NumberSubType
>(aSubType
) );
146 return DataType::FLOAT
;
148 return DataType::DOUBLE
;
150 return DataType::TIMESTAMP
;
152 switch (static_cast<BlobSubtype
>(aSubType
))
154 case BlobSubtype::Blob
:
155 return DataType::BLOB
;
156 case BlobSubtype::Clob
:
157 return DataType::CLOB
;
158 case BlobSubtype::Image
:
159 return DataType::LONGVARBINARY
;
161 SAL_WARN("connectivity.firebird", "Unknown subtype for Blob type: " << aSubType
);
162 assert(!"Unknown subtype for Blob type"); // Should never happen
166 return DataType::ARRAY
;
168 return DataType::TIME
;
170 return DataType::DATE
;
172 return DataType::SQLNULL
;
173 case SQL_QUAD
: // Is a "Blob ID" according to the docs
174 return 0; // TODO: verify
176 return DataType::BOOLEAN
;
178 assert(false); // Should never happen
183 OUString
firebird::ColumnTypeInfo::getColumnTypeName() const
185 sal_Int32 nDataType
= this->getSdbcType();
190 case DataType::TINYINT
:
191 return u
"TINYINT"_ustr
;
192 case DataType::SMALLINT
:
193 return u
"SMALLINT"_ustr
;
194 case DataType::INTEGER
:
195 return u
"INTEGER"_ustr
;
196 case DataType::BIGINT
:
197 return u
"BIGINT"_ustr
;
198 case DataType::FLOAT
:
199 return u
"FLOAT"_ustr
;
202 case DataType::DOUBLE
:
203 return u
"DOUBLE"_ustr
;
204 case DataType::NUMERIC
:
205 return u
"NUMERIC"_ustr
;
206 case DataType::DECIMAL
:
207 return u
"DECIMAL"_ustr
;
210 case DataType::VARCHAR
:
211 return u
"VARCHAR"_ustr
;
212 case DataType::LONGVARCHAR
:
213 return u
"LONGVARCHAR"_ustr
;
218 case DataType::TIMESTAMP
:
219 return u
"TIMESTAMP"_ustr
;
220 case DataType::BINARY
:
221 // in Firebird, that is the same datatype "CHAR" as DataType::CHAR,
222 // only with CHARACTER SET OCTETS; we use the synonym CHARACTER
223 // to fool LO into seeing it as different types.
224 return u
"CHARACTER"_ustr
;
225 case DataType::VARBINARY
:
226 // see above comment about DataType::BINARY.
227 return u
"CHARACTER VARYING"_ustr
;
228 case DataType::LONGVARBINARY
:
229 return "BLOB SUB_TYPE " + OUString::number(static_cast<short>(BlobSubtype::Image
));
230 case DataType::ARRAY
:
231 return u
"ARRAY"_ustr
;
233 return u
"BLOB SUB_TYPE BINARY"_ustr
;
235 return u
"BLOB SUB_TYPE TEXT"_ustr
;
236 case DataType::BOOLEAN
:
237 return u
"BOOLEAN"_ustr
;
238 case DataType::SQLNULL
:
241 assert(false); // Should never happen
246 short firebird::getFBTypeFromBlrType(short blrType
)
254 return 0; // No idea if this should be supported
259 return 0; // No idea if this should be supported
271 return SQL_TIMESTAMP
;
274 // case blr_SQL_ARRAY:
275 // return OUString("SQL_ARRAY");
277 return SQL_TYPE_TIME
;
279 return SQL_TYPE_DATE
;
283 // return OUString("SQL_NULL");
289 // If this happens we have hit one of the extra types in ibase.h
290 // look up blr_* for a list, e.g. blr_domain_name, blr_not_nullable etc.
296 void firebird::mallocSQLVAR(XSQLDA
* pSqlda
)
298 // TODO: confirm the sizings below.
299 XSQLVAR
* pVar
= pSqlda
->sqlvar
;
300 for (int i
=0; i
< pSqlda
->sqld
; i
++, pVar
++)
302 int dtype
= (pVar
->sqltype
& ~1); /* drop flag bit for now */
305 pVar
->sqldata
= static_cast<char *>(malloc(sizeof(char)*pVar
->sqllen
));
308 pVar
->sqldata
= static_cast<char *>(malloc(sizeof(char)*pVar
->sqllen
+ 2));
311 pVar
->sqldata
= static_cast<char*>(malloc(sizeof(sal_Int16
)));
314 pVar
->sqldata
= static_cast<char*>(malloc(sizeof(sal_Int32
)));
317 pVar
->sqldata
= static_cast<char *>(malloc(sizeof(float)));
321 pVar
->sqldata
= static_cast<char *>(malloc(sizeof(double)));
324 pVar
->sqldata
= static_cast<char*>(malloc(sizeof(ISC_TIMESTAMP
)));
326 // an ARRAY is in fact a BLOB of a specialized type
327 // See https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-datatypes-bnrytypes.html#fblangref25-datatypes-array
330 pVar
->sqldata
= static_cast<char*>(malloc(sizeof(ISC_QUAD
)));
333 pVar
->sqldata
= static_cast<char*>(malloc(sizeof(ISC_TIME
)));
336 pVar
->sqldata
= static_cast<char*>(malloc(sizeof(ISC_DATE
)));
339 pVar
->sqldata
= static_cast<char *>(malloc(sizeof(sal_Int64
)));
342 pVar
->sqldata
= static_cast<char *>(malloc(sizeof(sal_Bool
)));
344 // See https://www.firebirdsql.org/file/documentation/html/en/refdocs/fblangref25/firebird-25-language-reference.html#fblangref25-datatypes-special-sqlnull
346 pVar
->sqldata
= nullptr;
349 assert(false); // TODO: implement
352 SAL_WARN("connectivity.firebird", "Unknown type: " << dtype
);
356 /* allocate variable to hold NULL status */
357 pVar
->sqlind
= static_cast<short *>(malloc(sizeof(short)));
361 void firebird::freeSQLVAR(XSQLDA
* pSqlda
)
363 XSQLVAR
* pVar
= pSqlda
->sqlvar
;
364 for (int i
=0; i
< pSqlda
->sqld
; i
++, pVar
++)
366 int dtype
= (pVar
->sqltype
& ~1); /* drop flag bit for now */
376 // an ARRAY is in fact a BLOB of a specialized type
377 // See https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref25-datatypes-bnrytypes.html#fblangref25-datatypes-array
387 pVar
->sqldata
= nullptr;
391 // See SQL_NULL case in mallocSQLVAR
392 assert(pVar
->sqldata
== nullptr);
395 assert(false); // TODO: implement
398 SAL_WARN("connectivity.firebird", "Unknown type: " << dtype
);
406 pVar
->sqlind
= nullptr;
411 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */