您的位置:首页 > 数据库

两个数据库文件对比

2015-05-06 14:00 405 查看
如下图所示,函数首先打开两个数据库,然后获取两个数据库的版本信息。根据数据库各个表名称来打开相应的表,然后判断两个表的具体内容是否相同,如果不同的话则打印出该表名,如果用户选择打印具体内容的话,则分别打印两个表的具体内容(由于表的内容可能会比较多,且查看单个表内容的话使用SQLite软件看更直观,所以这个功能默认关闭)。



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "sqlite3.h"
#include "database_table.h"

#define OK     0
#define ERROR -1

#define TRUE  1
#define FALSE 0
#define TABLE_START_STR "CREATE TABLE IF NOT EXISTS"

/**@brief	数据库查询返回结构
*/
typedef struct{
int rows;		///> 查询结果的行数
int column;		///> 查询结果的列数
char ** data;	///> 查询结果的数据,一维数组,先是列名,然后是数据
}QUERY_TABLE;

/**@brief	   根据要查询的内容输入sql语句,返回要查询的数据集
* @param[in]  DATABASE * db 数据库的连接句柄,不能为NULL
* @param[in]  char *sql  要查询的sql语句,可以在数据库中正常运行的,不能为NULL
* @param[out] QUERY_TABLE *ds  返回的查询结果结构体
* @return	int SQLITE_OK 查询获取成功; 其他都是失败
*/
int db_query_open_v2 (sqlite3 *db, const char *table_name, QUERY_TABLE *ds)
{
int ret = -1;
char * errmsg = NULL;
char sql[128] = { 0 };

if( (NULL == db)||(NULL == table_name) )
{
return ret;
}

sprintf(sql, "select * from %s", table_name);
ret = sqlite3_get_table(db, sql, &(ds->data), &(ds->rows), &(ds->column), &errmsg);
if (ret != SQLITE_OK)
{
printf("sqlite3_get_table:%d, %s\n",ret, errmsg);
sqlite3_free(errmsg);
}

return ret;
}

/**@brief	关闭并释放查询返回的数据
* @param[in]  QUERY_TABLE *ds 返回的查询结果结构体
* @return	无
*/
void db_query_close_v2 (QUERY_TABLE *ds)
{
if(ds != NULL)
{
sqlite3_free_table(ds->data);
}
}

/**@brief	   比较两个表是否不同
* @param[in]  QUERY_TABLE *table1 数据库1的表
* @param[in]  QUERY_TABLE *table2 数据库2的表
* @param[out]
* @return	FALSE:两个表不同
TRUE:两个表相同
*/
int compare_tables(QUERY_TABLE *table1, QUERY_TABLE *table2)
{
int ret = 0;
int row = 0, col = 0;
char *str1 = NULL, *str2 = NULL;

if(NULL == table1 || NULL == table2)
{
return FALSE;
}

/*两个表的行列数不同,则肯定不相等*/
if (table1->rows != table2->rows ||
table1->column != table2->column)
{
return FALSE;
}

for (row = 1; row <= table1->rows; row++)
{
for (col = 0; col < table1->column; col++)
{
str1 = (table1->data)[row * table1->column + col];
str2 = (table2->data)[row * table2->column + col];

/*两个表的内容都为空,则表示相等,不需要strcmp判断*/
if (str1 == NULL && str2 == NULL)
{
continue;
}
else if(str1 == NULL || str2 == NULL)
{
return FALSE;
}
else
{
ret = strcmp(str1, str2);
if (ret != 0)
{
return FALSE;
}
}
}
}
return TRUE;
}

/**@brief	   打印两个表的信息
* @param[in]  int is_show_content:是否需要显示表的具体内容
* @param[in]  const char *table_name:需要打印的表名称
* @param[in]  QUERY_TABLE *table 数据库1的表
* @param[in]  QUERY_TABLE *table1 数据库2的表
* @param[out]
* @return
*/
void print_table(int is_show_content, const char *table_name, QUERY_TABLE *table, QUERY_TABLE *table1)
{
int row = 0, col = 0;

if(NULL == table_name || NULL == table || NULL == table1)
{
return ;
}
printf("different table: <%s>\n", table_name);

if(is_show_content)
{
for (row = 0; row <= table->rows; row++)
{
for (col = 0; col < table->column; col++)
{
printf("%s | ", (table->data)[row * table->column + col]);
}
printf("\n");
}
printf("\n");

for (row = 0; row <= table1->rows; row++)
{
for (col = 0; col < table1->column; col++)
{
printf("%s | ", (table1->data)[row * table1->column + col]);
}
printf("\n");
}
printf("\n");
}
}

/**@brief	   提取表中的表名
* @param[in]  char *p_database_table:表具体定义的字符串
* @param[in]  char *p_table_names:需要返回的表名称
* @param[out]  char *p_table_names:获取到的表名称
* @return	0:获取成功
-1:获取失败
*/
int parse_table_names(char *p_database_table, char *p_table_names)
{
char input[1024];
char *p_tmp_str = NULL;

memset(input, 0, sizeof(input));
memcpy(input, p_database_table, sizeof(input));

if(NULL == p_table_names || NULL == p_database_table)
{
printf("table name is null\n");
return -1;
}

p_tmp_str = strtok(input, TABLE_START_STR);
if(p_tmp_str)
{
memcpy(p_table_names, p_tmp_str, strlen(p_tmp_str));
return 0;
}

return -1;
}

/**@brief	  获取数据库的版本
* @param[in]  sqlite3 *db:打开的数据库
* @param[in]  char *p_db_name:数据库名称
* @param[out]
* @return
*/
void get_db_version(sqlite3 *db, char *p_db_name)
{
QUERY_TABLE table;
int ret = 0;

if(NULL == db || NULL == p_db_name)
{
return ;
}
ret = db_query_open_v2(db, "db_version", &table);
printf("db name:<%s> version:<%s>\n", p_db_name, (table.data)[1]);
db_query_close_v2(&table);
}

int main(int argc, char **argv)
{
sqlite3 *db1 = NULL;
sqlite3 *db2 = NULL;
QUERY_TABLE table1, table2;
int i = 0;
int ret = 0, ret1 = 0, ret2 = 0;
int table_num = 0, is_show_content = 0;
char table_names[64] = {0};

if (argc < 3)
{
printf("%s db_name1 db_name2 show_content<0/1> \n", argv[0]);
return -1;
}

// 打开两个数据库
// 打开指定的数据库文件,如果不存在将创建一个同名的数据库文件
ret = sqlite3_open(argv[1], &db1);
if (ret != SQLITE_OK)
{
printf("can not open db %s\n", argv[1]);
return -1;
}

ret = sqlite3_open(argv[2], &db2);
if (ret != SQLITE_OK)
{
printf("can not open db %s\n", argv[2]);
return -1;
}

get_db_version(db1, argv[1]);
get_db_version(db2, argv[2]);

/*是否需要显示数据库内容*/
if((argc == 4) &&memcmp(argv[3], "1", sizeof("1")) == 0)
{
is_show_content = 1;
}

table_num = sizeof(create_tables) / sizeof(char *);
// 分别读取两个数据库的内容
for (i = 0; i < table_num; i++)
{
memset(table_names, 0, sizeof(table_names));
if(parse_table_names(create_tables[i], table_names) != 0)
{
continue;
}
ret1 = db_query_open_v2(db1, table_names, &table1);
ret2 = db_query_open_v2(db2, table_names, &table2);
if (ret1 != OK || ret2 != OK)
{
printf("query table %s error\n", table_names);
continue;
}

/*比较如果两个表不同的话则打印相应信息*/
if (!compare_tables(&table1, &table2))
{
print_table(is_show_content, table_names, &table1, &table2);
}

db_query_close_v2(&table1);
db_query_close_v2(&table2);
}
sqlite3_close(db1);
sqlite3_close(db2);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: