mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-05-29 07:02:34 +02:00
2018-07-25 Fred Gleason <fredg@paravelsystems.com>
* Fixed a bug in the 'RDEscapeString' function that caused corruption in UTF-8 strings. * Added a UTF-8 complaint MySQL driver in 'drivers/qt3-mysql-utf/'.
This commit is contained in:
parent
c722e4fe09
commit
15f21fb4ec
@ -17214,3 +17214,7 @@
|
||||
* Cleaned up RDConf calls to ensure UTF-8 compatibility.
|
||||
2018-07-23 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Fixed a buffer overflow vulnerability in the 'RDWaveFile' class.
|
||||
2018-07-25 Fred Gleason <fredg@paravelsystems.com>
|
||||
* Fixed a bug in the 'RDEscapeString' function that caused corruption
|
||||
in UTF-8 strings.
|
||||
* Added a UTF-8 complaint MySQL driver in 'drivers/qt3-mysql-utf/'.
|
||||
|
@ -38,6 +38,7 @@ SUBDIRS = icons\
|
||||
conf\
|
||||
debian\
|
||||
docs\
|
||||
drivers\
|
||||
xdg\
|
||||
cae\
|
||||
importers\
|
||||
|
@ -24,7 +24,8 @@ Hostname=localhost
|
||||
Loginname=rduser
|
||||
Password=letmein
|
||||
Database=Rivendell
|
||||
Driver=QMYSQL3
|
||||
Driver=QMYSQL3 ; Stock Latin1-capable driver supplied by TrollTech
|
||||
;Driver=QNYSQLUTF8 ; UTF-8-capable driver packaged within Rivendell
|
||||
|
||||
; The following three settings control the attributes of new DB tables
|
||||
; created by Rivendell.
|
||||
|
@ -213,6 +213,11 @@ AC_CHECK_HEADER(security/pam_appl.h,[],[AC_MSG_ERROR([*** PAM not found ***])])
|
||||
#
|
||||
AC_CHECK_HEADER(soundtouch/SoundTouch.h,[],[AC_MSG_ERROR([*** SoundTouch not found ***])])
|
||||
|
||||
#
|
||||
# Check for MySQL client libraries
|
||||
#
|
||||
MYSQL_CLIENT()
|
||||
|
||||
#
|
||||
# Check for FLAC
|
||||
#
|
||||
@ -495,6 +500,8 @@ AC_CONFIG_FILES([rivendell.spec \
|
||||
rivendell-suse \
|
||||
rdrepld-suse \
|
||||
conf/rd-bin.conf \
|
||||
drivers/Makefile \
|
||||
drivers/qt3-mysql-utf/Makefile \
|
||||
icons/Makefile \
|
||||
helpers/Makefile \
|
||||
lib/rdpaths.h \
|
||||
|
40
drivers/Makefile.am
Normal file
40
drivers/Makefile.am
Normal file
@ -0,0 +1,40 @@
|
||||
## automake.am
|
||||
##
|
||||
## Makefile.am for rivendell/drivers
|
||||
##
|
||||
## (C) Copyright 2018 Fred Gleason <fredg@paravelsystems.com>
|
||||
##
|
||||
## 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 2 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, write to the Free Software
|
||||
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
##
|
||||
## Use automake to process this into a Makefile.in
|
||||
|
||||
SUBDIRS = qt3-mysql-utf
|
||||
|
||||
EXTRA_DIST = drivers.pro
|
||||
|
||||
CLEANFILES = *~\
|
||||
*.idb\
|
||||
*ilk\
|
||||
*.obj\
|
||||
*.pdb\
|
||||
*.qm\
|
||||
moc_*
|
||||
|
||||
MAINTAINERCLEANFILES = *~\
|
||||
*.tar.gz\
|
||||
aclocal.m4\
|
||||
configure\
|
||||
Makefile.in\
|
||||
moc_*
|
22
drivers/drivers.pro
Normal file
22
drivers/drivers.pro
Normal file
@ -0,0 +1,22 @@
|
||||
# drivers.pro
|
||||
#
|
||||
# The drivers/ QMake project file for Rivendell
|
||||
#
|
||||
# (C) Copyright 2018 Fred Gleason <fredg@paravelsystems.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += qt3-mysql-utf
|
103
drivers/qt3-mysql-utf/LICENSE.QPL
Normal file
103
drivers/qt3-mysql-utf/LICENSE.QPL
Normal file
@ -0,0 +1,103 @@
|
||||
THE Q PUBLIC LICENSE
|
||||
version 1.0
|
||||
|
||||
Copyright (C) 1999-2000 Trolltech AS, Norway.
|
||||
Everyone is permitted to copy and
|
||||
distribute this license document.
|
||||
|
||||
The intent of this license is to establish freedom to share and change the
|
||||
software regulated by this license under the open source model.
|
||||
|
||||
This license applies to any software containing a notice placed by the
|
||||
copyright holder saying that it may be distributed under the terms of
|
||||
the Q Public License version 1.0. Such software is herein referred to as
|
||||
the Software. This license covers modification and distribution of the
|
||||
Software, use of third-party application programs based on the Software,
|
||||
and development of free software which uses the Software.
|
||||
|
||||
Granted Rights
|
||||
|
||||
1. You are granted the non-exclusive rights set forth in this license
|
||||
provided you agree to and comply with any and all conditions in this
|
||||
license. Whole or partial distribution of the Software, or software
|
||||
items that link with the Software, in any form signifies acceptance of
|
||||
this license.
|
||||
|
||||
2. You may copy and distribute the Software in unmodified form provided
|
||||
that the entire package, including - but not restricted to - copyright,
|
||||
trademark notices and disclaimers, as released by the initial developer
|
||||
of the Software, is distributed.
|
||||
|
||||
3. You may make modifications to the Software and distribute your
|
||||
modifications, in a form that is separate from the Software, such as
|
||||
patches. The following restrictions apply to modifications:
|
||||
|
||||
a. Modifications must not alter or remove any copyright notices in
|
||||
the Software.
|
||||
|
||||
b. When modifications to the Software are released under this
|
||||
license, a non-exclusive royalty-free right is granted to the
|
||||
initial developer of the Software to distribute your modification
|
||||
in future versions of the Software provided such versions remain
|
||||
available under these terms in addition to any other license(s) of
|
||||
the initial developer.
|
||||
|
||||
4. You may distribute machine-executable forms of the Software or
|
||||
machine-executable forms of modified versions of the Software, provided
|
||||
that you meet these restrictions:
|
||||
|
||||
a. You must include this license document in the distribution.
|
||||
|
||||
b. You must ensure that all recipients of the machine-executable forms
|
||||
are also able to receive the complete machine-readable source code
|
||||
to the distributed Software, including all modifications, without
|
||||
any charge beyond the costs of data transfer, and place prominent
|
||||
notices in the distribution explaining this.
|
||||
|
||||
c. You must ensure that all modifications included in the
|
||||
machine-executable forms are available under the terms of this
|
||||
license.
|
||||
|
||||
5. You may use the original or modified versions of the Software to
|
||||
compile, link and run application programs legally developed by you
|
||||
or by others.
|
||||
|
||||
6. You may develop application programs, reusable components and other
|
||||
software items that link with the original or modified versions of the
|
||||
Software. These items, when distributed, are subject to the following
|
||||
requirements:
|
||||
|
||||
a. You must ensure that all recipients of machine-executable forms of
|
||||
these items are also able to receive and use the complete
|
||||
machine-readable source code to the items without any charge
|
||||
beyond the costs of data transfer.
|
||||
|
||||
b. You must explicitly license all recipients of your items to use
|
||||
and re-distribute original and modified versions of the items in
|
||||
both machine-executable and source code forms. The recipients must
|
||||
be able to do so without any charges whatsoever, and they must be
|
||||
able to re-distribute to anyone they choose.
|
||||
|
||||
|
||||
c. If the items are not available to the general public, and the
|
||||
initial developer of the Software requests a copy of the items,
|
||||
then you must supply one.
|
||||
|
||||
Limitations of Liability
|
||||
|
||||
In no event shall the initial developers or copyright holders be liable
|
||||
for any damages whatsoever, including - but not restricted to - lost
|
||||
revenue or profits or other direct, indirect, special, incidental or
|
||||
consequential damages, even if they have been advised of the possibility
|
||||
of such damages, except to the extent invariable law, if any, provides
|
||||
otherwise.
|
||||
|
||||
No Warranty
|
||||
|
||||
The Software and this license document are provided AS IS with NO WARRANTY
|
||||
OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE.
|
||||
Choice of Law
|
||||
|
||||
This license is governed by the Laws of Norway. Disputes shall be settled
|
||||
by Oslo City Court.
|
63
drivers/qt3-mysql-utf/Makefile.am
Normal file
63
drivers/qt3-mysql-utf/Makefile.am
Normal file
@ -0,0 +1,63 @@
|
||||
## automake.am
|
||||
##
|
||||
## Makefile.am for rivendell/drivers/qt3-mysql-utf
|
||||
##
|
||||
## by Fred Gleason <fredg@paravelsystems.com>
|
||||
## (C) Copyright 2002-2007,2016 Fred Gleason <fredg@paravelsystems.com>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License version 2 as
|
||||
## published by the Free Software Foundation.
|
||||
##
|
||||
## 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, write to the Free Software
|
||||
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
##
|
||||
## Use automake to process this into a Makefile.in
|
||||
##
|
||||
|
||||
AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -DQTDIR=\"@QT_DIR@\" @QT_CXXFLAGS@ @MYSQL_CLIENT_CFLAGS@
|
||||
LIBS = @QT_LIBS@
|
||||
MOC = @QT_MOC@
|
||||
|
||||
# The dependency for qt's Meta Object Compiler (moc)
|
||||
moc_%.cpp: %.h
|
||||
$(MOC) $< -o $@
|
||||
|
||||
install-exec-local:
|
||||
mkdir -p $(DESTDIR)$(QTDIR)/plugins/sqldrivers
|
||||
cp .libs/libqmysqlutf.so.0.0.0 $(DESTDIR)$(QTDIR)/plugins/sqldrivers/libqmysqlutf.so
|
||||
|
||||
uninstall-exec:
|
||||
rm -f $(DESTDIR)$(QTDIR)/plugins/sqldrivers/libqmysqlutf.so
|
||||
|
||||
lib_LTLIBRARIES = libqmysqlutf.la
|
||||
dist_libqmysqlutf_la_SOURCES = qsqlextension.cpp qsqlextension.h\
|
||||
qt3-mysql-utf.cpp qt3-mysql-utf.h
|
||||
|
||||
libqmysqlutf_la_LIBADD = @MYSQL_CLIENT_LIBS@
|
||||
libqmysqlutf_la_LDFLAGS = -rpath `pwd`
|
||||
|
||||
EXTRA_DIST = LICENSE.QPL\
|
||||
qt3-mysql-utf.pro
|
||||
|
||||
CLEANFILES = *~\
|
||||
*.idb\
|
||||
*.ilk\
|
||||
*.lib\
|
||||
*.obj\
|
||||
*.pdb\
|
||||
*.qm\
|
||||
moc_*
|
||||
|
||||
DISTCLEAN = Makefile
|
||||
|
||||
MAINTAINERCLEANFILES = *~\
|
||||
Makefile\
|
||||
Makefile.in\
|
||||
moc_*
|
169
drivers/qt3-mysql-utf/qsqlextension.cpp
Normal file
169
drivers/qt3-mysql-utf/qsqlextension.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Implementation of the QSqlExtension class
|
||||
**
|
||||
** Created : 2002-06-03
|
||||
**
|
||||
** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
|
||||
**
|
||||
** This file is part of the sql module of the Qt GUI Toolkit.
|
||||
**
|
||||
** This file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free
|
||||
** Software Foundation and appearing in the files LICENSE.GPL2
|
||||
** and LICENSE.GPL3 included in the packaging of this file.
|
||||
** Alternatively you may (at your option) use any later version
|
||||
** of the GNU General Public License if such license has been
|
||||
** publicly approved by Trolltech ASA (or its successors, if any)
|
||||
** and the KDE Free Qt Foundation.
|
||||
**
|
||||
** Please review the following information to ensure GNU General
|
||||
** Public Licensing requirements will be met:
|
||||
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** review the following information:
|
||||
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
|
||||
** or contact the sales department at sales@trolltech.com.
|
||||
**
|
||||
** This file may be used under the terms of the Q Public License as
|
||||
** defined by Trolltech ASA and appearing in the file LICENSE.QPL
|
||||
** included in the packaging of this file. Licensees holding valid Qt
|
||||
** Commercial licenses may use this file in accordance with the Qt
|
||||
** Commercial License Agreement provided with the Software.
|
||||
**
|
||||
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
|
||||
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
|
||||
** herein.
|
||||
**
|
||||
**********************************************************************/
|
||||
|
||||
#include "qsqlextension.h"
|
||||
|
||||
#ifndef QT_NO_SQL
|
||||
QSqlExtension::QSqlExtension()
|
||||
: bindm( BindByPosition ), bindCount( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
QSqlExtension::~QSqlExtension()
|
||||
{
|
||||
}
|
||||
|
||||
bool QSqlExtension::prepare( const QString& /*query*/ )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool QSqlExtension::exec()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void QSqlExtension::bindValue( const QString& placeholder, const QVariant& val, QSql::ParameterType tp )
|
||||
{
|
||||
bindm = BindByName;
|
||||
// if the index has already been set when doing emulated named
|
||||
// bindings - don't reset it
|
||||
if ( index.contains( (int)values.count() ) ) {
|
||||
index[ (int)values.count() ] = placeholder;
|
||||
}
|
||||
values[ placeholder ] = Param( val, tp );
|
||||
}
|
||||
|
||||
void QSqlExtension::bindValue( int pos, const QVariant& val, QSql::ParameterType tp )
|
||||
{
|
||||
bindm = BindByPosition;
|
||||
index[ pos ] = QString::number( pos );
|
||||
QString nm = QString::number( pos );
|
||||
values[ nm ] = Param( val, tp );
|
||||
}
|
||||
|
||||
void QSqlExtension::addBindValue( const QVariant& val, QSql::ParameterType tp )
|
||||
{
|
||||
bindm = BindByPosition;
|
||||
bindValue( bindCount++, val, tp );
|
||||
}
|
||||
|
||||
void QSqlExtension::clearValues()
|
||||
{
|
||||
values.clear();
|
||||
bindCount = 0;
|
||||
}
|
||||
|
||||
void QSqlExtension::resetBindCount()
|
||||
{
|
||||
bindCount = 0;
|
||||
}
|
||||
|
||||
void QSqlExtension::clearIndex()
|
||||
{
|
||||
index.clear();
|
||||
holders.clear();
|
||||
}
|
||||
|
||||
void QSqlExtension::clear()
|
||||
{
|
||||
clearValues();
|
||||
clearIndex();
|
||||
}
|
||||
|
||||
QVariant QSqlExtension::parameterValue( const QString& holder )
|
||||
{
|
||||
return values[ holder ].value;
|
||||
}
|
||||
|
||||
QVariant QSqlExtension::parameterValue( int pos )
|
||||
{
|
||||
return values[ index[ pos ] ].value;
|
||||
}
|
||||
|
||||
QVariant QSqlExtension::boundValue( const QString& holder ) const
|
||||
{
|
||||
return values[ holder ].value;
|
||||
}
|
||||
|
||||
QVariant QSqlExtension::boundValue( int pos ) const
|
||||
{
|
||||
return values[ index[ pos ] ].value;
|
||||
}
|
||||
|
||||
QMap<QString, QVariant> QSqlExtension::boundValues() const
|
||||
{
|
||||
QMap<QString, Param>::ConstIterator it;
|
||||
QMap<QString, QVariant> m;
|
||||
if ( bindm == BindByName ) {
|
||||
for ( it = values.begin(); it != values.end(); ++it )
|
||||
m.insert( it.key(), it.data().value );
|
||||
} else {
|
||||
QString key, tmp, fmt;
|
||||
fmt.sprintf( "%%0%dd", QString::number( values.count()-1 ).length() );
|
||||
for ( it = values.begin(); it != values.end(); ++it ) {
|
||||
tmp.sprintf( fmt.ascii(), it.key().toInt() );
|
||||
m.insert( tmp, it.data().value );
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
QSqlExtension::BindMethod QSqlExtension::bindMethod()
|
||||
{
|
||||
return bindm;
|
||||
}
|
||||
|
||||
QSqlDriverExtension::QSqlDriverExtension()
|
||||
{
|
||||
}
|
||||
|
||||
QSqlDriverExtension::~QSqlDriverExtension()
|
||||
{
|
||||
}
|
||||
|
||||
QSqlOpenExtension::QSqlOpenExtension()
|
||||
{
|
||||
}
|
||||
|
||||
QSqlOpenExtension::~QSqlOpenExtension()
|
||||
{
|
||||
}
|
||||
#endif
|
148
drivers/qt3-mysql-utf/qsqlextension.h
Normal file
148
drivers/qt3-mysql-utf/qsqlextension.h
Normal file
@ -0,0 +1,148 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Definition of the QSqlExtension class
|
||||
**
|
||||
** Created : 2002-06-03
|
||||
**
|
||||
** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
|
||||
**
|
||||
** This file is part of the sql module of the Qt GUI Toolkit.
|
||||
**
|
||||
** This file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free
|
||||
** Software Foundation and appearing in the file COPYING
|
||||
** included in the packaging of this file.
|
||||
** Alternatively you may (at your option) use any later version
|
||||
** of the GNU General Public License if such license has been
|
||||
** publicly approved by Trolltech ASA (or its successors, if any)
|
||||
** and the KDE Free Qt Foundation.
|
||||
**
|
||||
** Please review the following information to ensure GNU General
|
||||
** Public Licensing requirements will be met:
|
||||
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** review the following information:
|
||||
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
|
||||
** or contact the sales department at sales@trolltech.com.
|
||||
**
|
||||
** This file may be used under the terms of the Q Public License as
|
||||
** defined by Trolltech ASA and appearing in the file LICENSE.QPL
|
||||
** included in the packaging of this file. Licensees holding valid Qt
|
||||
** Commercial licenses may use this file in accordance with the Qt
|
||||
** Commercial License Agreement provided with the Software.
|
||||
**
|
||||
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
|
||||
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
|
||||
** herein.
|
||||
**
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef QSQLEXTENSION_H
|
||||
#define QSQLEXTENSION_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of other Qt classes. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef QT_H
|
||||
#include "qmap.h"
|
||||
#include "qvaluevector.h"
|
||||
#include "qstring.h"
|
||||
#include "qvariant.h"
|
||||
#include "qsql.h"
|
||||
#endif // QT_H
|
||||
|
||||
#ifndef QT_NO_SQL
|
||||
|
||||
#if !defined( QT_MODULE_SQL ) || defined( QT_LICENSE_PROFESSIONAL )
|
||||
#define QM_EXPORT_SQL
|
||||
#define QM_TEMPLATE_EXTERN_SQL
|
||||
#else
|
||||
#define QM_EXPORT_SQL Q_EXPORT
|
||||
#define QM_TEMPLATE_EXTERN_SQL Q_TEMPLATE_EXTERN
|
||||
#endif
|
||||
|
||||
struct Param {
|
||||
Param( const QVariant& v = QVariant(), QSql::ParameterType t = QSql::In ): value( v ), typ( t ) {}
|
||||
QVariant value;
|
||||
QSql::ParameterType typ;
|
||||
Q_DUMMY_COMPARISON_OPERATOR(Param)
|
||||
};
|
||||
|
||||
struct Holder {
|
||||
Holder( const QString& hldr = QString::null, int pos = -1 ): holderName( hldr ), holderPos( pos ) {}
|
||||
bool operator==( const Holder& h ) const { return h.holderPos == holderPos && h.holderName == holderName; }
|
||||
bool operator!=( const Holder& h ) const { return h.holderPos != holderPos || h.holderName != holderName; }
|
||||
QString holderName;
|
||||
int holderPos;
|
||||
};
|
||||
|
||||
#define Q_DEFINED_QSQLEXTENSION
|
||||
#include "qwinexport.h"
|
||||
|
||||
class QM_EXPORT_SQL QSqlExtension {
|
||||
public:
|
||||
QSqlExtension();
|
||||
virtual ~QSqlExtension();
|
||||
virtual bool prepare( const QString& query );
|
||||
virtual bool exec();
|
||||
virtual void bindValue( const QString& holder, const QVariant& value, QSql::ParameterType = QSql::In );
|
||||
virtual void bindValue( int pos, const QVariant& value, QSql::ParameterType = QSql::In );
|
||||
virtual void addBindValue( const QVariant& value, QSql::ParameterType = QSql::In );
|
||||
virtual QVariant parameterValue( const QString& holder );
|
||||
virtual QVariant parameterValue( int pos );
|
||||
QVariant boundValue( const QString& holder ) const;
|
||||
QVariant boundValue( int pos ) const;
|
||||
QMap<QString, QVariant> boundValues() const;
|
||||
void clear();
|
||||
void clearValues();
|
||||
void clearIndex();
|
||||
void resetBindCount();
|
||||
|
||||
enum BindMethod { BindByPosition, BindByName };
|
||||
BindMethod bindMethod(); // ### 4.0: make this const
|
||||
BindMethod bindm;
|
||||
int bindCount;
|
||||
|
||||
QMap<int, QString> index;
|
||||
typedef QMap<QString, Param> ValueMap;
|
||||
ValueMap values;
|
||||
|
||||
// convenience container for QSqlQuery
|
||||
// to map holders <-> positions
|
||||
typedef QValueVector<Holder> HolderVector;
|
||||
HolderVector holders;
|
||||
};
|
||||
|
||||
class QM_EXPORT_SQL QSqlDriverExtension
|
||||
{
|
||||
public:
|
||||
QSqlDriverExtension();
|
||||
virtual ~QSqlDriverExtension();
|
||||
virtual bool isOpen() const = 0;
|
||||
};
|
||||
|
||||
class QM_EXPORT_SQL QSqlOpenExtension
|
||||
{
|
||||
public:
|
||||
QSqlOpenExtension();
|
||||
virtual ~QSqlOpenExtension();
|
||||
virtual bool open( const QString& db,
|
||||
const QString& user,
|
||||
const QString& password,
|
||||
const QString& host,
|
||||
int port,
|
||||
const QString& connOpts ) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
781
drivers/qt3-mysql-utf/qt3-mysql-utf.cpp
Normal file
781
drivers/qt3-mysql-utf/qt3-mysql-utf.cpp
Normal file
@ -0,0 +1,781 @@
|
||||
// qt3-mysql-utf.cpp
|
||||
//
|
||||
// Qt3 SQL plug-in for MySQL with Unicode UTF-8 support
|
||||
// (C) Copyright 2018 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// Based on the stock Qt3 MySQL driver
|
||||
// Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
|
||||
//
|
||||
// This file may be used under the terms of the Q Public License as
|
||||
// defined by Trolltech ASA and appearing in the file LICENSE.QPL
|
||||
// included in the packaging of this file. Licensees holding valid Qt
|
||||
// Commercial licenses may use this file in accordance with the Qt
|
||||
// Commercial License Agreement provided with the Software.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
//
|
||||
// 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, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
#include "qt3-mysql-utf.h"
|
||||
#include "qsqlextension.h"
|
||||
|
||||
#include <qdatetime.h>
|
||||
#include <qvaluevector.h>
|
||||
#include <qsqlrecord.h>
|
||||
|
||||
#define QMYSQLUTF_DRIVER_NAME "QMYSQLUTF8"
|
||||
|
||||
QPtrDict<QSqlOpenExtension> *qSqlOpenExtDict();
|
||||
|
||||
static int qMySqlConnectionCount = 0;
|
||||
static bool qMySqlInitHandledByUser = FALSE;
|
||||
|
||||
class QMYSQLUTFOpenExtension : public QSqlOpenExtension
|
||||
{
|
||||
public:
|
||||
QMYSQLUTFOpenExtension( QMYSQLUTFDriver *dri )
|
||||
: QSqlOpenExtension(), driver(dri) {}
|
||||
~QMYSQLUTFOpenExtension() {}
|
||||
|
||||
bool open( const QString& db,
|
||||
const QString& user,
|
||||
const QString& password,
|
||||
const QString& host,
|
||||
int port,
|
||||
const QString& connOpts );
|
||||
|
||||
private:
|
||||
QMYSQLUTFDriver *driver;
|
||||
};
|
||||
|
||||
bool QMYSQLUTFOpenExtension::open( const QString& db,
|
||||
const QString& user,
|
||||
const QString& password,
|
||||
const QString& host,
|
||||
int port,
|
||||
const QString& connOpts )
|
||||
{
|
||||
return driver->open( db, user, password, host, port, connOpts );
|
||||
}
|
||||
|
||||
class QMYSQLUTFDriverPrivate
|
||||
{
|
||||
public:
|
||||
QMYSQLUTFDriverPrivate() : mysql(0) {}
|
||||
MYSQL* mysql;
|
||||
};
|
||||
|
||||
class QMYSQLUTFResultPrivate : public QMYSQLUTFDriverPrivate
|
||||
{
|
||||
public:
|
||||
QMYSQLUTFResultPrivate() : QMYSQLUTFDriverPrivate(), result(0) {}
|
||||
MYSQL_RES* result;
|
||||
MYSQL_ROW row;
|
||||
QValueVector<QVariant::Type> fieldTypes;
|
||||
};
|
||||
|
||||
QSqlError qMakeError( const QString& err, int type, const QMYSQLUTFDriverPrivate* p )
|
||||
{
|
||||
return QSqlError(QMYSQLUTF_DRIVER_NAME ": " + err, QString(mysql_error( p->mysql )), type, mysql_errno( p->mysql ));
|
||||
}
|
||||
|
||||
QVariant::Type qDecodeMYSQLType( int mysqltype, uint flags )
|
||||
{
|
||||
QVariant::Type type;
|
||||
switch ( mysqltype ) {
|
||||
case FIELD_TYPE_TINY :
|
||||
case FIELD_TYPE_SHORT :
|
||||
case FIELD_TYPE_LONG :
|
||||
case FIELD_TYPE_INT24 :
|
||||
type = (flags & UNSIGNED_FLAG) ? QVariant::UInt : QVariant::Int;
|
||||
break;
|
||||
case FIELD_TYPE_YEAR :
|
||||
type = QVariant::Int;
|
||||
break;
|
||||
case FIELD_TYPE_LONGLONG :
|
||||
type = (flags & UNSIGNED_FLAG) ? QVariant::ULongLong : QVariant::LongLong;
|
||||
break;
|
||||
case FIELD_TYPE_DECIMAL :
|
||||
case FIELD_TYPE_FLOAT :
|
||||
case FIELD_TYPE_DOUBLE :
|
||||
type = QVariant::Double;
|
||||
break;
|
||||
case FIELD_TYPE_DATE :
|
||||
type = QVariant::Date;
|
||||
break;
|
||||
case FIELD_TYPE_TIME :
|
||||
type = QVariant::Time;
|
||||
break;
|
||||
case FIELD_TYPE_DATETIME :
|
||||
case FIELD_TYPE_TIMESTAMP :
|
||||
type = QVariant::DateTime;
|
||||
break;
|
||||
case FIELD_TYPE_BLOB :
|
||||
case FIELD_TYPE_TINY_BLOB :
|
||||
case FIELD_TYPE_MEDIUM_BLOB :
|
||||
case FIELD_TYPE_LONG_BLOB :
|
||||
type = (flags & BINARY_FLAG) ? QVariant::ByteArray : QVariant::CString;
|
||||
break;
|
||||
default:
|
||||
case FIELD_TYPE_ENUM :
|
||||
case FIELD_TYPE_SET :
|
||||
case FIELD_TYPE_STRING :
|
||||
case FIELD_TYPE_VAR_STRING :
|
||||
type = QVariant::String;
|
||||
break;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
QMYSQLUTFResult::QMYSQLUTFResult( const QMYSQLUTFDriver* db )
|
||||
: QSqlResult( db )
|
||||
{
|
||||
d = new QMYSQLUTFResultPrivate();
|
||||
d->mysql = db->d->mysql;
|
||||
}
|
||||
|
||||
QMYSQLUTFResult::~QMYSQLUTFResult()
|
||||
{
|
||||
cleanup();
|
||||
delete d;
|
||||
}
|
||||
|
||||
MYSQL_RES* QMYSQLUTFResult::result()
|
||||
{
|
||||
return d->result;
|
||||
}
|
||||
|
||||
void QMYSQLUTFResult::cleanup()
|
||||
{
|
||||
if ( d->result ) {
|
||||
mysql_free_result( d->result );
|
||||
}
|
||||
d->result = NULL;
|
||||
d->row = NULL;
|
||||
setAt( -1 );
|
||||
setActive( FALSE );
|
||||
}
|
||||
|
||||
bool QMYSQLUTFResult::fetch( int i )
|
||||
{
|
||||
if ( isForwardOnly() ) { // fake a forward seek
|
||||
if ( at() < i ) {
|
||||
int x = i - at();
|
||||
while ( --x && fetchNext() );
|
||||
return fetchNext();
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if ( at() == i )
|
||||
return TRUE;
|
||||
mysql_data_seek( d->result, i );
|
||||
d->row = mysql_fetch_row( d->result );
|
||||
if ( !d->row )
|
||||
return FALSE;
|
||||
setAt( i );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool QMYSQLUTFResult::fetchNext()
|
||||
{
|
||||
d->row = mysql_fetch_row( d->result );
|
||||
if ( !d->row )
|
||||
return FALSE;
|
||||
setAt( at() + 1 );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool QMYSQLUTFResult::fetchLast()
|
||||
{
|
||||
if ( isForwardOnly() ) { // fake this since MySQL can't seek on forward only queries
|
||||
bool success = fetchNext(); // did we move at all?
|
||||
while ( fetchNext() );
|
||||
return success;
|
||||
}
|
||||
my_ulonglong numRows = mysql_num_rows( d->result );
|
||||
if ( !numRows )
|
||||
return FALSE;
|
||||
return fetch( numRows - 1 );
|
||||
}
|
||||
|
||||
bool QMYSQLUTFResult::fetchFirst()
|
||||
{
|
||||
if ( isForwardOnly() ) // again, fake it
|
||||
return fetchNext();
|
||||
return fetch( 0 );
|
||||
}
|
||||
|
||||
QVariant QMYSQLUTFResult::data( int field )
|
||||
{
|
||||
if ( !isSelect() || field >= (int) d->fieldTypes.count() ) {
|
||||
qWarning( "QMYSQLUTFResult::data: column %d out of range", field );
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QString val( d->row[field] );
|
||||
switch ( d->fieldTypes.at( field ) ) {
|
||||
case QVariant::LongLong:
|
||||
return QVariant( val.toLongLong() );
|
||||
case QVariant::ULongLong:
|
||||
return QVariant( val.toULongLong() );
|
||||
case QVariant::Int:
|
||||
return QVariant( val.toInt() );
|
||||
case QVariant::UInt:
|
||||
return QVariant( val.toUInt() );
|
||||
case QVariant::Double:
|
||||
return QVariant( val.toDouble() );
|
||||
case QVariant::Date:
|
||||
if ( val.isEmpty() ) {
|
||||
return QVariant( QDate() );
|
||||
} else {
|
||||
return QVariant( QDate::fromString( val, Qt::ISODate ) );
|
||||
}
|
||||
case QVariant::Time:
|
||||
if ( val.isEmpty() ) {
|
||||
return QVariant( QTime() );
|
||||
} else {
|
||||
return QVariant( QTime::fromString( val, Qt::ISODate ) );
|
||||
}
|
||||
case QVariant::DateTime:
|
||||
if ( val.isEmpty() )
|
||||
return QVariant( QDateTime() );
|
||||
if ( val.length() == 14u )
|
||||
// TIMESTAMPS have the format yyyyMMddhhmmss
|
||||
val.insert(4, "-").insert(7, "-").insert(10, 'T').insert(13, ':').insert(16, ':');
|
||||
return QVariant( QDateTime::fromString( val, Qt::ISODate ) );
|
||||
case QVariant::ByteArray: {
|
||||
unsigned long* fl = mysql_fetch_lengths( d->result );
|
||||
QByteArray ba;
|
||||
ba.duplicate( d->row[field], fl[field] );
|
||||
return QVariant( ba );
|
||||
}
|
||||
default:
|
||||
case QVariant::String:
|
||||
case QVariant::CString:
|
||||
return QVariant(QString::fromUtf8(d->row[field] ));
|
||||
}
|
||||
#ifdef QT_CHECK_RANGE
|
||||
qWarning("QMYSQLUTFResult::data: unknown data type");
|
||||
#endif
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool QMYSQLUTFResult::isNull( int field )
|
||||
{
|
||||
if ( d->row[field] == NULL )
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool QMYSQLUTFResult::reset ( const QString& query )
|
||||
{
|
||||
if ( !driver() )
|
||||
return FALSE;
|
||||
if ( !driver()-> isOpen() || driver()->isOpenError() )
|
||||
return FALSE;
|
||||
cleanup();
|
||||
|
||||
QCString encQuery = query.utf8();
|
||||
if ( mysql_real_query( d->mysql, encQuery, encQuery.length() ) ) {
|
||||
setLastError( qMakeError("Unable to execute query", QSqlError::Statement, d ) );
|
||||
return FALSE;
|
||||
}
|
||||
if ( isForwardOnly() ) {
|
||||
if ( isActive() || isValid() ) // have to empty the results from previous query
|
||||
fetchLast();
|
||||
d->result = mysql_use_result( d->mysql );
|
||||
} else {
|
||||
d->result = mysql_store_result( d->mysql );
|
||||
}
|
||||
if ( !d->result && mysql_field_count( d->mysql ) > 0 ) {
|
||||
setLastError( qMakeError( "Unable to store result", QSqlError::Statement, d ) );
|
||||
return FALSE;
|
||||
}
|
||||
int numFields = mysql_field_count( d->mysql );
|
||||
setSelect( !( numFields == 0) );
|
||||
d->fieldTypes.resize( numFields );
|
||||
if ( isSelect() ) {
|
||||
for( int i = 0; i < numFields; i++) {
|
||||
MYSQL_FIELD* field = mysql_fetch_field_direct( d->result, i );
|
||||
if ( field->type == FIELD_TYPE_DECIMAL )
|
||||
d->fieldTypes[i] = QVariant::String;
|
||||
else
|
||||
d->fieldTypes[i] = qDecodeMYSQLType( field->type, field->flags );
|
||||
}
|
||||
}
|
||||
setActive( TRUE );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int QMYSQLUTFResult::size()
|
||||
{
|
||||
return isSelect() ? (int)mysql_num_rows( d->result ) : -1;
|
||||
}
|
||||
|
||||
int QMYSQLUTFResult::numRowsAffected()
|
||||
{
|
||||
return (int)mysql_affected_rows( d->mysql );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
static void qServerEnd()
|
||||
{
|
||||
#ifndef Q_NO_MYSQL_EMBEDDED
|
||||
# if MYSQL_VERSION_ID >= 40000
|
||||
mysql_server_end();
|
||||
# endif // MYSQL_VERSION_ID
|
||||
#endif // Q_NO_MYSQL_EMBEDDED
|
||||
}
|
||||
|
||||
static void qServerInit()
|
||||
{
|
||||
#ifndef Q_NO_MYSQL_EMBEDDED
|
||||
# if MYSQL_VERSION_ID >= 40000
|
||||
if ( qMySqlInitHandledByUser || qMySqlConnectionCount > 1 )
|
||||
return;
|
||||
|
||||
// this should only be called once
|
||||
// has no effect on client/server library
|
||||
// but is vital for the embedded lib
|
||||
if ( mysql_server_init( 0, 0, 0 ) ) {
|
||||
# ifdef QT_CHECK_RANGE
|
||||
qWarning( "QMYSQLUTFDriver::qServerInit: unable to start server." );
|
||||
# endif
|
||||
}
|
||||
|
||||
# endif // MYSQL_VERSION_ID
|
||||
#endif // Q_NO_MYSQL_EMBEDDED
|
||||
}
|
||||
|
||||
QMYSQLUTFDriver::QMYSQLUTFDriver( QObject * parent, const char * name )
|
||||
: QSqlDriver( parent, name ? name : QMYSQLUTF_DRIVER_NAME )
|
||||
{
|
||||
init();
|
||||
qServerInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Create a driver instance with an already open connection handle.
|
||||
*/
|
||||
|
||||
QMYSQLUTFDriver::QMYSQLUTFDriver( MYSQL * con, QObject * parent, const char * name )
|
||||
: QSqlDriver( parent, name ? name : QMYSQLUTF_DRIVER_NAME )
|
||||
{
|
||||
init();
|
||||
if ( con ) {
|
||||
d->mysql = (MYSQL *) con;
|
||||
setOpen( TRUE );
|
||||
setOpenError( FALSE );
|
||||
if (qMySqlConnectionCount == 1)
|
||||
qMySqlInitHandledByUser = TRUE;
|
||||
} else {
|
||||
qServerInit();
|
||||
}
|
||||
}
|
||||
|
||||
void QMYSQLUTFDriver::init()
|
||||
{
|
||||
// qSqlOpenExtDict()->insert( this, new QMYSQLUTFOpenExtension(this) );
|
||||
d = new QMYSQLUTFDriverPrivate();
|
||||
d->mysql = 0;
|
||||
qMySqlConnectionCount++;
|
||||
}
|
||||
|
||||
QMYSQLUTFDriver::~QMYSQLUTFDriver()
|
||||
{
|
||||
qMySqlConnectionCount--;
|
||||
if (qMySqlConnectionCount == 0 && !qMySqlInitHandledByUser)
|
||||
qServerEnd();
|
||||
|
||||
delete d;
|
||||
|
||||
if ( !qSqlOpenExtDict()->isEmpty() ) {
|
||||
QSqlOpenExtension *ext = qSqlOpenExtDict()->take( this );
|
||||
delete ext;
|
||||
}
|
||||
}
|
||||
|
||||
bool QMYSQLUTFDriver::hasFeature( DriverFeature f ) const
|
||||
{
|
||||
switch ( f ) {
|
||||
case Transactions:
|
||||
// CLIENT_TRANSACTION should be defined in all recent mysql client libs > 3.23.34
|
||||
#ifdef CLIENT_TRANSACTIONS
|
||||
if ( d->mysql ) {
|
||||
if ( ( d->mysql->server_capabilities & CLIENT_TRANSACTIONS ) == CLIENT_TRANSACTIONS )
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
case QuerySize:
|
||||
return TRUE;
|
||||
case BLOB:
|
||||
return TRUE;
|
||||
case Unicode:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
bool QMYSQLUTFDriver::open( const QString& db,
|
||||
const QString& user,
|
||||
const QString& password,
|
||||
const QString& host,
|
||||
int port)
|
||||
{
|
||||
return open(db,user,password,host,port,"");
|
||||
}
|
||||
|
||||
bool QMYSQLUTFDriver::open( const QString& db,
|
||||
const QString& user,
|
||||
const QString& password,
|
||||
const QString& host,
|
||||
int port,
|
||||
const QString& connOpts )
|
||||
{
|
||||
if ( isOpen() )
|
||||
close();
|
||||
|
||||
unsigned int optionFlags = 0;
|
||||
|
||||
QStringList raw = QStringList::split( ';', connOpts );
|
||||
QStringList opts;
|
||||
QStringList::ConstIterator it;
|
||||
|
||||
// extract the real options from the string
|
||||
for ( it = raw.begin(); it != raw.end(); ++it ) {
|
||||
QString tmp( *it );
|
||||
int idx;
|
||||
if ( (idx = tmp.find( '=' )) != -1 ) {
|
||||
QString val( tmp.mid( idx + 1 ) );
|
||||
val.simplifyWhiteSpace();
|
||||
if ( val == "TRUE" || val == "1" )
|
||||
opts << tmp.left( idx );
|
||||
else
|
||||
qWarning( "QMYSQLUTFDriver::open: Illegal connect option value '%s'", tmp.latin1() );
|
||||
} else {
|
||||
opts << tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for ( it = opts.begin(); it != opts.end(); ++it ) {
|
||||
QString opt( (*it).upper() );
|
||||
if ( opt == "CLIENT_COMPRESS" )
|
||||
optionFlags |= CLIENT_COMPRESS;
|
||||
else if ( opt == "CLIENT_FOUND_ROWS" )
|
||||
optionFlags |= CLIENT_FOUND_ROWS;
|
||||
else if ( opt == "CLIENT_IGNORE_SPACE" )
|
||||
optionFlags |= CLIENT_IGNORE_SPACE;
|
||||
else if ( opt == "CLIENT_INTERACTIVE" )
|
||||
optionFlags |= CLIENT_INTERACTIVE;
|
||||
else if ( opt == "CLIENT_NO_SCHEMA" )
|
||||
optionFlags |= CLIENT_NO_SCHEMA;
|
||||
else if ( opt == "CLIENT_ODBC" )
|
||||
optionFlags |= CLIENT_ODBC;
|
||||
else if ( opt == "CLIENT_SSL" )
|
||||
optionFlags |= CLIENT_SSL;
|
||||
else
|
||||
qWarning( "QMYSQLUTFDriver::open: Unknown connect option '%s'", (*it).latin1() );
|
||||
}
|
||||
|
||||
if ( (d->mysql = mysql_init((MYSQL*) 0)) &&
|
||||
mysql_real_connect( d->mysql,
|
||||
host,
|
||||
user,
|
||||
password,
|
||||
db.isNull() ? QString("") : db,
|
||||
(port > -1) ? port : 0,
|
||||
NULL,
|
||||
optionFlags ) )
|
||||
{
|
||||
if ( !db.isEmpty() && mysql_select_db( d->mysql, db )) {
|
||||
setLastError( qMakeError("Unable open database '" + db + "'", QSqlError::Connection, d ) );
|
||||
mysql_close( d->mysql );
|
||||
setOpenError( TRUE );
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
setLastError( qMakeError( "Unable to connect", QSqlError::Connection, d ) );
|
||||
mysql_close( d->mysql );
|
||||
setOpenError( TRUE );
|
||||
return FALSE;
|
||||
}
|
||||
setOpen( TRUE );
|
||||
setOpenError( FALSE );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void QMYSQLUTFDriver::close()
|
||||
{
|
||||
if ( isOpen() ) {
|
||||
mysql_close( d->mysql );
|
||||
setOpen( FALSE );
|
||||
setOpenError( FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
QSqlQuery QMYSQLUTFDriver::createQuery() const
|
||||
{
|
||||
return QSqlQuery( new QMYSQLUTFResult( this ) );
|
||||
}
|
||||
|
||||
QStringList QMYSQLUTFDriver::tables( const QString& typeName ) const
|
||||
{
|
||||
QStringList tl;
|
||||
if ( !isOpen() )
|
||||
return tl;
|
||||
if ( !typeName.isEmpty() && !(typeName.toInt() & (int)QSql::Tables) )
|
||||
return tl;
|
||||
|
||||
MYSQL_RES* tableRes = mysql_list_tables( d->mysql, NULL );
|
||||
MYSQL_ROW row;
|
||||
int i = 0;
|
||||
while ( tableRes && TRUE ) {
|
||||
mysql_data_seek( tableRes, i );
|
||||
row = mysql_fetch_row( tableRes );
|
||||
if ( !row )
|
||||
break;
|
||||
tl.append( QString(row[0]) );
|
||||
i++;
|
||||
}
|
||||
mysql_free_result( tableRes );
|
||||
return tl;
|
||||
}
|
||||
|
||||
QSqlIndex QMYSQLUTFDriver::primaryIndex( const QString& tablename ) const
|
||||
{
|
||||
QSqlIndex idx;
|
||||
if ( !isOpen() )
|
||||
return idx;
|
||||
QSqlQuery i = createQuery();
|
||||
QString stmt( "show index from %1;" );
|
||||
QSqlRecord fil = record( tablename );
|
||||
i.exec( stmt.arg( tablename ) );
|
||||
while ( i.isActive() && i.next() ) {
|
||||
if ( i.value(2).toString() == "PRIMARY" ) {
|
||||
idx.append( *fil.field( i.value(4).toString() ) );
|
||||
idx.setCursorName( i.value(0).toString() );
|
||||
idx.setName( i.value(2).toString() );
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
QSqlRecord QMYSQLUTFDriver::record( const QString& tablename ) const
|
||||
{
|
||||
QSqlRecord fil;
|
||||
if ( !isOpen() )
|
||||
return fil;
|
||||
MYSQL_RES* r = mysql_list_fields( d->mysql, tablename.local8Bit().data(), 0);
|
||||
if ( !r ) {
|
||||
return fil;
|
||||
}
|
||||
MYSQL_FIELD* field;
|
||||
while ( (field = mysql_fetch_field( r ))) {
|
||||
QSqlField f ( QString( field->name ) , qDecodeMYSQLType( (int)field->type, field->flags ) );
|
||||
fil.append ( f );
|
||||
}
|
||||
mysql_free_result( r );
|
||||
return fil;
|
||||
}
|
||||
|
||||
QSqlRecord QMYSQLUTFDriver::record( const QSqlQuery& query ) const
|
||||
{
|
||||
QSqlRecord fil;
|
||||
if ( !isOpen() )
|
||||
return fil;
|
||||
if ( query.isActive() && query.isSelect() && query.driver() == this ) {
|
||||
QMYSQLUTFResult* result = (QMYSQLUTFResult*)query.result();
|
||||
QMYSQLUTFResultPrivate* p = result->d;
|
||||
if ( !mysql_errno( p->mysql ) ) {
|
||||
for ( ;; ) {
|
||||
MYSQL_FIELD* f = mysql_fetch_field( p->result );
|
||||
if ( f ) {
|
||||
QSqlField fi( QString((const char*)f->name), qDecodeMYSQLType( f->type, f->flags ) );
|
||||
fil.append( fi );
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
mysql_field_seek( p->result, 0 );
|
||||
}
|
||||
return fil;
|
||||
}
|
||||
|
||||
QSqlRecordInfo QMYSQLUTFDriver::recordInfo( const QString& tablename ) const
|
||||
{
|
||||
QSqlRecordInfo info;
|
||||
if ( !isOpen() )
|
||||
return info;
|
||||
MYSQL_RES* r = mysql_list_fields( d->mysql, tablename.local8Bit().data(), 0);
|
||||
if ( !r ) {
|
||||
return info;
|
||||
}
|
||||
MYSQL_FIELD* field;
|
||||
while ( (field = mysql_fetch_field( r ))) {
|
||||
info.append ( QSqlFieldInfo( QString( field->name ),
|
||||
qDecodeMYSQLType( (int)field->type, field->flags ),
|
||||
IS_NOT_NULL( field->flags ),
|
||||
(int)field->length,
|
||||
(int)field->decimals,
|
||||
QString( field->def ),
|
||||
(int)field->type ) );
|
||||
}
|
||||
mysql_free_result( r );
|
||||
return info;
|
||||
}
|
||||
|
||||
QSqlRecordInfo QMYSQLUTFDriver::recordInfo( const QSqlQuery& query ) const
|
||||
{
|
||||
QSqlRecordInfo info;
|
||||
if ( !isOpen() )
|
||||
return info;
|
||||
if ( query.isActive() && query.isSelect() && query.driver() == this ) {
|
||||
QMYSQLUTFResult* result = (QMYSQLUTFResult*)query.result();
|
||||
QMYSQLUTFResultPrivate* p = result->d;
|
||||
if ( !mysql_errno( p->mysql ) ) {
|
||||
for ( ;; ) {
|
||||
MYSQL_FIELD* field = mysql_fetch_field( p->result );
|
||||
if ( field ) {
|
||||
info.append ( QSqlFieldInfo( QString( field->name ),
|
||||
qDecodeMYSQLType( (int)field->type, field->flags ),
|
||||
IS_NOT_NULL( field->flags ),
|
||||
(int)field->length,
|
||||
(int)field->decimals,
|
||||
QVariant(),
|
||||
(int)field->type ) );
|
||||
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
mysql_field_seek( p->result, 0 );
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
MYSQL* QMYSQLUTFDriver::mysql()
|
||||
{
|
||||
return d->mysql;
|
||||
}
|
||||
|
||||
bool QMYSQLUTFDriver::beginTransaction()
|
||||
{
|
||||
#ifndef CLIENT_TRANSACTIONS
|
||||
return FALSE;
|
||||
#endif
|
||||
if ( !isOpen() ) {
|
||||
#ifdef QT_CHECK_RANGE
|
||||
qWarning( "QMYSQLUTFDriver::beginTransaction: Database not open" );
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
if ( mysql_query( d->mysql, "BEGIN WORK" ) ) {
|
||||
setLastError( qMakeError("Unable to begin transaction", QSqlError::Statement, d ) );
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool QMYSQLUTFDriver::commitTransaction()
|
||||
{
|
||||
#ifndef CLIENT_TRANSACTIONS
|
||||
return FALSE;
|
||||
#endif
|
||||
if ( !isOpen() ) {
|
||||
#ifdef QT_CHECK_RANGE
|
||||
qWarning( "QMYSQLUTFDriver::commitTransaction: Database not open" );
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
if ( mysql_query( d->mysql, "COMMIT" ) ) {
|
||||
setLastError( qMakeError("Unable to commit transaction", QSqlError::Statement, d ) );
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool QMYSQLUTFDriver::rollbackTransaction()
|
||||
{
|
||||
#ifndef CLIENT_TRANSACTIONS
|
||||
return FALSE;
|
||||
#endif
|
||||
if ( !isOpen() ) {
|
||||
#ifdef QT_CHECK_RANGE
|
||||
qWarning( "QMYSQLUTFDriver::rollbackTransaction: Database not open" );
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
if ( mysql_query( d->mysql, "ROLLBACK" ) ) {
|
||||
setLastError( qMakeError("Unable to rollback transaction", QSqlError::Statement, d ) );
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
QString QMYSQLUTFDriver::formatValue( const QSqlField* field, bool trimStrings ) const
|
||||
{
|
||||
QString r;
|
||||
if ( field->isNull() ) {
|
||||
r = nullText();
|
||||
} else {
|
||||
switch( field->type() ) {
|
||||
case QVariant::ByteArray: {
|
||||
|
||||
const QByteArray ba = field->value().toByteArray();
|
||||
// buffer has to be at least length*2+1 bytes
|
||||
char* buffer = new char[ ba.size() * 2 + 1 ];
|
||||
/*uint escapedSize =*/ mysql_escape_string( buffer, ba.data(), ba.size() );
|
||||
r.append("'").append(buffer).append("'");
|
||||
delete[] buffer;
|
||||
}
|
||||
break;
|
||||
case QVariant::String:
|
||||
case QVariant::CString: {
|
||||
// Escape '\' characters
|
||||
r = QSqlDriver::formatValue( field );
|
||||
r.replace( "\\", "\\\\" );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
r = QSqlDriver::formatValue( field, trimStrings );
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
QMYSQLUTFDriverPlugin::QMYSQLUTFDriverPlugin()
|
||||
: QSqlDriverPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
QSqlDriver* QMYSQLUTFDriverPlugin::create( const QString &name )
|
||||
{
|
||||
if ( name == "QMYSQLUTF8" ) {
|
||||
QMYSQLUTFDriver* driver = new QMYSQLUTFDriver();
|
||||
return driver;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList QMYSQLUTFDriverPlugin::keys() const
|
||||
{
|
||||
QStringList l;
|
||||
l << "QMYSQLUTF8";
|
||||
return l;
|
||||
}
|
||||
|
||||
Q_EXPORT_PLUGIN( QMYSQLUTFDriverPlugin )
|
115
drivers/qt3-mysql-utf/qt3-mysql-utf.h
Normal file
115
drivers/qt3-mysql-utf/qt3-mysql-utf.h
Normal file
@ -0,0 +1,115 @@
|
||||
// qt3-mysql-utf.h
|
||||
//
|
||||
// Qt3 SQL plug-in for MySQL with Unicode UTF-8 support
|
||||
// (C) Copyright 2018 Fred Gleason <fredg@paravelsystems.com>
|
||||
//
|
||||
// Based on the stock Qt3 MySQL driver
|
||||
// Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
//
|
||||
// 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, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//
|
||||
|
||||
#ifndef QT3_MYSQL_UTF_H
|
||||
#define QT3_MYSQL_UTF_H
|
||||
|
||||
#include <qsqldriver.h>
|
||||
#include <qsqldriverplugin.h>
|
||||
#include <qsqlresult.h>
|
||||
#include <qsqlfield.h>
|
||||
#include <qsqlindex.h>
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#define Q_EXPORT_SQLDRIVER_MYSQL
|
||||
|
||||
class QMYSQLUTFDriverPlugin : public QSqlDriverPlugin
|
||||
{
|
||||
public:
|
||||
QMYSQLUTFDriverPlugin();
|
||||
|
||||
QSqlDriver* create( const QString & );
|
||||
QStringList keys() const;
|
||||
};
|
||||
|
||||
class QMYSQLUTFDriverPrivate;
|
||||
class QMYSQLUTFResultPrivate;
|
||||
class QMYSQLUTFDriver;
|
||||
class QSqlRecordInfo;
|
||||
|
||||
class QMYSQLUTFResult : public QSqlResult
|
||||
{
|
||||
friend class QMYSQLUTFDriver;
|
||||
public:
|
||||
QMYSQLUTFResult( const QMYSQLUTFDriver* db );
|
||||
~QMYSQLUTFResult();
|
||||
|
||||
MYSQL_RES* result();
|
||||
protected:
|
||||
void cleanup();
|
||||
bool fetch( int i );
|
||||
bool fetchNext();
|
||||
bool fetchLast();
|
||||
bool fetchFirst();
|
||||
QVariant data( int field );
|
||||
bool isNull( int field );
|
||||
bool reset ( const QString& query );
|
||||
int size();
|
||||
int numRowsAffected();
|
||||
private:
|
||||
QMYSQLUTFResultPrivate* d;
|
||||
};
|
||||
|
||||
class Q_EXPORT_SQLDRIVER_MYSQL QMYSQLUTFDriver : public QSqlDriver
|
||||
{
|
||||
friend class QMYSQLUTFResult;
|
||||
public:
|
||||
QMYSQLUTFDriver( QObject * parent=0, const char * name=0 );
|
||||
QMYSQLUTFDriver( MYSQL * con, QObject * parent=0, const char * name=0 );
|
||||
~QMYSQLUTFDriver();
|
||||
bool hasFeature( DriverFeature f ) const;
|
||||
bool open( const QString & db,
|
||||
const QString & user = QString::null,
|
||||
const QString & password = QString::null,
|
||||
const QString & host = QString::null,
|
||||
int port = -1 );
|
||||
void close();
|
||||
QSqlQuery createQuery() const;
|
||||
QStringList tables( const QString& user ) const;
|
||||
QSqlIndex primaryIndex( const QString& tablename ) const;
|
||||
QSqlRecord record( const QString& tablename ) const;
|
||||
QSqlRecord record( const QSqlQuery& query ) const;
|
||||
QSqlRecordInfo recordInfo( const QString& tablename ) const;
|
||||
QSqlRecordInfo recordInfo( const QSqlQuery& query ) const;
|
||||
QString formatValue( const QSqlField* field,
|
||||
bool trimStrings ) const;
|
||||
MYSQL* mysql();
|
||||
// ### remove me for 4.0
|
||||
bool open( const QString& db,
|
||||
const QString& user,
|
||||
const QString& password,
|
||||
const QString& host,
|
||||
int port,
|
||||
const QString& connOpts );
|
||||
|
||||
protected:
|
||||
bool beginTransaction();
|
||||
bool commitTransaction();
|
||||
bool rollbackTransaction();
|
||||
private:
|
||||
void init();
|
||||
QMYSQLUTFDriverPrivate* d;
|
||||
};
|
||||
|
||||
|
||||
#endif // QT3_MYSQL_UTF_H
|
26
drivers/qt3-mysql-utf/qt3-mysql-utf.pro
Normal file
26
drivers/qt3-mysql-utf/qt3-mysql-utf.pro
Normal file
@ -0,0 +1,26 @@
|
||||
# qt3-mysql-utf.pro
|
||||
#
|
||||
# The QMake project file for qt3-mysql-utf
|
||||
#
|
||||
# (C) Copyright 2018 Fred Gleason <fredg@paravelsystems.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
TEMPLATE = plugin
|
||||
|
||||
SOURCES += qsqlextension.cpp
|
||||
SOURCES += qt3-mysql-utf.cpp
|
||||
|
||||
HEADERS += qsqlextension.h
|
||||
HEADERS += qt3-mysql-utf.h
|
@ -76,74 +76,32 @@ QString RDCheckDateTime(QDate const &date, QString const &format)
|
||||
|
||||
QString RDEscapeString(QString const &str)
|
||||
{
|
||||
QString orig=str;
|
||||
QString res;
|
||||
|
||||
for(unsigned i=0;i<str.length();i++) {
|
||||
switch(((const char *)str)[i]) {
|
||||
case '(':
|
||||
res+=QString("\\\(");
|
||||
break;
|
||||
QChar c=orig.ref(i);
|
||||
switch(c) {
|
||||
case '"':
|
||||
res+=QString("\\\"");
|
||||
break;
|
||||
|
||||
case ')':
|
||||
res+=QString("\\)");
|
||||
break;
|
||||
case '`':
|
||||
res+=QString("\\`");
|
||||
break;
|
||||
|
||||
case '{':
|
||||
res+=QString("\\\{");
|
||||
break;
|
||||
case '\'':
|
||||
res+=QString("\\\'");
|
||||
break;
|
||||
|
||||
case '"':
|
||||
res+=QString("\\\"");
|
||||
break;
|
||||
case '\\':
|
||||
res+=QString("\\");
|
||||
res+=QString("\\");
|
||||
break;
|
||||
|
||||
case '`':
|
||||
res+=QString("\\`");
|
||||
break;
|
||||
|
||||
case '[':
|
||||
res+=QString("\\\[");
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
res+=QString("\\\'");
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
res+=QString("\\");
|
||||
res+=QString("\\");
|
||||
break;
|
||||
|
||||
case '?':
|
||||
res+=QString("\\\?");
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
res+=QString("\\ ");
|
||||
break;
|
||||
|
||||
case '&':
|
||||
res+=QString("\\&");
|
||||
break;
|
||||
|
||||
case ';':
|
||||
res+=QString("\\;");
|
||||
break;
|
||||
|
||||
case '<':
|
||||
res+=QString("\\<");
|
||||
break;
|
||||
|
||||
case '>':
|
||||
res+=QString("\\>");
|
||||
break;
|
||||
|
||||
case '|':
|
||||
res+=QString("\\|");
|
||||
break;
|
||||
|
||||
default:
|
||||
res+=((const char *)str)[i];
|
||||
break;
|
||||
default:
|
||||
res+=c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -916,6 +916,7 @@ void EditCart::okData()
|
||||
rdcart_cart->setPublisher(rdcart_controls.publisher_edit->text());
|
||||
rdcart_cart->setConductor(rdcart_controls.conductor_edit->text());
|
||||
rdcart_cart->setComposer(rdcart_controls.composer_edit->text());
|
||||
printf("USERDEF: %s\n",(const char *)rdcart_controls.user_defined_edit->text());
|
||||
rdcart_cart->setUserDefined(rdcart_controls.user_defined_edit->text());
|
||||
rdcart_cart->
|
||||
setUsageCode((RDCart::UsageCode)rdcart_usage_box->currentItem());
|
||||
|
@ -108,6 +108,7 @@ make
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
rm -f $RPM_BUILD_ROOT/@LOCAL_PREFIX@/@RD_LIB_PATH@/libqmysqlutf*
|
||||
mkdir $RPM_BUILD_ROOT/.qt
|
||||
touch $RPM_BUILD_ROOT/.qt/qt
|
||||
rm -f $RPM_BUILD_ROOT/lib/security/pam_rd.la
|
||||
@ -257,6 +258,7 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
@LOCAL_PREFIX@/@RD_LIB_PATH@/rivendell/*.rlm
|
||||
@LOCAL_PREFIX@/@RD_LIB_PATH@/qt-3.3/plugins/sqldrivers/libqmysqlutf.so
|
||||
@LOCAL_PREFIX@/bin/rdadmin
|
||||
@LOCAL_PREFIX@/bin/rdairplay
|
||||
@LOCAL_PREFIX@/bin/rdpanel
|
||||
|
Loading…
x
Reference in New Issue
Block a user