Skip to content

Commit

Permalink
Sybase ASE to Oracle migration improved
Browse files Browse the repository at this point in the history
  • Loading branch information
dmtolpeko committed Dec 1, 2017
1 parent da5ea50 commit 069c7ee
Show file tree
Hide file tree
Showing 13 changed files with 328 additions and 154 deletions.
36 changes: 36 additions & 0 deletions sqldata/sqlapibase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,42 @@ void SqlApiBase::SplitConnectionString(const char *conn, std::string &user, std:
}
}

void SqlApiBase::SplitConnectionString(const char *conn, std::string &user, std::string &pwd, std::string &server, std::string &db, std::string &port)
{
if(conn == NULL)
return;

std::string db_full;

SplitConnectionString(conn, user, pwd, db_full);

const char *start = db_full.c_str();

// Find : and , that denote the server port and the database name
const char *semi = strchr(start, ':');
const char *comma = strchr(start, ',');

const char *end = (semi != NULL) ? semi :comma;

// Define server name
if(end != NULL)
server.assign(start, (size_t)(end - start));
else
server = start;

// Define port
if(semi != NULL)
{
if(comma != NULL && comma > semi)
port.assign(semi + 1, (size_t)(comma - semi - 1));
else
port = semi + 1;
}

if(comma != NULL)
db = Str::SkipSpaces(comma + 1);
}

// Build a condition to select objects from the catalog and exclude from selection
void SqlApiBase::GetSelectionCriteria(const char *select, const char *exclude, const char *schema,
const char *object, std::string &output, const char *default_schema, bool upper_case)
Expand Down
7 changes: 5 additions & 2 deletions sqldata/sqlapibase.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ struct SqlCol

// Column contains binary data (MySQL)
bool _binary;

// Data fetched in UTF-16
bool _nchar;

// Column data type name
std::string _datatype_name;
std::string _t_datatype_name;
Expand Down Expand Up @@ -106,7 +108,7 @@ struct SqlCol
SqlCol()
{
*_name = '\x0'; *_t_name = '\x0';
_len = 0; _fetch_len = 0; _precision = 0; _scale = 0; _binary = false;
_len = 0; _fetch_len = 0; _precision = 0; _scale = 0; _binary = false; _nchar = false;
_native_dt = 0; _native_fetch_dt = 0;
_data = NULL; _ind2 = NULL; /*ind4 = NULL;*/ ind = NULL; _len_ind2 = NULL; _len_ind4 = NULL;
_nullable = true; _lob = false; _lob_fetch_status = 0;
Expand Down Expand Up @@ -642,6 +644,7 @@ class SqlApiBase

// Split connection string to user, password and database
void SplitConnectionString(const char *conn, std::string &user, std::string &pwd, std::string &db);
void SplitConnectionString(const char *conn, std::string &user, std::string &pwd, std::string &server, std::string &db, std::string &port);

// Build a condition to select objects from the catalog
static void GetSelectionCriteria(const char *select, const char *exclude, const char *schema, const char *object, std::string &output, const char *default_schema, bool upper_case);
Expand Down
96 changes: 68 additions & 28 deletions sqldata/sqlctapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ int SqlCtApi::Init()
}
}

#else
_ct_dll = Os::LoadLibrary(CTLIB_DLL);
_cs_dll = Os::LoadLibrary(CSLIB_DLL);

if(_ct_dll == NULL || _cs_dll == NULL)
{
char *error = Os::LoadLibraryError();
if(error != NULL)
strcpy(_native_error_text, error);
}
#endif

// Get functions
Expand Down Expand Up @@ -211,26 +221,7 @@ int SqlCtApi::Init()
// Set the connection string in the API object
void SqlCtApi::SetConnectionString(const char *conn)
{
if(conn == NULL)
return;

std::string db;

SplitConnectionString(conn, _user, _pwd, db);

const char *start = db.c_str();

// Find , that denotes the database name
const char *comma = strchr(start, ',');

// Define server and database name
if(comma != NULL)
{
_server.assign(start, (size_t)(comma - start));
_db = comma + 1;
}
else
_server = start;
SplitConnectionString(conn, _user, _pwd, _server, _db, _port);
}

// Connect to the database
Expand All @@ -253,8 +244,26 @@ int SqlCtApi::Connect(size_t *time_spent)
rc = _ct_con_props(_connection, CS_SET, CS_USERNAME, (CS_VOID*)_user.c_str(), CS_NULLTERM, NULL);
rc = _ct_con_props(_connection, CS_SET, CS_PASSWORD, (CS_VOID*)_pwd.c_str(), CS_NULLTERM, NULL);

// Check if password encryption required
if(_parameters->GetTrue("-sybase_encrypted_password") != NULL)
{
CS_BOOL sec_encryption = CS_TRUE;

// Sybase uses extended password encryption as the first preference, if the server cannot support extended password encryption, it uses normal password encryption
rc = _ct_con_props(_connection, CS_SET, CS_SEC_EXTENDED_ENCRYPTION, (CS_VOID*)&sec_encryption, CS_UNUSED, NULL);
rc = _ct_con_props(_connection, CS_SET, CS_SEC_ENCRYPTION, (CS_VOID*)&sec_encryption, CS_UNUSED, NULL);
}

const char *server = _server.empty() ? NULL : _server.c_str();

// Check if port is specified
if(!_port.empty())
{
// Use format "server port"
std::string serveraddr = _server + " " + _port;
rc = _ct_con_props(_connection, CS_SET, CS_SERVERADDR, (CS_VOID*)serveraddr.c_str(), CS_NULLTERM, NULL);
}

// Connect to the server
rc = _ct_connect(_connection, (CS_CHAR*)server, CS_NULLTERM);

Expand Down Expand Up @@ -507,6 +516,11 @@ int SqlCtApi::OpenCursor(const char *query, size_t buffer_rows, int buffer_memor
// Get column information
for(int i = 0; i < _cursor_cols_count; i++)
{
// Note that CHAR and VARCHAR both have CS_CHAR_TYPE, and you cannot distinguish them using CS_FMT_PADBLANK and CS_FMT_PADNULL in fmt.format
// as it is always 0 (CS_FMT_UNUSED) in ct_describe (Not applicable)

// CS_LONGCHAR_TYPE is returned for VARCHAR > 255 (max length is 32K since ASE 12.5)

rc = _ct_describe(_cursor_cmd, i + 1, &fmt[i]);

// Copy the column name
Expand All @@ -521,9 +535,9 @@ int SqlCtApi::OpenCursor(const char *query, size_t buffer_rows, int buffer_memor

// Get column length for character and binary strings
_cursor_cols[i]._len = (size_t)fmt[i].maxlength;

// TEXT, Sybase ASE 16 returns size 32768, change to 1M
if(_cursor_cols[i]._native_dt == CS_TEXT_TYPE)
// For TEXT and UNITEXT Sybase ASE 16 returns size 32768, change to 1M
if(_cursor_cols[i]._native_dt == CS_TEXT_TYPE || _cursor_cols[i]._native_dt == CS_UNITEXT_TYPE)
_cursor_cols[i]._len = 1048576;

row_size += _cursor_cols[i]._len;
Expand Down Expand Up @@ -551,8 +565,8 @@ int SqlCtApi::OpenCursor(const char *query, size_t buffer_rows, int buffer_memor
// Allocate buffers for each column
for(int i = 0; i < _cursor_cols_count; i++)
{
// CHAR data type
if(_cursor_cols[i]._native_dt == CS_CHAR_TYPE)
// CHAR and VARCHAR data types; CS_CHAR_TYPE for VARCHAR <= 255, and CS_LONGCHAR_TYPE for VARCHAR < 32K
if(_cursor_cols[i]._native_dt == CS_CHAR_TYPE || _cursor_cols[i]._native_dt == CS_LONGCHAR_TYPE)
{
// Do not bind to null-terminating string as zero byte will be included to length indicator
_cursor_cols[i]._native_fetch_dt = _cursor_cols[i]._native_dt;
Expand All @@ -561,6 +575,15 @@ int SqlCtApi::OpenCursor(const char *query, size_t buffer_rows, int buffer_memor
_cursor_cols[i]._data = new char[_cursor_cols[i]._fetch_len * _cursor_allocated_rows];
}
else
// BINARY data type
if(_cursor_cols[i]._native_dt == CS_BINARY_TYPE)
{
_cursor_cols[i]._native_fetch_dt = _cursor_cols[i]._native_dt;
_cursor_cols[i]._fetch_len = _cursor_cols[i]._len;

_cursor_cols[i]._data = new char[_cursor_cols[i]._fetch_len * _cursor_allocated_rows];
}
else
// BIGINT data type
if(_cursor_cols[i]._native_dt == CS_BIGINT_TYPE)
{
Expand Down Expand Up @@ -759,6 +782,20 @@ int SqlCtApi::OpenCursor(const char *query, size_t buffer_rows, int buffer_memor

fmt[i].datatype = CS_CHAR_TYPE;
fmt[i].maxlength = (CS_INT)_cursor_cols[i]._fetch_len;
}
else
// UNITEXT
if(_cursor_cols[i]._native_dt == CS_UNITEXT_TYPE)
{
// Data fetched as UTF-16 i.e. 0x00 byte goes first for first 127 ASCII characters
_cursor_cols[i]._native_fetch_dt = CS_UNICHAR_TYPE;
_cursor_cols[i]._nchar = true;

_cursor_cols[i]._fetch_len = _cursor_cols[i]._len;
_cursor_cols[i]._data = new char[_cursor_cols[i]._fetch_len * _cursor_allocated_rows];

fmt[i].datatype = CS_UNICHAR_TYPE;
fmt[i].maxlength = (CS_INT)_cursor_cols[i]._fetch_len;
}

// Bind the data to array
Expand Down Expand Up @@ -1192,7 +1229,8 @@ int SqlCtApi::ReadTableColumns(std::string &condition)
_table_columns.push_back(col_meta);
}

rc = Fetch(&rows_fetched, &time_read);
if(rc != 100)
rc = Fetch(&rows_fetched, &time_read);

// No more rows
if(rc == 100)
Expand Down Expand Up @@ -1345,7 +1383,8 @@ int SqlCtApi::ReadIndexes(std::string &condition)
}
}

rc = Fetch(&rows_fetched, &time_read);
if(rc != 100)
rc = Fetch(&rows_fetched, &time_read);

// No more rows
if(rc == 100)
Expand Down Expand Up @@ -1530,7 +1569,8 @@ int SqlCtApi::ReadReferences(std::string &condition)
}
}

rc = Fetch(&rows_fetched, &time_read);
if(rc != 100)
rc = Fetch(&rows_fetched, &time_read);

// No more rows
if(rc == 100)
Expand Down
4 changes: 4 additions & 0 deletions sqldata/sqlctapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
#elif defined(WIN32)
#define CTLIB_DLL "libsybct.dll"
#define CSLIB_DLL "libsybcs.dll"
#else
#define CTLIB_DLL "libsybct64.so"
#define CSLIB_DLL "libsybcs64.so"
#endif

// Sybase ASE 12.5 DLLs
Expand Down Expand Up @@ -79,6 +82,7 @@ class SqlCtApi : public SqlApiBase
std::string _user;
std::string _pwd;
std::string _server;
std::string _port;
std::string _db;

// Open cursor command
Expand Down
4 changes: 3 additions & 1 deletion sqldata/sqldata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2359,7 +2359,9 @@ void SqlData::GetIdentityMetaTask(SqlColMeta &col)
char start_str[11];
char inc_str[11];

sprintf(start_str, "%d", col.id_next);
int start = (col.id_next > 0) ? col.id_next : col.id_start;

sprintf(start_str, "%d", start);
sprintf(inc_str, "%d", col.id_inc);

// Create sequence
Expand Down
2 changes: 1 addition & 1 deletion sqldata/sqldata.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#include "applog.h"

#define SQLDATA_NAME "SQLines Data"
#define SQLDATA_VERSION_NUMBER "3.1.317"
#define SQLDATA_VERSION_NUMBER "3.1.703"

#if defined(_WIN64)
#define SQLDATA_VERSION SQLDATA_NAME ## " " ## SQLDATA_VERSION_NUMBER ##" x64"
Expand Down
24 changes: 17 additions & 7 deletions sqldata/sqldatacmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -930,12 +930,11 @@ void SqlDataCmd::CallbackValidationRows(SqlDataReply *reply)

// Show differences
if(reply->_int1 != 0)
{
_log.Log("\n Not Equal: %d row%s, %d of %d column%s (%s)", reply->_int1, SUFFIX(reply->_int1),
reply->_int2, reply->_int3, SUFFIX(reply->_int3), reply->data2);
_log.Log("\n Source query: %s", reply->s_sql_l.c_str());
_log.Log("\n Target query: %s", reply->t_sql_l.c_str());
}

_log.Log("\n Source query: %s", reply->s_sql_l.c_str());
_log.Log("\n Target query: %s", reply->t_sql_l.c_str());
}
else
// All tables validated
Expand Down Expand Up @@ -1145,8 +1144,19 @@ int SqlDataCmd::ReadMetadata()

// Create queues to transfer schema metadata
std::string meta_filter = _t;

if(_t.empty())
meta_filter = "*";
{
int c = 0;
for(std::list<std::string>::iterator i = avail_tables.begin(); i != avail_tables.end(); i++)
{
if(c > 0)
meta_filter += ",";

meta_filter += (*i);
c++;
}
}

_sqlData.CreateMetadataQueues(meta_filter, _texcl);

Expand Down Expand Up @@ -1790,13 +1800,13 @@ void SqlDataCmd::PrintHowToUse()
printf("\n\nExample:");
printf("\n\nTransfer table cities from Oracle to SQL Server");
#if defined(WIN32) || defined(_WIN64)
printf("\n\n sqldata.exe -sd=oracle,scott/tiger@orcl -td=sql,trusted@srv1.hr -t=cities");
printf("\n\n sqldata.exe -sd=oracle,scott/tiger@orcl -td=sql,trusted@srv1,hr -t=cities");
printf("\n");
printf("\nRun sqldata_w.exe to launch a GUI version of SQLData.\n");
printf("\nPress any key to continue...\n");
_getch();
#else
printf("\n\n ./sqldata -sd=oracle,scott/tiger@orcl -td=sql,trusted@srv1.hr -t=cities");
printf("\n\n ./sqldata -sd=oracle,scott/tiger@orcl -td=sql,trusted@srv1,hr -t=cities");
printf("\n\n");
#endif
}
Expand Down
Loading

0 comments on commit 069c7ee

Please sign in to comment.