mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-16 18:25:11 -06:00
Update xml file backend to recognize a newer version file on load attempt, not load, and alert user of need to upgrade Gnucash.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@21908 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
c2458bfc68
commit
7c03e237b2
@ -99,15 +99,6 @@ typedef int ssize_t;
|
||||
|
||||
static QofLogModule log_module = GNC_MOD_BACKEND;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GNC_BOOK_NOT_OURS,
|
||||
GNC_BOOK_BIN_FILE,
|
||||
GNC_BOOK_XML1_FILE,
|
||||
GNC_BOOK_XML2_FILE,
|
||||
GNC_BOOK_XML2_FILE_NO_ENCODING,
|
||||
} QofBookFileType;
|
||||
|
||||
static gboolean save_may_clobber_data (QofBackend *bend);
|
||||
|
||||
/* ================================================================= */
|
||||
@ -561,7 +552,10 @@ static QofBookFileType
|
||||
gnc_xml_be_determine_file_type(const char *path)
|
||||
{
|
||||
gboolean with_encoding;
|
||||
if (gnc_is_xml_data_file_v2(path, &with_encoding))
|
||||
QofBookFileType v2type;
|
||||
|
||||
v2type = gnc_is_xml_data_file_v2(path, &with_encoding);
|
||||
if (v2type == GNC_BOOK_XML2_FILE)
|
||||
{
|
||||
if (with_encoding)
|
||||
{
|
||||
@ -572,7 +566,11 @@ gnc_xml_be_determine_file_type(const char *path)
|
||||
return GNC_BOOK_XML2_FILE_NO_ENCODING;
|
||||
}
|
||||
}
|
||||
else if (gnc_is_xml_data_file(path))
|
||||
else if (v2type == GNC_BOOK_POST_XML2_0_0_FILE)
|
||||
{
|
||||
return GNC_BOOK_POST_XML2_0_0_FILE;
|
||||
}
|
||||
else if (v2type == GNC_BOOK_XML1_FILE)
|
||||
{
|
||||
return GNC_BOOK_XML1_FILE;
|
||||
}
|
||||
@ -586,6 +584,7 @@ gnc_determine_file_type (const char *uri)
|
||||
int rc;
|
||||
FILE *t;
|
||||
gchar *filename;
|
||||
QofBookFileType xml_type;
|
||||
gboolean result;
|
||||
|
||||
if (!uri)
|
||||
@ -619,12 +618,10 @@ gnc_determine_file_type (const char *uri)
|
||||
result = TRUE;
|
||||
goto det_exit;
|
||||
}
|
||||
if (gnc_is_xml_data_file_v2(filename, NULL))
|
||||
{
|
||||
result = TRUE;
|
||||
goto det_exit;
|
||||
}
|
||||
else if (gnc_is_xml_data_file(filename))
|
||||
xml_type = gnc_is_xml_data_file_v2(filename, NULL);
|
||||
if ((xml_type == GNC_BOOK_XML2_FILE) ||
|
||||
(xml_type == GNC_BOOK_XML1_FILE) ||
|
||||
(xml_type == GNC_BOOK_POST_XML2_0_0_FILE))
|
||||
{
|
||||
result = TRUE;
|
||||
goto det_exit;
|
||||
@ -1117,7 +1114,7 @@ gnc_xml_be_load_from_file (QofBackend *bend, QofBook *book, QofBackendLoadType l
|
||||
switch (gnc_xml_be_determine_file_type(be->fullpath))
|
||||
{
|
||||
case GNC_BOOK_XML2_FILE:
|
||||
rc = qof_session_load_from_xml_file_v2 (be, book);
|
||||
rc = qof_session_load_from_xml_file_v2 (be, book, GNC_BOOK_XML2_FILE);
|
||||
if (FALSE == rc)
|
||||
{
|
||||
PWARN( "Syntax error in Xml File %s", be->fullpath );
|
||||
@ -1137,6 +1134,10 @@ gnc_xml_be_load_from_file (QofBackend *bend, QofBook *book, QofBackendLoadType l
|
||||
error = ERR_FILEIO_PARSE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GNC_BOOK_POST_XML2_0_0_FILE:
|
||||
error = ERR_BACKEND_TOO_NEW;
|
||||
PWARN( "Version of Xml file %s is newer than what we can read", be->fullpath );
|
||||
break;
|
||||
default:
|
||||
/* If file type wasn't known, check errno again to give the
|
||||
user some more useful feedback for some particular error
|
||||
|
@ -43,6 +43,16 @@ typedef enum
|
||||
XML_RETAIN_ALL
|
||||
} XMLFileRetentionType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GNC_BOOK_NOT_OURS,
|
||||
GNC_BOOK_BIN_FILE,
|
||||
GNC_BOOK_XML1_FILE,
|
||||
GNC_BOOK_XML2_FILE,
|
||||
GNC_BOOK_XML2_FILE_NO_ENCODING,
|
||||
GNC_BOOK_POST_XML2_0_0_FILE
|
||||
} QofBookFileType;
|
||||
|
||||
struct FileBackend_struct
|
||||
{
|
||||
QofBackend be;
|
||||
|
@ -498,8 +498,9 @@ gnc_load_example_account_list(const char *dirname)
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/*
|
||||
gboolean
|
||||
gnc_is_example_account_xml(const gchar *name)
|
||||
{
|
||||
return gnc_is_our_xml_file(name, GNC_ACCOUNT_STRING, NULL);
|
||||
}
|
||||
} */
|
||||
|
@ -53,6 +53,6 @@ GncExampleAccount *gnc_read_example_account(const gchar *filename);
|
||||
void gnc_free_example_account_list(GSList *list);
|
||||
GSList* gnc_load_example_account_list(const char *dirname);
|
||||
|
||||
gboolean gnc_is_example_account_xml(const gchar *name);
|
||||
/* gboolean gnc_is_example_account_xml(const gchar *name); */
|
||||
|
||||
#endif /* IO_EXAMPLE_ACCOUNT_H */
|
||||
|
@ -412,7 +412,9 @@ qof_session_load_from_xml_file(QofBook *book, const char *filename)
|
||||
gboolean
|
||||
gnc_is_xml_data_file(const gchar *filename)
|
||||
{
|
||||
return gnc_is_our_xml_file(filename, "gnc", NULL);
|
||||
if ((gnc_is_our_xml_file(filename, NULL)) == GNC_BOOK_XML1_FILE)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
@ -95,6 +95,8 @@ struct file_backend
|
||||
};
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
/* non-static because they are used in sixtp.c */
|
||||
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
extern const gchar *gnc_v2_book_version_string; /* see gnc-book-xml-v2 */
|
||||
|
||||
void
|
||||
@ -679,7 +681,8 @@ gnc_sixtp_gdv2_new (
|
||||
static gboolean
|
||||
qof_session_load_from_xml_file_v2_full(
|
||||
FileBackend *fbe, QofBook *book,
|
||||
sixtp_push_handler push_handler, gpointer push_user_data)
|
||||
sixtp_push_handler push_handler, gpointer push_user_data,
|
||||
QofBookFileType type)
|
||||
{
|
||||
Account *root;
|
||||
QofBackend *be = &fbe->be;
|
||||
@ -689,6 +692,7 @@ qof_session_load_from_xml_file_v2_full(
|
||||
sixtp *book_parser;
|
||||
struct file_backend be_data;
|
||||
gboolean retval;
|
||||
char *v2type;
|
||||
|
||||
gd = gnc_sixtp_gdv2_new(book, FALSE, file_rw_feedback, be->percentage);
|
||||
|
||||
@ -696,14 +700,20 @@ qof_session_load_from_xml_file_v2_full(
|
||||
main_parser = sixtp_new();
|
||||
book_parser = sixtp_new();
|
||||
|
||||
if (type == GNC_BOOK_XML2_FILE)
|
||||
v2type = g_strdup(GNC_V2_STRING);
|
||||
|
||||
if (!sixtp_add_some_sub_parsers(
|
||||
top_parser, TRUE,
|
||||
GNC_V2_STRING, main_parser,
|
||||
v2type, main_parser,
|
||||
NULL, NULL))
|
||||
{
|
||||
g_free(v2type);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
g_free(v2type);
|
||||
|
||||
if (!sixtp_add_some_sub_parsers(
|
||||
main_parser, TRUE,
|
||||
COUNT_DATA_TAG, gnc_counter_sixtp_parser_create(),
|
||||
@ -819,9 +829,10 @@ bail:
|
||||
}
|
||||
|
||||
gboolean
|
||||
qof_session_load_from_xml_file_v2(FileBackend *fbe, QofBook *book)
|
||||
qof_session_load_from_xml_file_v2(FileBackend *fbe, QofBook *book,
|
||||
QofBookFileType type)
|
||||
{
|
||||
return qof_session_load_from_xml_file_v2_full(fbe, book, NULL, NULL);
|
||||
return qof_session_load_from_xml_file_v2_full(fbe, book, NULL, NULL, type);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@ -1620,12 +1631,9 @@ is_gzipped_file(const gchar *name)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
QofBookFileType
|
||||
gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding)
|
||||
{
|
||||
if (gnc_is_our_xml_file(name, GNC_V2_STRING, with_encoding))
|
||||
return TRUE;
|
||||
|
||||
if (is_gzipped_file(name))
|
||||
{
|
||||
gzFile *file = NULL;
|
||||
@ -1647,19 +1655,18 @@ gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding)
|
||||
file = gzopen(name, "r");
|
||||
#endif
|
||||
if (file == NULL)
|
||||
return FALSE;
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
|
||||
num_read = gzread(file, first_chunk, sizeof(first_chunk) - 1);
|
||||
gzclose(file);
|
||||
|
||||
if (num_read < 1)
|
||||
return FALSE;
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
|
||||
return gnc_is_our_first_xml_chunk(first_chunk, GNC_V2_STRING,
|
||||
with_encoding);
|
||||
return gnc_is_our_first_xml_chunk(first_chunk, with_encoding);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return (gnc_is_our_xml_file(name, with_encoding));
|
||||
}
|
||||
|
||||
|
||||
@ -2095,7 +2102,7 @@ gnc_xml2_parse_with_subst (FileBackend *fbe, QofBook *book, GHashTable *subst)
|
||||
|
||||
success = qof_session_load_from_xml_file_v2_full(
|
||||
fbe, book, (sixtp_push_handler) parse_with_subst_push_handler,
|
||||
push_data);
|
||||
push_data, GNC_BOOK_XML2_FILE);
|
||||
|
||||
if (success)
|
||||
qof_book_kvp_changed(book);
|
||||
|
@ -128,7 +128,7 @@ typedef struct
|
||||
void run_callback(sixtp_gdv2 *data, const char *type);
|
||||
|
||||
/** read in an account group from a file */
|
||||
gboolean qof_session_load_from_xml_file_v2(FileBackend *, QofBook *);
|
||||
gboolean qof_session_load_from_xml_file_v2(FileBackend *, QofBook *, QofBookFileType);
|
||||
|
||||
/* write all book info to a file */
|
||||
gboolean gnc_book_write_to_xml_filehandle_v2(QofBook *book, FILE *fh);
|
||||
@ -142,7 +142,7 @@ gboolean gnc_book_write_accounts_to_xml_file_v2(QofBackend * be, QofBook *book,
|
||||
/** The is_gncxml_file() routine checks to see if the first few
|
||||
* chars of the file look like gnc-xml data.
|
||||
*/
|
||||
gboolean gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding);
|
||||
QofBookFileType gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding);
|
||||
|
||||
/** Write a name-space declaration for the provided namespace data type
|
||||
* within the GNC XML namespace at http://www.gnucash.org/XML.
|
||||
|
@ -41,6 +41,8 @@ typedef int ssize_t;
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "gnc.backend.file.sixtp"
|
||||
|
||||
extern const gchar *gnc_v2_xml_version_string; /* see io-gncxml-v2.c */
|
||||
|
||||
/************************************************************************/
|
||||
gboolean
|
||||
is_child_result_from_node_named(sixtp_child_result *cr, const char *tag)
|
||||
@ -860,21 +862,19 @@ search_for(unsigned char marker, char **cursor)
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gnc_is_our_xml_file(const char *filename, const char *first_tag,
|
||||
gboolean *with_encoding)
|
||||
QofBookFileType
|
||||
gnc_is_our_xml_file(const char *filename, gboolean *with_encoding)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
char first_chunk[256];
|
||||
ssize_t num_read;
|
||||
|
||||
g_return_val_if_fail(filename, FALSE);
|
||||
g_return_val_if_fail(first_tag, FALSE);
|
||||
g_return_val_if_fail(filename, GNC_BOOK_NOT_OURS);
|
||||
|
||||
f = g_fopen(filename, "r");
|
||||
if (f == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
}
|
||||
|
||||
num_read = fread(first_chunk, sizeof(char), sizeof(first_chunk) - 1, f);
|
||||
@ -882,17 +882,16 @@ gnc_is_our_xml_file(const char *filename, const char *first_tag,
|
||||
|
||||
if (num_read == 0)
|
||||
{
|
||||
return FALSE;
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
}
|
||||
|
||||
first_chunk[num_read] = '\0';
|
||||
|
||||
return gnc_is_our_first_xml_chunk(first_chunk, first_tag, with_encoding);
|
||||
return gnc_is_our_first_xml_chunk(first_chunk, with_encoding);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gnc_is_our_first_xml_chunk(char *chunk, const char *first_tag,
|
||||
gboolean *with_encoding)
|
||||
QofBookFileType
|
||||
gnc_is_our_first_xml_chunk(char *chunk, gboolean *with_encoding)
|
||||
{
|
||||
char *cursor = NULL;
|
||||
|
||||
@ -905,51 +904,58 @@ gnc_is_our_first_xml_chunk(char *chunk, const char *first_tag,
|
||||
|
||||
if (!eat_whitespace(&cursor))
|
||||
{
|
||||
return FALSE;
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
}
|
||||
|
||||
if (strncmp(cursor, "<?xml", 5) == 0)
|
||||
{
|
||||
char *tag_compare;
|
||||
gboolean result;
|
||||
|
||||
if (!search_for('>', &cursor))
|
||||
{
|
||||
return FALSE;
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
}
|
||||
|
||||
if (!eat_whitespace(&cursor))
|
||||
{
|
||||
return FALSE;
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
}
|
||||
|
||||
tag_compare = g_strdup_printf("<%s", first_tag);
|
||||
tag_compare = g_strdup_printf("<%s\n", gnc_v2_xml_version_string);
|
||||
|
||||
result = (strncmp(cursor, tag_compare, strlen(tag_compare)) == 0);
|
||||
g_free (tag_compare);
|
||||
|
||||
if (result && with_encoding)
|
||||
if (strncmp(cursor, tag_compare, strlen(tag_compare)) == 0)
|
||||
{
|
||||
*cursor = '\0';
|
||||
cursor = chunk;
|
||||
while (search_for('e', &cursor))
|
||||
if (with_encoding)
|
||||
{
|
||||
if (strncmp(cursor, "ncoding=", 8) == 0)
|
||||
*cursor = '\0';
|
||||
cursor = chunk;
|
||||
while (search_for('e', &cursor))
|
||||
{
|
||||
*with_encoding = TRUE;
|
||||
break;
|
||||
if (strncmp(cursor, "ncoding=", 8) == 0)
|
||||
{
|
||||
*with_encoding = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free (tag_compare);
|
||||
return GNC_BOOK_XML2_FILE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
g_free (tag_compare);
|
||||
|
||||
if (strncmp(cursor, "<gnc>\n", strlen("<gnc>\n")) == 0)
|
||||
return GNC_BOOK_XML1_FILE;
|
||||
|
||||
/* If it doesn't match any of the above but has '<gnc-v...', it must */
|
||||
/* be a later version */
|
||||
if (strncmp(cursor, "<gnc-v", strlen("<gnc-v")) == 0)
|
||||
return GNC_BOOK_POST_XML2_0_0_FILE;
|
||||
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return GNC_BOOK_NOT_OURS;
|
||||
}
|
||||
|
||||
/************************* END OF FILE *********************************/
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "gnc-xml-helper.h"
|
||||
#include "gnc-engine.h"
|
||||
#include "gnc-backend-xml.h"
|
||||
|
||||
typedef struct _sixtp_child_result sixtp_child_result;
|
||||
|
||||
@ -208,11 +209,10 @@ sixtp* sixtp_add_some_sub_parsers(sixtp *tochange, gboolean cleanup, ...);
|
||||
gboolean sixtp_add_sub_parser(sixtp *parser, const gchar* tag,
|
||||
sixtp *sub_parser);
|
||||
|
||||
gboolean gnc_is_our_xml_file(const char *filename, const char *first_tag,
|
||||
QofBookFileType gnc_is_our_xml_file(const char *filename,
|
||||
gboolean *with_encoding);
|
||||
|
||||
gboolean gnc_is_our_first_xml_chunk(char *chunk, const char *first_tag,
|
||||
gboolean *with_encoding);
|
||||
QofBookFileType gnc_is_our_first_xml_chunk(char *chunk, gboolean *with_encoding);
|
||||
|
||||
|
||||
#endif /* _SIXTP_H_ */
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "sixtp-utils.h"
|
||||
#include "sixtp-dom-generators.h"
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
@ -43,6 +43,9 @@
|
||||
|
||||
#include "gnc-commodity.h"
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
|
||||
static void
|
||||
test_dom_tree_to_commodity_ref(void)
|
||||
{
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "sixtp-dom-generators.h"
|
||||
#include "sixtp-dom-parsers.h"
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
|
||||
static void
|
||||
test_kvp_get_slot(int run,
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include "test-engine-stuff.h"
|
||||
#include "test-file-stuff.h"
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
|
||||
static void
|
||||
test_binary()
|
||||
{
|
||||
|
@ -43,6 +43,9 @@
|
||||
#include "Account.h"
|
||||
#include "Scrub.h"
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
|
||||
static QofBook *sixbook;
|
||||
|
||||
static gchar*
|
||||
|
@ -24,6 +24,9 @@
|
||||
|
||||
#include "Account.h"
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
|
||||
static QofBook *book;
|
||||
|
||||
static gchar*
|
||||
|
@ -42,6 +42,9 @@
|
||||
#include "test-engine-stuff.h"
|
||||
#include "test-file-stuff.h"
|
||||
|
||||
#define GNC_V2_STRING "gnc-v2"
|
||||
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
|
||||
|
||||
static QofSession *session;
|
||||
|
||||
struct pricedb_data_struct
|
||||
|
@ -421,7 +421,8 @@ show_session_error (QofBackendError io_error,
|
||||
case ERR_SQL_DB_TOO_NEW:
|
||||
fmt = _("This database is from a newer version of GnuCash. "
|
||||
"This version can read it, but cannot safely save to it. "
|
||||
"It will be marked read-only until you do File>Save As.");
|
||||
"It will be marked read-only until you do File>Save As, "
|
||||
"but data may be lost in writing to the old version.");
|
||||
gnc_warning_dialog (parent, "%s", fmt);
|
||||
uh_oh = TRUE;
|
||||
break;
|
||||
@ -458,6 +459,16 @@ show_session_error (QofBackendError io_error,
|
||||
gnc_error_dialog (parent, "%s", fmt);
|
||||
break;
|
||||
|
||||
case ERR_FILEIO_FILE_UPGRADE:
|
||||
fmt = _("This file is from an older version of GnuCash and will be "
|
||||
"upgraded when saved by this version. You will not be able "
|
||||
"to read the saved file from the older version of Gnucash "
|
||||
"(it will report an \"error parsing the file\"). If you wish "
|
||||
"to preserve the old version, exit without saving.");
|
||||
gnc_warning_dialog (parent, "%s", fmt);
|
||||
uh_oh = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
PERR("FIXME: Unhandled error %d", io_error);
|
||||
fmt = _("An unknown I/O error (%d) occurred.");
|
||||
|
@ -98,6 +98,8 @@ typedef enum
|
||||
ERR_FILEIO_FILE_EACCES, /**< No read access permission for the given file */
|
||||
ERR_FILEIO_RESERVED_WRITE, /**< User attempt to write to a directory reserved
|
||||
for internal use by GnuCash */
|
||||
ERR_FILEIO_FILE_UPGRADE, /**< file will be upgraded and not be able to be
|
||||
read by prior versions - warn users*/
|
||||
|
||||
/* network errors */
|
||||
ERR_NETIO_SHORT_READ = 2000, /**< not enough bytes received */
|
||||
|
@ -1257,6 +1257,7 @@ qof_session_load (QofSession *session,
|
||||
if ((err != ERR_BACKEND_NO_ERR) &&
|
||||
(err != ERR_FILEIO_FILE_TOO_OLD) &&
|
||||
(err != ERR_FILEIO_NO_ENCODING) &&
|
||||
(err != ERR_FILEIO_FILE_UPGRADE) &&
|
||||
(err != ERR_SQL_DB_TOO_OLD) &&
|
||||
(err != ERR_SQL_DB_TOO_NEW))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user