mz::JSON2SQLite::JSON2SQLite( const char* json, const char* ini, const char* db ) { mp_json = new mz::JSONParser( json ); mp_ini = new mz::TableInfo( ini ); ini_table = ((mz::TableInfo*)mp_ini); FillTableInfo(); }
/*********************************************************************** ** FillTableDesc() ** ** This function will randomly fill in all the information needed in the ** TableDescription structure. ************************************************************************/ void FillTableDesc(TableDescription *TablePtr) { TableInfo *TPtr; KeyDef *KPtr; ColumnInfo *CPtr; short i,j; short temp; short AbortColumn; short ZerosumColumn; short LastIdColumn; short Column[SQL_MAX_COLUMNS]; short ColumnCount; short KeyLengthMax; short KeyLength; short ActualKeyColCount; TPtr=TablePtr->TableInfoPtr; /* build a list of all columns */ for(i=0;i<TPtr->NumOfCol;i++) Column[i]=i; ColumnCount=TPtr->NumOfCol; /* if entry seq. or relative table then the key column is always */ /* added by the system and is a system key and always column 0 */ /* need to adjust the column count to allow for the addition of */ /* a system key and still keep the same column count */ if(TPtr->Organization==ENTRY_SEQ || TPtr->Organization==RELATIVE_TABLE){ TPtr->KeyType=SYSTEM_KEY; ColumnCount--; } else { /* NOMAD cannot work with a key seq. table that has only a system */ /* key so, make the key type either primary or clustering */ if(RANDOM_T_OR_F) { TPtr->KeyType=PRIMARY_KEY; KeyLengthMax=255; } else { TPtr->KeyType=CLUSTERING_KEY; KeyLengthMax=247; } } /* Randomly pick a column to be a numeric data type for the abort column */ temp=RANDOM_NUM0(ColumnCount-1); AbortColumn=Column[temp]; CPtr=TPtr->ColPtr+AbortColumn; CPtr->DataType=RandomNumericType(); /* if type is NUMERIC, DECIMAL, or PIC then make sure the length */ /* and/or scale is set to a value NOMAD can use */ if((CPtr->DataType==TYPE_NUMERIC)||(CPtr->DataType==TYPE_DECIMAL)){ CPtr->DataTypeLen=RANDOM_RANGE(5,18); CPtr->DataTypeScale=0; } /* remove that column number from the list of column choices */ for(i=temp;i+1<ColumnCount;i++) Column[i]=Column[i+1]; ColumnCount--; /* Randomly pick a column to be a numeric data type for zerosum column */ temp=RANDOM_NUM0(ColumnCount-1); ZerosumColumn=Column[temp]; CPtr=TPtr->ColPtr+ZerosumColumn; CPtr->DataType=RandomNumericType(); /* if type is NUMERIC, DECIMAL, or PIC then make sure the length */ /* and/or scale is set to a value NOMAD can use */ if((CPtr->DataType==TYPE_NUMERIC)||(CPtr->DataType==TYPE_DECIMAL)){ CPtr->DataTypeLen=RANDOM_RANGE(5,18); CPtr->DataTypeScale=0; } /* remove that column number from the list of column choices */ for(i=temp;i+1<ColumnCount;i++) Column[i]=Column[i+1]; ColumnCount--; /* Randomly pick a column to be a numeric data type for last-id column */ temp=RANDOM_NUM0(ColumnCount-1); LastIdColumn=Column[temp]; CPtr=TPtr->ColPtr+LastIdColumn; CPtr->DataType=RandomNonDateTimeType(); /* if type is NUMERIC, DECIMAL, PIC, CHAR, VCHAR, or PICX then make */ /* sure the length and/or scale is set to a value NOMAD can use */ if((CPtr->DataType==TYPE_NUMERIC)|| (CPtr->DataType==TYPE_DECIMAL)|| (CPtr->DataType==TYPE_CHAR)|| (CPtr->DataType==TYPE_VARCHAR)){ CPtr->DataTypeLen=RANDOM_RANGE(5,18); CPtr->DataTypeScale=0; } /* remove that column number from the list of column choices */ for(i=temp;i+1<ColumnCount;i++) Column[i]=Column[i+1]; ColumnCount--; /* if a key seq. table then we have some work to do to set up the */ /* key field that NOMAD will use to keep track of records with */ if(TPtr->Organization==KEY_SEQ){ /* assign the key columns so that none of the three columns just picked */ /* will be used as part of the key. First, set up at least one */ /* column of the key to meet NOMAD's requirements */ /* make sure one of the key columns is a non-datetime type */ KPtr=TPtr->KeyPtr; temp=RANDOM_NUM0(ColumnCount-1); KPtr->ColNum=Column[temp]; CPtr=TPtr->ColPtr+(KPtr->ColNum); CPtr->DataType=RandomNonDateTimeType(); for(j=temp;j+1<ColumnCount;j++) Column[j]=Column[j+1]; ColumnCount--; KPtr++; /* if type is NUMERIC or DECIMAL, then make sure the length */ /* and/or scale is set to a value NOMAD can use */ if((CPtr->DataType==TYPE_NUMERIC)|| (CPtr->DataType==TYPE_DECIMAL)|| (CPtr->DataType==TYPE_CHAR)|| (CPtr->DataType==TYPE_VARCHAR)){ CPtr->DataTypeLen=RANDOM_RANGE(5,18); CPtr->DataTypeScale=0; } KeyLength=(short)CPtr->DataTypeLen; /* Now pick the rest of the key columns randomly */ /* loop until we have the number of key columns we wanted or until */ /* we run out of columns to choose from */ ActualKeyColCount=1; i=1; while(KeyLengthMax!=(TPtr->KeyType==PRIMARY_KEY ? 255 : 247) && (i<TPtr->KeyColCount) && (ColumnCount!=0)){ temp=RANDOM_NUM0(ColumnCount); KPtr->ColNum=Column[temp]; CPtr=TPtr->ColPtr+(KPtr->ColNum); FillColumnInfo(CPtr); /* see if this key column will make the total key length exceed */ /* the maximum key length. If it doesn't then we can use this one */ /* for part of the key. If it does, then randomly make up another */ /* set of column information until we get one we can use */ while(KeyLength+(CPtr->DataTypeLen) > KeyLengthMax){ /* clear column info */ memset(CPtr,-1,sizeof(ColumnInfo)); CPtr->CName[0] = NULL; CPtr->Literal = NULL; CPtr->CHeading[0] = NULL; /* Randomly create new column info */ FillColumnInfo(CPtr); } ActualKeyColCount++; KeyLength+=(short)CPtr->DataTypeLen; /* remove it from the list of column choices */ for(j=temp;j+1<ColumnCount;j++) Column[j]=Column[j+1]; ColumnCount--; KPtr++; i++; } /* end: while */ /* it might have been the case that we could not select the requested */ /* number of key columns because the maximum key length would have */ /* been exceeded no matter which combination of columns were chosen */ /* So, we'll adjust the key column count here to be the actual count */ TPtr->KeyColCount=ActualKeyColCount; } /* end: if KEY_SEQ */ /* Now just fill in the TableInfo part. The NomadInfo */ /* will be filled in later by CreateSQLTable() */ FillTableInfo(TablePtr->TableInfoPtr); } /* end: FillTableDesc() */
/******************************************************************** ** FindRequiredColumns() ** ** This function finds the required column numbers for the three ** required columns in an SQL table (in addition to any key columns). ** The three columns can be of any SQL data type EXCEPT date-time and ** can NOT be a key column. The three columns are ZEROSUM, ABORT, and ** LAST PROCESS ID and are used for consistency checking and problem ** analysis. While the key may be composed of several columns, there is ** the requirement that at least one column of the key MUST not be a ** date-time SQL data type and have a scale of 5 or greater. ** ** Input: ** - TableDescription ********************************************************************/ ReturnStatus *FindRequiredColumns(TableDescription *table_ptr) { short key_column[SQL_MAX_KEY_COLUMNS]; TableInfo *TPtr; NomadInfo *NPtr; ReturnStatus *RSPtr; short column_number; short temp_size; Boolean done; key_info *tptr_key; short temp_data_type; short i; short memory_required; short unknown; /* counter for key column data types */ /* initialize some pointers to save typing in long pointer names */ TPtr=table_ptr->TableInfoPtr; NPtr=table_ptr->NomadInfoPtr; RSPtr=NULL; switch(TPtr->Organization){ case RELATIVE_TABLE: NPtr->key_column_used=0; NPtr->key_column_count=1; NPtr->key_ptr=(key_info *)malloc(sizeof(key_info)); if(NPtr->key_ptr==NULL) return(BuildReturnStatusMALLOC); NPtr->key_ptr->ColNum=0; memory_required=(short)TPtr->ColPtr[0].DataTypeLen; NPtr->key_ptr->DefaultValue=(char *)malloc(memory_required); if(NPtr->key_ptr->DefaultValue==NULL) return(BuildReturnStatusMALLOC); break; case ENTRY_SEQ: NPtr->key_column_used= ScanTableColumnsForNondatetime(TPtr,0); NPtr->key_column_count=1; NPtr->key_ptr=(key_info *)malloc(sizeof(key_info)); if(NPtr->key_ptr==NULL) return(BuildReturnStatusMALLOC); NPtr->key_ptr->ColNum=NPtr->key_column_used; memory_required=(short)TPtr->ColPtr[NPtr->key_column_used].DataTypeLen; NPtr->key_ptr->DefaultValue=(char *)malloc(memory_required); if(NPtr->key_ptr->DefaultValue==NULL) return(BuildReturnStatusMALLOC); break; case KEY_SEQ: NPtr->key_column_count=TPtr->KeyColCount; for(i=0;i<NPtr->key_column_count;i++){ key_column[i]=TPtr->KeyPtr[i].ColNum; } /* remove SYSKEY column from our key column list if it is there */ /* because we ignore it when dealing with key sequenced tables */ /* the SYSKEY column is always the first column of a table */ /* SYSKEY is also the least significant key column of a clustering key */ if((TPtr->KeyType==CLUSTERING_KEY) || (TPtr->KeyType==SYSTEM_KEY)){ for(i=0;i+1<NPtr->key_column_count;i++){ key_column[i]=key_column[i+1]; } NPtr->key_column_count--; } // check that we have at least one non-SYSKEY key to proceed if(NPtr->key_column_count<=0){ RSPtr=BuildReturnStatus(RT_PROGRAMERR,0,NULL, "%s need at least one primary key column (other than SYSKEY) in '%s'.\n", g_errstr,TPtr->TableName); return(RSPtr); } /* allocate space for key column numbers */ temp_size=NPtr->key_column_count*sizeof(key_info); NPtr->key_ptr=(key_info *)malloc(temp_size); if(NPtr->key_ptr==NULL) return(BuildReturnStatusMALLOC); /* set column numbers of key columns into TableDescription structure */ unknown=0; NPtr->key_column_used=-1; tptr_key=NPtr->key_ptr; FillTableInfo(TPtr); for(i=0;i<NPtr->key_column_count;i++){ tptr_key->ColNum=key_column[i]; temp_data_type=TPtr->ColPtr[key_column[i]].pTypeInfo->SQLDataType; memory_required=(short)TPtr->ColPtr[key_column[i]].DataTypeLen; /* pick a key column to use as our record number key */ /* NOTE: can NOT be a datetime data type and must be able to hold...*/ /* ... a five digit value if any other SQL data type */ /* The FIRST key column which meets our requirements will be chosen */ switch(temp_data_type){ case SQL_INTEGER: case SQL_SMALLINT: case SQL_FLOAT: case SQL_REAL: case SQL_DOUBLE: case SQL_BIGINT: if(NPtr->key_column_used==-1){ NPtr->key_column_used=key_column[i]; } break; case SQL_NUMERIC: case SQL_DECIMAL: if(TPtr->ColPtr[key_column[i]].DataTypePrecision>=5){ if(NPtr->key_column_used==-1){ NPtr->key_column_used=key_column[i]; } } break; case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: if(TPtr->ColPtr[key_column[i]].DataTypeLen>=5){ if(NPtr->key_column_used==-1){ NPtr->key_column_used=key_column[i]; } } memory_required++; // add byte for NULL terminator break; case SQL_BINARY: case SQL_VARBINARY: case SQL_LONGVARBINARY: if(TPtr->ColPtr[key_column[i]].DataTypeLen>=5){ if(NPtr->key_column_used==-1){ NPtr->key_column_used=key_column[i]; } } break; // These types can't be used for the record number key column case SQL_DATE: case SQL_TIME: case SQL_TIMESTAMP: case SQL_TINYINT: case SQL_BIT: /* an unknown data type */ default: unknown++; } /* end switch */ /* allocate space for the constant value used for key columns */ /* in the case of more than one column in the key. We will select */ /* one column to use and the others will have a fixed value */ tptr_key->DefaultValue=(char *)malloc(memory_required); if(tptr_key->DefaultValue==NULL) return(BuildReturnStatusMALLOC); /* save a random fixed value to use for this key column */ memcpy(tptr_key->DefaultValue, TPtr->ColPtr[key_column[i]].Value.pChar, memory_required); tptr_key++; } break; } /* end: switch on file type */ /* check that we found a key column to use that met our requirements */ if(NPtr->key_column_used<=-1){ RSPtr=BuildReturnStatus(RT_PROGRAMERR,0,NULL, "%s ONE column of the key MUST meet these requirements:\n" " o NOT be an SQL date-time or interval data type\n" " o if NUMERIC or DECIMAL it MUST have precision >= 5\n" " o if any CHAR or BINARY types it MUST have length >= 5\n" " Hey, who knows why...ask my boss...at any rate I wasn't able to find\n" " a column within the key of table '%s'\n" " that met all those lofty requirements.\n" " I know you already know what this means but, I'm going to tell you\n" " anyway, just to make it official: 'I can't use this table'\n" " Change the key for this table or give me another table\n\n", g_errstr,TPtr->TableName); return(RSPtr); } /* scan fields looking for 16 bit (or larger) short field to be zerosum */ column_number=0; done=FALSE; column_number=ScanTableColumnsForNumber(TPtr,column_number); while((!done) && (column_number>=0)) { /* make sure the column is large enough to hold the zerosum values */ if(TPtr->ColPtr[column_number].DataTypePrecision>=5){ /* make sure its not one of the columns of the key */ if(is_key_column(table_ptr,column_number)) { column_number++; column_number=ScanTableColumnsForNumber(TPtr,column_number); } else done=TRUE; } else { column_number++; column_number=ScanTableColumnsForNumber(TPtr,column_number); } } if(column_number<0){ RSPtr=BuildReturnStatus(RT_PROGRAMERR,0,NULL, "%s unable to find two numeric columns and one non-datetime\n" " column that are not part of the key\n", g_errstr); return(RSPtr); } NPtr->zerosum_column=column_number; /* scan fields looking for 16 bit (or larger) short field to be abort */ column_number=0; done=FALSE; column_number=ScanTableColumnsForNumber(TPtr,column_number); while(!done) { /* make sure its not one of the columns of the key or zerosum */ if((is_key_column(table_ptr,column_number))|| (column_number==NPtr->zerosum_column)){ column_number++; column_number=ScanTableColumnsForNumber(TPtr,column_number); } else done=TRUE; } if(column_number<0){ RSPtr=BuildReturnStatus(RT_PROGRAMERR,0,NULL, "%s unable to find two numeric columns and one non-datetime\n" " column that are not part of the key\n", g_errstr); return(RSPtr); } NPtr->abort_column=column_number; /* scan fields looking for any non-date-time column to be process-id */ column_number=0; done=FALSE; column_number=ScanTableColumnsForNumber(TPtr,column_number); while(!done) { /* make sure its not one of the columns of the key, zerosum, or ...*/ /*...abort columns */ if((is_key_column(table_ptr,column_number))|| (column_number==NPtr->zerosum_column)|| (column_number==NPtr->abort_column)){ column_number++; column_number=ScanTableColumnsForNumber(TPtr,column_number); } else done=TRUE; } if(column_number<0){ RSPtr=BuildReturnStatus(RT_PROGRAMERR,0,NULL, "%s unable to find three numeric columns that are not part of the key\n", g_errstr); return(RSPtr); } NPtr->last_process_id_column=column_number; return(NULL); } /* end: FindRequiredColumns() */