216
224
void dlgDirectDbg::populateParamGrid( )
218
// First, try to load default values from a previous invocation into
219
// m_targetInfo (assuming that we're debugging the same target this
226
for( int count = 0; count < m_targetInfo->getArgCount(); ++count )
228
wsArgInfo & arg = ((*m_targetInfo)[count] );
230
// If this is an IN parameter (or an IN/OUT parameter), add
231
// a new row to the grid
233
if( arg.getMode() != wxT( "o" ))
235
grdParams->AppendRows( 1 );
236
grdParams->SetCellValue( i, COL_NAME, arg.getName());
226
// First, try to load default values from a previous invocation into
227
// m_targetInfo (assuming that we're debugging the same target this
234
for( int count = 0; count < m_targetInfo->getArgCount(); ++count )
236
wsArgInfo &arg = ((*m_targetInfo)[count] );
238
// If this is an IN parameter (or an IN/OUT parameter), add
239
// a new row to the grid
241
if( arg.getMode() != wxT( "o" ))
243
grdParams->AppendRows( 1 );
244
grdParams->SetCellValue( i, COL_NAME, arg.getName());
238
246
// Make it obvious which are variadics
239
247
if (arg.getMode() != wxT( "v" ))
240
grdParams->SetCellValue( i, COL_TYPE, arg.getType());
248
grdParams->SetCellValue( i, COL_TYPE, arg.getType());
242
grdParams->SetCellValue( i, COL_TYPE, arg.getType() + wxT(" VARIADIC"));
244
grdParams->SetCellValue( i, COL_VALUE, arg.getValue());
246
grdParams->SetReadOnly( i, COL_NAME, true );
247
grdParams->SetReadOnly( i, COL_TYPE, true );
248
grdParams->SetReadOnly( i, COL_VALUE, false );
254
// Move the cursor to the first value (so that the user
255
// can just start typing)
257
grdParams->SetGridCursor( 0, COL_VALUE );
258
grdParams->SetFocus();
260
// If the target is defined within package, offer the user
261
// a chance to debug the initializer (there may or may not
262
// be an initializer, we don't really know at this point)
264
if( m_targetInfo->getPkgOid() == 0 )
265
chkPkgInit->Disable();
267
chkPkgInit->Enable();
269
// If the target function has no parameters (and it's not defined within
270
// a package), there's no good reason to wait for the user to hit the Ok
271
// button before we invoke the target...
273
if((m_targetInfo->getArgInCount() + m_targetInfo->getArgInOutCount() == 0 ) && ( m_targetInfo->getPkgOid() == 0))
275
grdParams->AppendRows( 1 );
276
grdParams->SetReadOnly( i, COL_NAME, true );
277
grdParams->SetReadOnly( i, COL_TYPE, true );
278
grdParams->SetReadOnly( i, COL_VALUE, true );
280
grdParams->SetCellValue( 0, COL_NAME, _( "No arguments required" ));
281
wxFont font = grdParams->GetCellFont( 0, COL_NAME );
282
font.SetStyle( wxFONTSTYLE_ITALIC );
283
grdParams->SetCellFont( 0, COL_NAME, font );
285
grdParams->SetColSize(COL_NAME, 200);
250
grdParams->SetCellValue( i, COL_TYPE, arg.getType() + wxT(" VARIADIC"));
252
grdParams->SetCellValue( i, COL_VALUE, arg.getValue());
254
grdParams->SetReadOnly( i, COL_NAME, true );
255
grdParams->SetReadOnly( i, COL_TYPE, true );
256
grdParams->SetReadOnly( i, COL_VALUE, false );
262
// Move the cursor to the first value (so that the user
263
// can just start typing)
265
grdParams->SetGridCursor( 0, COL_VALUE );
266
grdParams->SetFocus();
268
// If the target is defined within package, offer the user
269
// a chance to debug the initializer (there may or may not
270
// be an initializer, we don't really know at this point)
272
if( m_targetInfo->getPkgOid() == 0 )
273
chkPkgInit->Disable();
275
chkPkgInit->Enable();
277
// If the target function has no parameters (and it's not defined within
278
// a package), there's no good reason to wait for the user to hit the Ok
279
// button before we invoke the target...
281
if((m_targetInfo->getArgInCount() + m_targetInfo->getArgInOutCount() == 0 ) && ( m_targetInfo->getPkgOid() == 0))
283
grdParams->AppendRows( 1 );
284
grdParams->SetReadOnly( i, COL_NAME, true );
285
grdParams->SetReadOnly( i, COL_TYPE, true );
286
grdParams->SetReadOnly( i, COL_VALUE, true );
288
grdParams->SetCellValue( 0, COL_NAME, _( "No arguments required" ));
289
wxFont font = grdParams->GetCellFont( 0, COL_NAME );
290
font.SetStyle( wxFONTSTYLE_ITALIC );
291
grdParams->SetCellFont( 0, COL_NAME, font );
293
grdParams->SetColSize(COL_NAME, 200);
292
300
////////////////////////////////////////////////////////////////////////////////
295
303
// This event handler is called when the user clicks the OK button - we call the
296
// activateDebugger() function to set the required breakpoint and invoke the
304
// activateDebugger() function to set the required breakpoint and invoke the
297
305
// target (after nabbing any parameter values from the prompt dialog)
299
void dlgDirectDbg::OnOk( wxCommandEvent & event )
307
void dlgDirectDbg::OnOk( wxCommandEvent &event )
304
312
////////////////////////////////////////////////////////////////////////////////
305
313
// loadSettings()
307
// Loads default values from our .ini file. We save the OID of the most
315
// Loads default values from our .ini file. We save the OID of the most
308
316
// recent direct-debugging target when close a session. If we're direct-
309
317
// debugging the same target this time around, we load the argument values
310
318
// from the .ini file.
312
320
void dlgDirectDbg::loadSettings()
316
settings->Read( wxT( "Debugger/Proc/OID" ), &lastOID, -1 );
318
if( lastOID == m_targetInfo->getOid())
322
for( int i = 0; i < m_targetInfo->getArgCount(); ++i )
324
wsArgInfo & arg = (*m_targetInfo)[i];
326
if( arg.getMode() != wxT( "o" ))
328
settings->Read( wxString::Format( wxT( "Debugger/Proc/argValue%d" ), ++count ), &(arg.getValue()), wxT( "" ));
324
settings->Read( wxT( "Debugger/Proc/OID" ), &lastOID, -1 );
326
if( lastOID == m_targetInfo->getOid())
330
for( int i = 0; i < m_targetInfo->getArgCount(); ++i )
332
wsArgInfo &arg = (*m_targetInfo)[i];
334
if( arg.getMode() != wxT( "o" ))
336
settings->Read( wxString::Format( wxT( "Debugger/Proc/argValue%d" ), ++count ), &(arg.getValue()), wxT( "" ));
334
342
////////////////////////////////////////////////////////////////////////////////
335
343
// saveSettings()
337
// Save default values to our .ini file. We save the OID of the most
338
// recent direct-debugging target when close a session. We also save the
345
// Save default values to our .ini file. We save the OID of the most
346
// recent direct-debugging target when close a session. We also save the
339
347
// value of each argument - if you debug the same target again next time,
340
// loadSettings() will initialize the parameter-values window with the
348
// loadSettings() will initialize the parameter-values window with the
341
349
// same parameter values that you entered in this session.
343
351
void dlgDirectDbg::saveSettings()
345
settings->Write( wxT( "Debugger/Proc/OID" ), m_targetInfo->getOid());
349
for( int i = 0; i < m_targetInfo->getArgCount(); ++i )
351
wsArgInfo & arg = ( *m_targetInfo)[i];
353
if( arg.getMode() != wxT( "o" ))
355
settings->Write( wxString::Format( wxT( "Debugger/Proc/argName%d" ), ++count ), arg.getName());
356
settings->Write( wxString::Format( wxT( "Debugger/Proc/argType%d" ), count ), arg.getType());
357
settings->Write( wxString::Format( wxT( "Debugger/Proc/argValue%d" ), count ), (arg.getValue() == wxT("NULL") ? wxEmptyString : arg.getValue().c_str()));
353
settings->WriteLong( wxT( "Debugger/Proc/OID" ), m_targetInfo->getOid());
357
for( int i = 0; i < m_targetInfo->getArgCount(); ++i )
359
wsArgInfo &arg = ( *m_targetInfo)[i];
361
if( arg.getMode() != wxT( "o" ))
363
settings->Write( wxString::Format( wxT( "Debugger/Proc/argName%d" ), ++count ), arg.getName());
364
settings->Write( wxString::Format( wxT( "Debugger/Proc/argType%d" ), count ), arg.getType());
365
settings->Write( wxString::Format( wxT( "Debugger/Proc/argValue%d" ), count ), wxString((arg.getValue() == wxT("NULL") ? wxEmptyString : arg.getValue().c_str())));
362
370
////////////////////////////////////////////////////////////////////////////////
423
431
// This function is called after the user has filled in any parameter values
424
432
// and clicked the Ok button. activateDebugger() extracts the paramter values
425
433
// from the grid control and copies those values into our dbgTargetInfo object
426
// (m_targetInfo). Next, we set a breakpoint at the target, and, finally,
434
// (m_targetInfo). Next, we set a breakpoint at the target, and, finally,
427
435
// we invoke the target function/procedure
429
437
bool dlgDirectDbg::activateDebugger( )
431
// Unset the completed flag (if it exists)
433
m_codeWindow->m_targetComplete = false;
435
// Copy the parameter values from the grid into m_targetInfo
438
for( int count = 0; count < m_targetInfo->getArgCount(); ++count )
440
wsArgInfo & arg = (*m_targetInfo)[count];
442
// Populate the ArgInfo object's IN or INOUT variables only, OUT
443
// variables will be assigned NULL later on.
445
if(arg.getMode() != wxT("o"))
447
arg.setValue( grdParams->GetCellValue(i, COL_VALUE));
452
// Write the target OID and argument values to our settings file
453
// so that we can default them next time around
456
// Now set a breakpoint at the target (note: the call to setBreakpoint()
457
// will hang until the server sends us a response)
461
// Debug the initialiser. We can only do so once, so unset, and disable
462
// the option after setting the breakpoint
463
if( chkPkgInit->GetValue())
464
setBreakpoint( m_targetInfo->getPkgOid(), m_targetInfo->getPkgInitOid());
466
chkPkgInit->SetValue(false);
467
chkPkgInit->Disable();
469
setBreakpoint( m_targetInfo->getPkgOid(), m_targetInfo->getOid());
471
catch( const std::runtime_error & error )
473
wxMessageBox( wxString( error.what(), wxConvUTF8 ), _( "Cannot create breakpoint" ), wxOK | wxICON_ERROR );
477
// And invoke the target (note: the call to invokeTarget() will *NOT*
478
// wait for a result set from the server - instead, OnResultReady() will
479
// be called when the result set is ready)
485
catch( const std::runtime_error & error )
487
wxMessageBox( wxString( error.what(), wxConvUTF8 ), _( "Cannot invoke target" ), wxOK | wxICON_ERROR );
439
// Unset the completed flag (if it exists)
441
m_codeWindow->m_targetComplete = false;
443
// Copy the parameter values from the grid into m_targetInfo
446
for( int count = 0; count < m_targetInfo->getArgCount(); ++count )
448
wsArgInfo &arg = (*m_targetInfo)[count];
450
// Populate the ArgInfo object's IN or INOUT variables only, OUT
451
// variables will be assigned NULL later on.
453
if(arg.getMode() != wxT("o"))
455
arg.setValue( grdParams->GetCellValue(i, COL_VALUE));
460
// Write the target OID and argument values to our settings file
461
// so that we can default them next time around
464
// Now set a breakpoint at the target (note: the call to setBreakpoint()
465
// will hang until the server sends us a response)
469
// Debug the initialiser. We can only do so once, so unset, and disable
470
// the option after setting the breakpoint
471
if( chkPkgInit->GetValue())
472
setBreakpoint( m_targetInfo->getPkgOid(), m_targetInfo->getPkgInitOid());
474
chkPkgInit->SetValue(false);
475
chkPkgInit->Disable();
477
setBreakpoint( m_targetInfo->getPkgOid(), m_targetInfo->getOid());
479
catch( const std::runtime_error &error )
481
wxMessageBox( wxString( error.what(), wxConvUTF8 ), _( "Cannot create breakpoint" ), wxOK | wxICON_ERROR );
485
// And invoke the target (note: the call to invokeTarget() will *NOT*
486
// wait for a result set from the server - instead, OnResultReady() will
487
// be called when the result set is ready)
493
catch( const std::runtime_error &error )
495
wxMessageBox( wxString( error.what(), wxConvUTF8 ), _( "Cannot invoke target" ), wxOK | wxICON_ERROR );
494
502
////////////////////////////////////////////////////////////////////////////////
495
503
// setBreakpoint()
497
505
// This function creates a breakpoint at the target. For now, we always create
498
// a breakpoint by calling edb_procoid_debug() or plpgsql_procoid_debug() with
499
// the OID of the target. Later, we'll change this function to use the
506
// a breakpoint by calling edb_procoid_debug() or plpgsql_procoid_debug() with
507
// the OID of the target. Later, we'll change this function to use the
500
508
// new CREATE BREAKPOINT command.
502
510
void dlgDirectDbg::setBreakpoint(long pkgOid, long funcOid)
504
dbgResultset * result;
506
if (m_conn->DebuggerApiVersion() <= DEBUGGER_V2_API)
508
if( m_targetInfo->getLanguage() == wxT( "edbspl" ))
509
result = new dbgResultset(m_conn->waitForCommand(wxString::Format(wxT("select edb_oid_debug( %ld, %ld );"), pkgOid, funcOid)));
511
result = new dbgResultset(m_conn->waitForCommand(wxString::Format(wxT("select plpgsql_oid_debug( %ld, %ld );"), pkgOid, funcOid)));
515
if( m_targetInfo->getLanguage() == wxT( "edbspl" ))
516
result = new dbgResultset(m_conn->waitForCommand(wxString::Format(wxT("select edb_oid_debug(%ld);"), funcOid)));
518
result = new dbgResultset(m_conn->waitForCommand(wxString::Format(wxT("select plpgsql_oid_debug(%ld);"), funcOid)));
521
if( result->getCommandStatus() != PGRES_TUPLES_OK )
522
throw( std::runtime_error( result->getRawErrorMessage()));
512
dbgResultset *result;
514
if (m_conn->DebuggerApiVersion() <= DEBUGGER_V2_API)
516
if( m_targetInfo->getLanguage() == wxT( "edbspl" ))
517
result = new dbgResultset(m_conn->waitForCommand(wxString::Format(wxT("select edb_oid_debug( %ld, %ld );"), pkgOid, funcOid)));
519
result = new dbgResultset(m_conn->waitForCommand(wxString::Format(wxT("select plpgsql_oid_debug( %ld, %ld );"), pkgOid, funcOid)));
523
if( m_targetInfo->getLanguage() == wxT( "edbspl" ))
524
result = new dbgResultset(m_conn->waitForCommand(wxString::Format(wxT("select edb_oid_debug(%ld);"), funcOid)));
526
result = new dbgResultset(m_conn->waitForCommand(wxString::Format(wxT("select plpgsql_oid_debug(%ld);"), funcOid)));
529
if( result->getCommandStatus() != PGRES_TUPLES_OK )
530
throw( std::runtime_error( result->getRawErrorMessage()));
525
533
////////////////////////////////////////////////////////////////////////////////
526
534
// invokeTarget()
528
536
// This function invokes the debugger target (that is, the function or procedure
529
// that the user wants to debug). If the target is a function, we generate a
537
// that the user wants to debug). If the target is a function, we generate a
530
538
// SELECT statement; if the target is a procedure, we generate an EXEC statement.
531
539
// In either case, we build the argument list from the argument values found
532
540
// in m_targetInfo
534
542
void dlgDirectDbg::invokeTarget()
536
// If we have access the the EDB extended libpq functions,
537
// and this is a stored procedure, we should execute the
538
// procedure using the callable statement interface to allow
539
// us to retrieve the OUT/INOUT parameter results.
540
// Otherwise, just SELECT/EXEC it as per normal.
544
// If we have access the the EDB extended libpq functions,
545
// and this is a stored procedure, we should execute the
546
// procedure using the callable statement interface to allow
547
// us to retrieve the OUT/INOUT parameter results.
548
// Otherwise, just SELECT/EXEC it as per normal.
542
if (!m_targetInfo->getIsFunction() &&
545
PQiSendQueryPreparedOut)
546
invokeTargetCallable();
550
if (!m_conn->EdbMinimumVersion(9, 0) &&
551
!m_targetInfo->getIsFunction() &&
554
PQiSendQueryPreparedOut)
555
invokeTargetCallable();
550
if (!m_targetInfo->getIsFunction())
551
invokeTargetCallable();
555
invokeTargetStatement();
557
// Since parameter window has done its job, we need to hide
558
// it and let code window come in front.
561
m_codeWindow->enableTools();
562
m_codeWindow->resumeLocalDebugging();
559
if (!m_conn->EdbMinimumVersion(9, 0) &&
560
!m_targetInfo->getIsFunction())
561
invokeTargetCallable();
565
invokeTargetStatement();
567
// Since parameter window has done its job, we need to hide
568
// it and let code window come in front.
571
m_codeWindow->enableTools();
572
m_codeWindow->resumeLocalDebugging();
568
578
void dlgDirectDbg::invokeTargetCallable()
570
dbgPgParams *params = new dbgPgParams();
572
wxString query = wxT("CALL ") + m_targetInfo->getFQName() + wxT("(");
574
// Setup the param struct.
575
params->nParams = m_targetInfo->getArgCount();
576
params->paramTypes = new Oid[params->nParams];
577
params->paramValues = new char*[params->nParams];
578
params->paramModes = new int[params->nParams];
580
// Iterate through the parameters, adding them to the param
581
// struct and the statement as we go.
582
for( int i = 0; i < params->nParams; ++i )
584
wsArgInfo &arg = (*m_targetInfo)[i];
586
params->paramTypes[i] = arg.getTypeOid();
588
if(arg.getMode() == wxT("o")) // OUT
590
params->paramModes[i] = 2;
591
params->paramValues[i] = 0;
593
else if(arg.getMode() == wxT("b")) // IN OUT
595
params->paramModes[i] = 3;
597
int len = arg.getValue().Length() + 1;
598
char *tmp = new char[len];
599
snprintf(tmp, len, "%s", (const char *)arg.getValue().mb_str(wxConvUTF8));
600
if (strcmp(tmp, "") == 0)
601
params->paramValues[i] = 0;
602
else if (strcmp(tmp, "''") == 0)
603
params->paramValues[i] = (char *)"";
604
else if (strcmp(tmp, "\\'\\'") == 0)
605
params->paramValues[i] = (char *)"''";
607
params->paramValues[i] = tmp;
611
params->paramModes[i] = 1;
613
int len = arg.getValue().Length() + 1;
614
char *tmp = new char[len];
615
snprintf(tmp, len, "%s", (const char *)arg.getValue().mb_str(wxConvUTF8));
616
if (strcmp(tmp, "") == 0)
617
params->paramValues[i] = 0;
618
else if (strcmp(tmp, "''") == 0)
619
params->paramValues[i] = (char *)"";
620
else if (strcmp(tmp, "\\'\\'") == 0)
621
params->paramValues[i] = (char *)"''";
623
params->paramValues[i] = tmp;
628
query += wxString::Format(wxT("$%d::"), i + 1) + arg.getType();
634
// And send the completed command to the server - we'll get
635
// a dbgDbResult event when the command completes (and that
636
// event will get routed to dlgDirectDbg::OnResultReady())
637
m_conn->startCommand( query, GetEventHandler(), RESULT_ID_DIRECT_TARGET_COMPLETE, params );
580
dbgPgParams *params = new dbgPgParams();
582
wxString query = wxT("CALL ") + m_targetInfo->getFQName() + wxT("(");
584
// Setup the param struct.
585
params->nParams = m_targetInfo->getArgCount();
586
params->paramTypes = new Oid[params->nParams];
587
params->paramValues = new char*[params->nParams];
588
params->paramModes = new int[params->nParams];
590
// Iterate through the parameters, adding them to the param
591
// struct and the statement as we go.
592
for( int i = 0; i < params->nParams; ++i )
594
wsArgInfo &arg = (*m_targetInfo)[i];
596
params->paramTypes[i] = arg.getTypeOid();
598
if(arg.getMode() == wxT("o")) // OUT
600
params->paramModes[i] = 2;
601
params->paramValues[i] = 0;
603
else if(arg.getMode() == wxT("b")) // IN OUT
605
params->paramModes[i] = 3;
607
int len = arg.getValue().Length() + 1;
608
char *tmp = new char[len];
609
snprintf(tmp, len, "%s", (const char *)arg.getValue().mb_str(wxConvUTF8));
610
if (strcmp(tmp, "") == 0)
611
params->paramValues[i] = 0;
612
else if (strcmp(tmp, "''") == 0)
613
params->paramValues[i] = (char *)"";
614
else if (strcmp(tmp, "\\'\\'") == 0)
615
params->paramValues[i] = (char *)"''";
617
params->paramValues[i] = tmp;
621
params->paramModes[i] = 1;
623
int len = arg.getValue().Length() + 1;
624
char *tmp = new char[len];
625
snprintf(tmp, len, "%s", (const char *)arg.getValue().mb_str(wxConvUTF8));
626
if (strcmp(tmp, "") == 0)
627
params->paramValues[i] = 0;
628
else if (strcmp(tmp, "''") == 0)
629
params->paramValues[i] = (char *)"";
630
else if (strcmp(tmp, "\\'\\'") == 0)
631
params->paramValues[i] = (char *)"''";
633
params->paramValues[i] = tmp;
638
query += wxString::Format(wxT("$%d::"), i + 1) + arg.getType();
644
// And send the completed command to the server - we'll get
645
// a dbgDbResult event when the command completes (and that
646
// event will get routed to dlgDirectDbg::OnResultReady())
647
m_conn->startCommand( query, GetEventHandler(), RESULT_ID_DIRECT_TARGET_COMPLETE, params );
640
650
void dlgDirectDbg::invokeTargetStatement()
642
wxString query, declareStatement;
643
if (!m_conn->EdbMinimumVersion(8, 4))
644
query = m_targetInfo->getIsFunction() ? wxT( "SELECT " ) : wxT( "EXEC " );
647
query = wxT("SELECT");
648
if (!m_targetInfo->getIsFunction())
649
query = wxT("EXEC ");
650
else if (m_targetInfo->getLanguage() == wxT("edbspl"))
651
query = wxT("PERFORM ");
654
// If this is a function, and the return type is not record, or
655
// we have at least one OUT/INOUT param, we should select from
656
// the function to get a full resultset.
657
if (m_targetInfo->getIsFunction() && m_targetInfo->getLanguage() != wxT("edbspl") &&
658
(m_targetInfo->getReturnType() != wxT("record") ||
659
m_targetInfo->getArgInOutCount() > 0 ||
660
m_targetInfo->getArgOutCount() > 0))
661
query.Append(wxT("* FROM "));
663
// Stuff the verb (SELECT or EXEC), schema, and target name into the query
664
query.Append(m_targetInfo->getFQName());
666
// Now append the argument list
667
query.Append(wxT("("));
669
for(int i = 0; i < m_targetInfo->getArgCount(); ++i)
671
wsArgInfo & arg = (*m_targetInfo)[i];
673
if(arg.getMode() == wxT("o") && !m_conn->EdbMinimumVersion(8, 4))
675
if (!m_targetInfo->getIsFunction() || m_targetInfo->getLanguage() == wxT("edbspl"))
676
query.Append( wxT("NULL::") + arg.getType() + wxT(", "));
678
else if (m_conn->EdbMinimumVersion(8, 4) && (arg.getMode() == wxT("o") || arg.getMode() == wxT("b")))
680
if (!m_targetInfo->getIsFunction() || m_targetInfo->getLanguage() == wxT("edbspl"))
682
wxString strParam = wxString::Format(wxT("param%d"), i);
683
declareStatement += strParam + wxT(" ") + arg.getType();
684
if (arg.getMode() == wxT("b"))
685
declareStatement += wxT(" := ") + arg.quoteValue() + wxT("::") + arg.getType();
686
declareStatement += wxT(";\n");
687
query.Append(strParam + wxT(", "));
689
else if (arg.getMode() != wxT("o"))
690
query.Append( arg.quoteValue() + wxT("::") + arg.getType() + wxT(", "));
692
else if(arg.getMode() == wxT("v"))
693
query.Append( arg.getValue() + wxT(", "));
695
query.Append( arg.quoteValue() + wxT("::") + arg.getType() + wxT(", "));
698
if (query.EndsWith(wxT(", ")))
699
query = query.Left(query.Length() - 2);
700
else if (query.EndsWith(wxT("(")))
701
query = query.Left(query.Length() - 1);
703
// And terminate the argument list
704
if(m_targetInfo->getArgInCount() + m_targetInfo->getArgInOutCount() == 0)
707
* edbspl function/procedure with OUT parameter takes value/variable as an input
709
if (m_conn->GetIsEdb())
711
if (m_targetInfo->getArgCount() == 0)
713
if (m_targetInfo->getIsFunction() || m_targetInfo->getLanguage() != wxT("edbspl"))
714
query.Append(wxT("()"));
716
else if (m_targetInfo->getLanguage() != wxT("edbspl"))
717
query.Append(wxT("()"));
719
query.Append(wxT(")"));
721
else if (m_targetInfo->getIsFunction())
722
query.Append(wxT("()"));
726
query.Append(wxT(")"));
729
if (m_conn->EdbMinimumVersion(8, 4) && (m_targetInfo->getLanguage() == wxT("edbspl") || !m_targetInfo->getIsFunction()))
731
wxString tmpQuery = wxT("DECLARE\n")
739
// And send the completed command to the server - we'll get
740
// a dbgDbResult event when the command completes (and that
741
// event will get routed to dlgDirectDbg::OnResultReady())
742
m_conn->startCommand( query, GetEventHandler(), RESULT_ID_DIRECT_TARGET_COMPLETE );
652
wxString query, declareStatement;
653
if (!m_conn->EdbMinimumVersion(8, 4))
654
query = m_targetInfo->getIsFunction() ? wxT( "SELECT " ) : wxT( "EXEC " );
657
query = wxT("SELECT");
658
if (!m_targetInfo->getIsFunction())
659
query = wxT("EXEC ");
660
else if (m_targetInfo->getLanguage() == wxT("edbspl"))
661
query = wxT("PERFORM ");
664
// If this is a function, and the return type is not record, or
665
// we have at least one OUT/INOUT param, we should select from
666
// the function to get a full resultset.
667
if (m_targetInfo->getIsFunction() && m_targetInfo->getLanguage() != wxT("edbspl") &&
668
(m_targetInfo->getReturnType() != wxT("record") ||
669
m_targetInfo->getArgInOutCount() > 0 ||
670
m_targetInfo->getArgOutCount() > 0))
671
query.Append(wxT("* FROM "));
673
// Stuff the verb (SELECT or EXEC), schema, and target name into the query
674
query.Append(m_targetInfo->getFQName());
676
// Now append the argument list
677
query.Append(wxT("("));
679
for(int i = 0; i < m_targetInfo->getArgCount(); ++i)
681
wsArgInfo &arg = (*m_targetInfo)[i];
683
if(arg.getMode() == wxT("o") && !m_conn->EdbMinimumVersion(8, 4))
685
if (!m_targetInfo->getIsFunction() || m_targetInfo->getLanguage() == wxT("edbspl"))
686
query.Append( wxT("NULL::") + arg.getType() + wxT(", "));
688
else if (m_conn->EdbMinimumVersion(8, 4) && (arg.getMode() == wxT("o") || arg.getMode() == wxT("b")))
690
if (!m_targetInfo->getIsFunction() || m_targetInfo->getLanguage() == wxT("edbspl"))
692
wxString strParam = wxString::Format(wxT("param%d"), i);
693
declareStatement += strParam + wxT(" ") + arg.getType();
694
if (arg.getMode() == wxT("b"))
696
declareStatement += wxT(" := ") + arg.quoteValue();
697
if (!arg.quoteValue().Contains(wxT("::")))
698
declareStatement += wxT("::") + arg.getType();
700
declareStatement += wxT(";\n");
701
query.Append(strParam + wxT(", "));
703
else if (arg.getMode() != wxT("o"))
705
if (!arg.quoteValue().Contains(wxT("::")))
706
query.Append( arg.quoteValue() + wxT("::") + arg.getType() + wxT(", "));
708
query.Append( arg.quoteValue() + wxT(", "));
711
else if(arg.getMode() == wxT("v"))
712
query.Append( arg.getValue() + wxT(", "));
715
if (!arg.quoteValue().Contains(wxT("::")))
716
query.Append( arg.quoteValue() + wxT("::") + arg.getType() + wxT(", "));
718
query.Append( arg.quoteValue() + wxT(", "));
722
if (query.EndsWith(wxT(", ")))
723
query = query.Left(query.Length() - 2);
724
else if (query.EndsWith(wxT("(")))
725
query = query.Left(query.Length() - 1);
727
// And terminate the argument list
728
if(m_targetInfo->getArgInCount() + m_targetInfo->getArgInOutCount() == 0)
731
* edbspl function/procedure with OUT parameter takes value/variable as an input
733
if (m_conn->GetIsEdb())
735
if (m_targetInfo->getArgCount() == 0)
737
if (m_targetInfo->getIsFunction() || m_targetInfo->getLanguage() != wxT("edbspl"))
738
query.Append(wxT("()"));
740
else if (m_targetInfo->getLanguage() != wxT("edbspl"))
741
query.Append(wxT("()"));
743
query.Append(wxT(")"));
745
else if (m_targetInfo->getIsFunction())
746
query.Append(wxT("()"));
750
query.Append(wxT(")"));
753
if (m_conn->EdbMinimumVersion(8, 4) && (m_targetInfo->getLanguage() == wxT("edbspl") || !m_targetInfo->getIsFunction()))
755
wxString tmpQuery = wxT("DECLARE\n")
763
// And send the completed command to the server - we'll get
764
// a dbgDbResult event when the command completes (and that
765
// event will get routed to dlgDirectDbg::OnResultReady())
766
m_conn->startCommand( query, GetEventHandler(), RESULT_ID_DIRECT_TARGET_COMPLETE );
756
780
// We should really display the complete result set somewhere too.
758
void dlgDirectDbg::OnTargetComplete( wxCommandEvent & event )
782
void dlgDirectDbg::OnTargetComplete( wxCommandEvent &event )
760
// Extract the result set handle from the event and log the status info
762
PGresult * result = (PGresult *)event.GetClientData();
764
wxLogInfo( wxT( "OnTargetComplete() called\n" ));
765
wxLogInfo( wxT( "%s\n" ), wxString(PQresStatus( PQresultStatus( result )), wxConvUTF8).c_str());
767
// If the query failed, write the error message to the status line, otherwise, copy the result set into the grid
768
if(( PQresultStatus( result ) == PGRES_NONFATAL_ERROR ) || ( PQresultStatus( result ) == PGRES_FATAL_ERROR ))
770
wxString message( PQresultErrorMessage( result ), wxConvUTF8 );
772
message.Replace( wxT( "\n" ), wxT( " " ));
774
m_parent->getStatusBar()->SetStatusText( message, 1 );
775
char *state = PQresultErrorField(result,PG_DIAG_SQLSTATE);
777
// Don't bother telling the user that he aborted - he already knows!
778
if (state != NULL && strcmp(state, "57014"))
779
wxLogError( wxT( "%s\n" ), wxString(PQerrorMessage(m_conn->getConnection()), wxConvUTF8).c_str());
781
wxLogInfo( wxT( "%s\n" ), wxString(PQerrorMessage(m_conn->getConnection()), wxConvUTF8).c_str());
785
wxString message( PQcmdStatus( result ), wxConvUTF8 );
787
message.Replace( wxT( "\r" ), wxT( "" ));
788
message.Replace( wxT( "\n" ), wxT( " " ));
790
m_parent->getStatusBar()->SetStatusText( message, 1 );
792
// If this result set has any columns, add a result grid to the code window so
793
// we can show the results to the user
795
if( m_codeWindow && PQnfields( result ))
797
m_codeWindow->OnResultSet( result );
803
m_codeWindow->m_targetComplete = true;
804
m_codeWindow->disableTools( );
807
// Do not show if aborted
808
if ( m_codeWindow && m_codeWindow->m_targetAborted )
784
// Extract the result set handle from the event and log the status info
786
PGresult *result = (PGresult *)event.GetClientData();
788
wxLogInfo( wxT( "OnTargetComplete() called\n" ));
789
wxLogInfo( wxT( "%s\n" ), wxString(PQresStatus( PQresultStatus( result )), wxConvUTF8).c_str());
791
// If the query failed, write the error message to the status line, otherwise, copy the result set into the grid
792
if(( PQresultStatus( result ) == PGRES_NONFATAL_ERROR ) || ( PQresultStatus( result ) == PGRES_FATAL_ERROR ))
794
wxString message( PQresultErrorMessage( result ), wxConvUTF8 );
796
message.Replace( wxT( "\n" ), wxT( " " ));
798
m_parent->getStatusBar()->SetStatusText( message, 1 );
799
char *state = PQresultErrorField(result, PG_DIAG_SQLSTATE);
801
// Don't bother telling the user that he aborted - he already knows!
802
// Depending on the stage, m_conn might not be set all! so check for
806
if (state != NULL && strcmp(state, "57014"))
807
wxLogError( wxT( "%s\n" ), wxString(PQerrorMessage(m_conn->getConnection()), wxConvUTF8).c_str());
809
wxLogInfo( wxT( "%s\n" ), wxString(PQerrorMessage(m_conn->getConnection()), wxConvUTF8).c_str());
814
wxString message( PQcmdStatus( result ), wxConvUTF8 );
816
message.Replace( wxT( "\r" ), wxT( "" ));
817
message.Replace( wxT( "\n" ), wxT( " " ));
819
m_parent->getStatusBar()->SetStatusText( message, 1 );
821
// If this result set has any columns, add a result grid to the code window so
822
// we can show the results to the user
824
if( m_codeWindow && PQnfields( result ))
826
m_codeWindow->OnResultSet( result );
832
m_codeWindow->m_targetComplete = true;
833
m_codeWindow->disableTools( );
836
// Do not show if aborted
837
if ( m_codeWindow && m_codeWindow->m_targetAborted )
814
843
////////////////////////////////////////////////////////////////////////////////