int main( int argc, char **argv ) { FILE *input = stdin; PVARTEXT pvt_cmd; TEXTCHAR readbuf[4096]; TEXTCHAR *buf; int offset = 0; int no_headers = 0; PODBC default_odbc = NULL; CTEXTSTR select_into; PLIST output = NULL; PLIST outputs = NULL; int arg_ofs = 0; SQLSetFeedbackHandler( ShowSQLStates ); //SetAllocateDebug( TRUE ); //SetAllocateLogging( TRUE ); if( argc < 2 ) Usage( 1 ); else { while( argv[1+arg_ofs] && ( argv[1+arg_ofs][0] == '-' ) ) { TEXTSTR tmp; switch( argv[1+arg_ofs][1] ) { case 'n': no_headers = 1; break; case 'f': arg_ofs++; input = sack_fopen( 0, tmp = DupCharToText( argv[1+arg_ofs] ), WIDE("rt") ); if( input ) SQLSetFeedbackHandler( LogSQLStates ); break; } if( tmp ) { Deallocate( TEXTSTR, tmp ); tmp = NULL; } arg_ofs++; } if( argv[1+arg_ofs] ) default_odbc = ConnectToDatabase( DupCharToText( argv[1 + arg_ofs] ) ); } SetHeapUnit( 4096 * 1024 ); // 4 megs expansion if needed... pvt_cmd = VarTextCreateExx( 10000, 50000 ); while( (buf = readbuf), fgets( readbuf + offset , sizeof( readbuf ) - offset , input ) ) { CTEXTSTR *result = NULL; size_t len; while( buf[0] == WIDE(' ') || buf[0] == WIDE('\t') ) buf++; len = strlen( buf ); if( buf[0] == WIDE('#') ) continue; if( ( len > 0 ) && buf[len-1] == WIDE('\n') ) { len--; buf[len] = 0; } if( strcmp( buf, WIDE("\\q") ) == 0 ) break; if( !buf[0] && VarTextLength( pvt_cmd ) == 0 ) continue; if( ( len > 0 ) && buf[len-1] == WIDE('\\') ) { buf[len-1] = 0; len--; vtprintf( pvt_cmd, WIDE("%s"), buf ); offset = 0; //offset = (len - 1); // read over the slash continue; } else { if( len > 0 ) vtprintf( pvt_cmd, WIDE("%s"), buf ); offset = 0; } buf = GetText( VarTextPeek( pvt_cmd ) ); if( buf[0] == WIDE('?') ) { int fields; int replace = 0; int ofs = 1; CTEXTSTR *columns; TEXTSTR *_columns; PVARTEXT pvt = NULL; if( buf[1] == WIDE('!') ) { replace = 1; ofs = 2; } if( output ) { if( !select_into || !select_into[0] ) { printf( WIDE("Table name was invalid to insert into on the destination side...\'%s\'"), select_into ); VarTextEmpty( pvt_cmd ); continue; } pvt = VarTextCreateExx( 10000, 50000 ); } if( SQLRecordQuery( default_odbc, buf + ofs, &fields, &result, &columns ) ) { int count = 0; int first = 1; _columns = NewArray( TEXTSTR, fields ); if( !no_headers ) { { int n; for( n = 0; n < fields; n++ ) { _columns[n] = StrDup( columns[n] ); if( !pvt ) fprintf( stdout, WIDE("%s%s"), n?WIDE(","):WIDE(""), columns[n] ); } } if( !pvt ) fprintf( stdout, WIDE("\n") ); } for( ; result; FetchSQLRecord( default_odbc, &result ) ) { if( pvt && first ) { vtprintf( pvt, WIDE("%s into `%s` ("), replace?WIDE("replace"):WIDE("insert ignore"), select_into ); { int first = 1; int n; for( n = 0; n < fields; n++ ) { vtprintf( pvt, WIDE("%s`%s`"), first?WIDE(""):WIDE(","), _columns[n] ); first = 0; } } vtprintf( pvt, WIDE(") values ") ); } if( pvt ) { vtprintf( pvt, WIDE("%s("), first?WIDE(""):WIDE(",") ); { int first = 1; // private first, sorry :) parse that, Visual studio can. int n; for( n = 0; n < fields; n++ ) { TEXTSTR tmp; vtprintf( pvt, WIDE("%s%s") , first?WIDE(""):WIDE(",") , result[n]?(tmp=EscapeStringOpt( result[n], TRUE)):((tmp=NULL),WIDE("NULL")) ); Release( tmp ); first = 0; } } vtprintf( pvt, WIDE(")") ); } else { int n; int first = 1; for( n = 0; n < fields; n++ ) { fprintf( stdout, WIDE("%s%s"), first?WIDE(""):WIDE(","),result[n]?result[n]:WIDE("NULL") ); first = 0; } fprintf( stdout, WIDE("\n") ); } first = 0; count++; if( ( VarTextLength( pvt ) ) > 100000 ) { PTEXT cmd; first = 1; // reset first to rebuild the beginning of the insert. printf( WIDE("Flushing at 100k characters...%d records\n"), count ); if( pvt ) { cmd = VarTextGet( pvt ); if( cmd ) { INDEX idx; PODBC odbc; LIST_FORALL( output, idx, PODBC, odbc ) { if( !SQLCommand( odbc, GetText( cmd ) ) ) printf( WIDE("Failed command to:%s\n"), (CTEXTSTR)GetLink( &outputs, idx ) ); } LineRelease( cmd ); } } } } if( !no_headers ) { int n; for( n = 0; n < fields; n++ ) { Release( _columns[n] ); } } Release( _columns ); }
//-------------------------------------------------------------------------- void DatabaseInteraction::Init() { ConnectToDatabase(); }
int main( int argc, char **argv ) { int n; g.dsn = "version.db"; g.build_id = INVALID_INDEX; g.flags.use_common_build = 1; // force this flag... for( n = 1; n < argc; n++ ) { if( argv[n][0] == '-' ) { switch( argv[n][1] ) { case 'n': case 'N': g.flags.skip_push = 1; break; case 'b': case 'B': if( argv[n][2] ) g.build_id = atoi( argv[n] + 2); else if( n < (argc-1) ) g.build_id = atoi( argv[++n] ); break; case 'u': case 'U': if( !l.odbc ) l.odbc = ConnectToDatabase( g.dsn ); IncrementBuild( l.odbc ); break; case 'd': case 'D': if( argv[n][2] ) g.dsn = argv[n] + 2; else if( n < (argc-1) ) g.dsn = argv[++n]; if( l.odbc ) CloseDatabase( l.odbc ); l.odbc = ConnectToDatabase( g.dsn ); lprintf( "new db %p", l.odbc ); break; case 'v': case 'V': if( !l.odbc ) l.odbc = ConnectToDatabase( g.dsn ); if( argv[n][2] ) SetCurrentVersion( l.odbc, argv[n]+2 ); else if( n < (argc-1) ) SetCurrentVersion( l.odbc, argv[++n] ); break; } } else { PPROJECT_ROOT project_root = New( PROJECT_ROOT ); if( !l.odbc ) l.odbc = ConnectToDatabase( g.dsn ); project_root->root_path = argv[n]; project_root->project_id = CheckProjectTable( l.odbc, argv[n] ); SetCurrentPath( project_root->root_path ); // GetBuildVersion also does the hg tag.... project_root->build_id = GetBuildVersion( l.odbc, project_root->project_id ); if( !g.flags.skip_push ) System( "hg push", NULL, 0 ); } } if( n == 1 ) { printf( "Usage: %s [-b build_id] [-u] [-v version] [-d dsn] [-n] [project]\n", argv[0] ); printf( " option order matters; such that - option must preceed the project otherwise does not matter\n" ); printf( " -b sets the current build number\n" ); printf( " build_id is an integer; it specifies the least significant build digits\n" ); printf( " -v sets the major version part\n" ); printf( " version is a string; it specifies the major part of the version\n" ); printf( " -d specifies the database; if not specified will be version.db in the current working directory.\n" ); printf( " dsn is a string; it is the data source name (.db extension will trigger sqlite)\n" ); printf( " project is a string; it specifies the application name for the versioning\n" ); printf( " -u increments the current build number.\n" ); printf( " -n skips running 'hg push' after 'hg tag'\n" ); printf( " using -v will set the current default for the next update\n" ); printf( " using -b sets the current so the tool can be called without -u to rebuild.\n" ); } return 0; }