#include #define STRTOK strtok #define LAFCMS_DL_MSSQLSERVER_SHAPE_DESC_TOKEN_CHAR "/" #define LAFCMS_CM_NULL_FIELD_TYPE LAFCMS_CM_FIELD_none #define LAFCMS_CM_NULL_FIELD_WIDTH 0 #define LAFCMS_ENUM_CM_FIELD_TYPES LAFCMS_CM_FIELD_none = 0x00, \ LAFCMS_CM_FIELD_autodetect = 0x10, \ LAFCMS_CM_FIELD_string = 0x01, \ LAFCMS_CM_FIELD_long = 0x02, \ LAFCMS_CM_FIELD_double = 0x03, \ LAFCMS_CM_FIELD_cmitem = 0x04, \ LAFCMS_CM_FIELD_old_datetime = 0x12, \ LAFCMS_CM_FIELD_datetime = 0x05, \ LAFCMS_CM_FIELD_boolean = 0x22 #define LAFCMS_ENUM_RETURN_CODES LAFCMS_success = 0, \ LAFCMS_success_recycled_object = 1, \ LAFCMS_fail = 2, \ LAFCMS_fail_eof = 3, \ LAFCMS_error_internal = 10, \ LAFCMS_error_mutex_timeout = 11, \ LAFCMS_error_invalid_object = 12, \ LAFCMS_error_invalid_value = 13, \ LAFCMS_error_cant_happen = 14, \ LAFCMS_error_not_implemented = 15, \ LAFCMS_error_type_mismatch = 16, \ LAFCMS_error_not_found = 17, \ LAFCMS_error_out_of_memory = 18, \ LAFCMS_error_cannot_set_property = 19, \ LAFCMS_error_no_connection = 20, \ LAFCMS_error_database_exception = 21, \ LAFCMS_error_connection_pool_failure = 22, \ LAFCMS_error_data_retrieve_failed = 23, \ LAFCMS_error_no_such_constant = 24, \ LAFCMS_error_bad_array = 25, \ LAFCMS_error_bad_variant = 26, \ LAFCMS_error_bad_bstr = 27, \ LAFCMS_error_queryinterface_failed = 28, \ LAFCMS_error_bad_object = 29, \ LAFCMS_error_connection_mismatch = 30, \ LAFCMS_error_invalid_connection = 31, \ LAFCMS_error_data_too_large = 32, \ LAFCMS_error_data_store_read_only = 33, \ LAFCMS_error_jni_api_failed = 34 enum cm_field_types { LAFCMS_ENUM_CM_FIELD_TYPES }; enum return_codes { LAFCMS_ENUM_RETURN_CODES }; #define LAFCMS_SET_RETURNCODE(RETURNCODE,VALUE) do { RETURNCODE = VALUE; } while (0) #define LAFCMS_ALLOCATE_MEMORY(VARIABLE,TYPE,COMMAND) \ (((LAFCMS_tmp_alloc = (COMMAND)) != NULL) ? ((VARIABLE = (TYPE)LAFCMS_tmp_alloc), LAFCMS_success) : LAFCMS_error_out_of_memory) #define LAFCMS_ALLOCATE_MEMORY_PREP void *LAFCMS_tmp_alloc = NULL struct shape { char *name; cm_field_types type; long width; }; struct field_desc { char *name; cm_field_types type; long width; struct field_desc *next; }; struct LAFCMS_tm { int year, month, day, hour, minute, second, millisecond; }; struct stacker { char *string; struct stacker *next; }; void LAFCMS_string_free(char **target) { if ((target != NULL) && (*target != NULL)) { free(*target); *target = NULL; } return; } return_codes LAFCMS_string_copy_malloc(char **destination, char *source, unsigned int *strlen_destination = NULL) { return_codes return_code = LAFCMS_success; unsigned int tmp_strlen = 0; LAFCMS_ALLOCATE_MEMORY_PREP; if (destination != NULL) if (source == NULL) *destination = NULL; else { tmp_strlen = strlen(source); if ((return_code = LAFCMS_ALLOCATE_MEMORY(*destination, char *, malloc(tmp_strlen + 1))) == LAFCMS_success) strcpy(*destination, source); } if (strlen_destination != NULL) *strlen_destination = tmp_strlen; return(return_code); } return_codes LAFCMS_string_copy_realloc(char **destination, char *source, unsigned int *strlen_destination = NULL) { return_codes return_code = LAFCMS_success; unsigned int tmp_strlen = 0; LAFCMS_ALLOCATE_MEMORY_PREP; if (destination != NULL) if (source == NULL) LAFCMS_string_free(destination); else { tmp_strlen = strlen(source); if ((return_code = LAFCMS_ALLOCATE_MEMORY(*destination, char *, realloc(*destination, tmp_strlen + 1))) == LAFCMS_success) strcpy(*destination, source); } if (strlen_destination != NULL) *strlen_destination = tmp_strlen; return(return_code); } return_codes shape_init(struct shape *target_shape) { return_codes return_code = LAFCMS_success; if (target_shape != NULL) { target_shape->name = NULL; target_shape->type = LAFCMS_CM_NULL_FIELD_TYPE; target_shape->width = LAFCMS_CM_NULL_FIELD_WIDTH; } else LAFCMS_SET_RETURNCODE(return_code, LAFCMS_error_invalid_value); return(return_code); }; return_codes create_content_shape(char *shape_desc, struct shape **return_shape, long *return_num_shapes) { return_codes return_code = LAFCMS_success; struct field_desc *fields = NULL, *tmp_field; char *tmp_shape_desc = NULL, *token = NULL; long i, num_fields, total_strlen; LAFCMS_ALLOCATE_MEMORY_PREP; if (shape_desc != NULL) { if ((return_code = LAFCMS_string_copy_malloc(&tmp_shape_desc, shape_desc)) == LAFCMS_success) { token = STRTOK(tmp_shape_desc, LAFCMS_DL_MSSQLSERVER_SHAPE_DESC_TOKEN_CHAR); num_fields = 0; total_strlen = 0; while ((token != NULL) && (return_code == LAFCMS_success)) { num_fields++; if (fields == NULL) { if ((return_code = LAFCMS_ALLOCATE_MEMORY(fields, struct field_desc *, malloc(sizeof(struct field_desc)))) == LAFCMS_success) tmp_field = fields; } else { if ((return_code = LAFCMS_ALLOCATE_MEMORY(tmp_field->next, struct field_desc *, malloc(sizeof(struct field_desc)))) == LAFCMS_success) tmp_field = tmp_field->next; } if (return_code == LAFCMS_success) { tmp_field->next = NULL; tmp_field->name = token; total_strlen += strlen(token); if ((token = STRTOK(NULL, LAFCMS_DL_MSSQLSERVER_SHAPE_DESC_TOKEN_CHAR)) != NULL) { tmp_field->type = (cm_field_types)atol(token); if ((token = STRTOK(NULL, LAFCMS_DL_MSSQLSERVER_SHAPE_DESC_TOKEN_CHAR)) != NULL) { tmp_field->width = atol(token); token = STRTOK(NULL, LAFCMS_DL_MSSQLSERVER_SHAPE_DESC_TOKEN_CHAR); } else LAFCMS_SET_RETURNCODE(return_code, LAFCMS_error_invalid_value); } else LAFCMS_SET_RETURNCODE(return_code, LAFCMS_error_invalid_value); } } if ((return_code == LAFCMS_success) && ((return_code = LAFCMS_ALLOCATE_MEMORY(*return_shape, struct shape *, malloc(sizeof(struct shape) * (num_fields + 1)))) == LAFCMS_success)) { *return_num_shapes = num_fields; shape_init(&(*return_shape)[num_fields]); tmp_field = fields; i = 0; while (tmp_field != NULL) { shape_init(&(*return_shape)[i]); if ((return_code = LAFCMS_string_copy_malloc(&(*return_shape)[i].name, tmp_field->name)) != LAFCMS_success) break; (*return_shape)[i].type = tmp_field->type; (*return_shape)[i].width = tmp_field->width; i++; tmp_field = tmp_field->next; } } tmp_field = fields; while (tmp_field != NULL) { fields = tmp_field; tmp_field = tmp_field->next; free(fields); } LAFCMS_string_free(&tmp_shape_desc); } } else LAFCMS_SET_RETURNCODE(return_code, LAFCMS_error_invalid_value); return(return_code); } return_codes shape_destroy(struct shape *target_shape) { return_codes return_code = LAFCMS_success; if (target_shape != NULL) { LAFCMS_string_free(&target_shape->name); target_shape->type = LAFCMS_CM_NULL_FIELD_TYPE; target_shape->width = LAFCMS_CM_NULL_FIELD_WIDTH; } else LAFCMS_SET_RETURNCODE(return_code, LAFCMS_error_invalid_value); return(return_code); }; return_codes shape_array_free(struct shape **target_array) { long i; if (*target_array != NULL) { for (i = 0; (*target_array)[i].type != LAFCMS_CM_NULL_FIELD_TYPE; i++) shape_destroy(&(*target_array)[i]); free(*target_array); *target_array = NULL; } return(LAFCMS_success); } void LAFCMS_tm_encode(unsigned long *destination, struct LAFCMS_tm *source) { if (source != NULL) { destination[0] = ((source->year & 0x3FFF) << 9) | ((source->month & 0x000F) << 5) | (source->day & 0x001F); destination[1] = ((source->hour & 0x001F) << 22) | ((source->minute & 0x003F) << 16) | ((source->second & 0x003F) << 10) | (source->millisecond & 0x000003FF); } else { destination[0] = 0; destination[1] = 0; } return; } void trace_statement(char *statement) { long strlen_statement = (long)strlen(statement); char tmp_char = '\0'; while (strlen_statement > 0) { if (strlen_statement >= 511) { tmp_char = statement[510]; statement[510] = '\0'; } TRACE("%s\n", statement); if (strlen_statement >= 511) statement[510] = tmp_char; strlen_statement -= 510; statement += 510; } return; } int migrate(int argc, char *argv[]) { CDatabase tmp_db, tmp_db2; CRecordset tmp_rs, tmp_rs2; CDBVariant tmp_dbvariant; char tmp_guid[27], tmp_id[27]; char *tmp_shape = NULL, *tmp_ptr; char *tmp_tabledesc = NULL; struct shape *shapes = NULL; long num_shapes; char tmp_sql[1024]; int success = 1; unsigned long new_value[2]; struct LAFCMS_tm tmp_lafcms_tm; struct tm *tmp_tm; long i, num_statements = 0; struct stacker *stack = NULL, *end_stack = NULL, *tmp_stack; if (argc == 2) { try { tmp_db.OpenEx(argv[1], CDatabase::noOdbcDialog); tmp_db.BeginTrans(); tmp_db2.OpenEx(argv[1], CDatabase::noOdbcDialog); tmp_rs.m_pDatabase = &tmp_db; tmp_rs2.m_pDatabase = &tmp_db2; printf("Generating SQL statements for Columns, Locations and Values...\n\n"); if (tmp_rs.Open(CRecordset::forwardOnly, (char *)"SELECT * FROM [lafcms_location] WHERE ([shape] LIKE '%/18/0/%')")) { while (!tmp_rs.IsEOF()) { tmp_rs.GetFieldValue((short)0, tmp_dbvariant, SQL_C_CHAR); strcpy(tmp_guid, (LPCTSTR)(*tmp_dbvariant.m_pstring)); tmp_rs.GetFieldValue((short)1, tmp_dbvariant, SQL_C_CHAR); tmp_shape = (char *)malloc(tmp_dbvariant.m_pstring->GetLength() + 1024); strcpy(tmp_shape, (LPCTSTR)(*tmp_dbvariant.m_pstring)); create_content_shape(tmp_shape, &shapes, &num_shapes); tmp_ptr = tmp_shape + sprintf(tmp_shape, "UPDATE [LAFCMS_location] SET [shape] = '"); for (i = 0; i < num_shapes; i++) { if (shapes[i].type == LAFCMS_CM_FIELD_old_datetime) { shapes[i].type = LAFCMS_CM_FIELD_datetime; TRACE("Altering column %s in table %s\n", shapes[i].name, tmp_guid); printf("C"); sprintf(tmp_sql, "ALTER TABLE [LAFCMS__%s] ALTER COLUMN [%s] BINARY(8)", tmp_guid, shapes[i].name); tmp_stack = (struct stacker *)malloc(sizeof(struct stacker)); LAFCMS_string_copy_malloc(&tmp_stack->string, tmp_sql); tmp_stack->next = NULL; if (end_stack == NULL) { end_stack = tmp_stack; stack = tmp_stack; } else { end_stack->next = tmp_stack; end_stack = tmp_stack; } num_statements++; } tmp_ptr += sprintf(tmp_ptr, "%s/%ld/%ld/", shapes[i].name, shapes[i].type, shapes[i].width); } sprintf(tmp_ptr, "' WHERE ([location_id] = '%s')", tmp_guid); TRACE("Fixing location entry for %s\n", tmp_guid); printf("L"); tmp_stack = (struct stacker *)malloc(sizeof(struct stacker)); tmp_stack->string = tmp_shape; tmp_stack->next = NULL; if (end_stack == NULL) { end_stack = tmp_stack; stack = tmp_stack; } else { end_stack->next = tmp_stack; end_stack = tmp_stack; } num_statements++; sprintf(tmp_sql, "SELECT * FROM [LAFCMS__%s]", tmp_guid); if (tmp_rs2.Open(CRecordset::forwardOnly, tmp_sql)) { while (!tmp_rs2.IsEOF()) { tmp_rs2.GetFieldValue((short)0, tmp_dbvariant, SQL_C_CHAR); strcpy(tmp_id, (LPCTSTR)(*tmp_dbvariant.m_pstring)); for (i = 0; i < num_shapes; i++) { if (shapes[i].type == LAFCMS_CM_FIELD_datetime) { tmp_rs2.GetFieldValue((short)(i + 1), tmp_dbvariant, SQL_C_SLONG); tmp_tm = localtime(&tmp_dbvariant.m_lVal); tmp_lafcms_tm.year = tmp_tm->tm_year + 1900; tmp_lafcms_tm.month = tmp_tm->tm_mon + 1; tmp_lafcms_tm.day = tmp_tm->tm_mday; tmp_lafcms_tm.hour = tmp_tm->tm_hour; tmp_lafcms_tm.minute = tmp_tm->tm_min; tmp_lafcms_tm.second = tmp_tm->tm_sec; tmp_lafcms_tm.millisecond = 0; LAFCMS_tm_encode(new_value, &tmp_lafcms_tm); TRACE("Converting %s of record %s (%d/%d/%d %d:%d:%d.%d) in table %s from %ld to 0x%.8X%.8X\n", shapes[i].name, tmp_id, tmp_lafcms_tm.month, tmp_lafcms_tm.day, tmp_lafcms_tm.year, tmp_lafcms_tm.hour, tmp_lafcms_tm.minute, tmp_lafcms_tm.second, tmp_lafcms_tm.millisecond, tmp_guid, tmp_dbvariant.m_lVal, new_value[0], new_value[1]); printf("v"); sprintf(tmp_sql, "UPDATE [LAFCMS__%s] SET [%s] = 0x%.8X%.8X WHERE ([lafcms_item_id] = '%s')", tmp_guid, shapes[i].name, new_value[0], new_value[1], tmp_id); tmp_stack = (struct stacker *)malloc(sizeof(struct stacker)); LAFCMS_string_copy_malloc(&tmp_stack->string, tmp_sql); tmp_stack->next = NULL; if (end_stack == NULL) { end_stack = tmp_stack; stack = tmp_stack; } else { end_stack->next = tmp_stack; end_stack = tmp_stack; } num_statements++; } } tmp_rs2.MoveNext(); } tmp_rs2.Close(); } else { success = 0; break; } shape_array_free(&shapes); tmp_rs.MoveNext(); } tmp_rs.Close(); } else success = 0; if (success) { if (num_statements > 0) { printf("\n\nExecuting SQL statements...\n\n"); tmp_stack = stack; i = 0; while (tmp_stack != NULL) { if (((long)((i / (num_statements * 1.0)) * 100) % 10) == 0) printf("%d", (long)((i / (num_statements * 1.0)) * 10)); else printf("."); trace_statement(tmp_stack->string); tmp_db.ExecuteSQL(tmp_stack->string); LAFCMS_string_free(&tmp_stack->string); stack = stack->next; free(tmp_stack); tmp_stack = stack; i++; } printf("\n"); } else printf("\n\nNothing to do!\n"); tmp_db.CommitTrans(); } else tmp_db.Rollback(); tmp_db.Close(); tmp_db2.Close(); } catch (CDBException *tmp_exception) { printf("ERROR: %s\n", (char *)(LPCTSTR)tmp_exception->m_strError); tmp_exception->Delete(); success = 0; } } else printf("USAGE: %s connection_string\n", argv[0]); return(!success); }