I have defined a new command my_command in PostgreSQL. This command takes the path of ANALYZE and inside analyze.c, I have a function to do some operations if its my_command.This command takes the input arguments: table name, column name and an input string.
When I run this command from command line psql, it works as expected. But when I call the same command from a java application, all the variables that store the input arguments are NULL.
I printed the value of the input string in gram.y file where I have defined my_command.
fprintf (stderr, "I am inside gram.y %s\n",n->inp_str);
and the input string is printed correctly.
But when I print stmt->inp_str in the function standard_ProcessUtility() of utility.c for the case T_VacuumStmt, I get the value as NULL. This is as far as I could trace back from analyze.c.
I am not sure how running the command from an application can make a difference.
gram.y content gist:
MyStmt:
my_keyword qualified_name name_list my_inp_str
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_ANALYZE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
n->relation = $2;
n->va_cols = $3;
n->inp_str = $4;
fprintf (stderr, "I am inside gram.y %s\n",n->inp_str);
$$ = (Node *)n;
}
;
char *inp_str is added to the struct VacuumStmt in parsenodes.h
Any help is appreciated. Thanks!
I had mailed this question to the pgsql-hackers mailing list and I got a response that I had to add code to copy inp_str to _copyVacuumStmt().
Once this was done, the command worked from the Java application too. I have asked for the reason why it worked from command line even without adding the above code. I will update the details once I get the details.
Related
I have an issue with trying to check if a file exists and reading it if it exists.
My code:
use std::{env, fs};
use std::fs::{File, read};
use std::path::Path;
use std::process::exit;
let arg = env::args().next().expect("Please open a file via the command line!");
let path = Path::new(
&arg
);
if !path.exists() {
error!("The specified path does not exist!");
exit(101);
}
let file = read(path).expect("Could not read file!");
let content = String::from_utf8(file).expect("The file does not contain valid characters!");
Run the program like this ./program.exe a_vali_file_path.txt
Expectation:
If you run the program with a valid file path as the first argument, the program will check if it exists. If it does, the program reads the file content and just returns.
What actually happened:
The program doesn't even really check for the file (it does not panic, even if the path is not valid) and if it tries to read it prints a bunch of bytes into the console followed by the error
error: Utf8Error { valid_up_to: 2, error_len: Some(1) } }.
This behavior occurs if the file exists or not.
env::args.next() references the executable, which doesn't contain UTF-8 bytes. If you want to point to the next argument you must use another .next() call, or better yet use a Vector to store your args.
Example of a vector being used to store args ->
fn main() {
let args: Vec<String> = env::args().collect()
...
}
To solve it your way:
fn main() {
let args = env::args()
args.next() //Points to executable (argv[0])
args.next() //Points to file (argv[1])
}
As you can see the second solution is not very elegant, but hey, to each their own.
Let's say for simplicities sake I have a file (please forgive my useless pseudo code)
file.txt
std::string filename = "filename.txt"
double v_no = 2.0;
const int v_minor = 0; // < --- Target
std::string random_var1 = "Hello"
std::string random_var2 = "Hello 2"
int main()
{
// ..
}
And I have a bash file in the same directory - set_version.sh
I want to replace a string in this file with this script - specifically "v_minor = 0" with "v_minor = $VARIABLE" - in my case the variable will be an environmental set on a server.
So lets say it has been successfully run a couple of times. Now the string reads "v_minor = 2". I still want the same set_version.sh script to change 2 to whatever the variable is.
In the windows build of my software I have a batch file that changes "v_minor = %d" to "v_minor = %VERSION%".
My question is how I do something similar in bash? E.g. ignoring what the decimal is in the string and changing it to variable.
What I've got so far:
set_version.sh
#!/bin/bash
VERSION=75
sed -i '' 's/v_minor = %d/v_minor = $VERSION/g/' file.txt
Version var being set is just for testing purposes.
This returns error
sed: 1: "s/v_minor = %d/v_minor ...": bad flag in substitute command: '/'
I'm running Mac OS X Yosemite for this test.
Again, essentially %d can be any integer.
Thank you
That will work for you:
sed -i '' "s/v_minor = .*$/v_minor = $VERSION/g" file.txt
.*$ means till the end of that string.
Don't forget to use " " when operating with variables.
sed -i '' 's/v_minor = %d/v_minor = $VERSION/g/' file.txt
# ^
# /
# remove this slash ---
According to your description, I would suggest another easier way as follows (and simplicity will make less bugs...):
First, Change your target to
const int v_minor = V_MINOR; // < --- Target
Second, add an include line, anywhere before the target statement:
#include "version.h"
Third, write a script to generate the version.h similar to the followings:
#ifndef _VERSION_H_
#define V_MINOR 0 // <== this 0 is what you want to change.
#endif
Generate a script to output the said version.h is too simple (Just some fixed prints plus the target number). Thus, I don't provide it here.
Comparing to those possible error-prone sed-awk-perl solution, I prefer this simple solution.
I have a huge code file and want to insert print code in every function.
I know debugging is one option but I am new to Kernel and kgdb is not an easy and immediate option hence I want to use printf temporarily.
I used vim's multiple buffers to do this task faster, but want to know if there is any way to automate it in .vimrc
Here is what the final code must look like
void foo(int a, int b) {
printf("Some print");
// ...
}
int bar() {
printf("Some print");
// ...
}
void bleh(int b) {
printf("Some print");
// ...
}
one quick way to do it is in the shell:
find -name '*.c' | xargs vim
In vim, you start recording with qq a macro, make use of the global command
:g/\v\s*(void|int) \w+\([^)]*\)/normal A^Mprint("some print");
And then you use the wonderful argdo command:
:argdo normal #q
To save the changes you use:
:argdo normal :w^M
That will add print("someprint") to every function on the located c source code files. If you want to use the function name or the file name in the print statement, you can use the global command with a little complex substitution like (not tested):
:global /\v\s*(void|int) \w+([^)]*)/s/\v(\w+)\([^]]*\)\s* {/\=submatch(0) . '\r\t\tprint(in file.function:'. expand('%') .'.'. submatch(1) . ');'
Remember that ^M and ^[ are not literal strings, they are inserted with <C-v><CR> and <C-v><Esc>
Hope this help
I'm attempting to write a function that will pull text from different sources (Ethernet client/Serial/etc.) into a single line, then compare them and run other functions based on them. Simple..
And while this works, I am having issues when trying to call a simple Serial.println() from a function OTHER than loop().
So far, I have around 140 lines of code, but here's a trimmed down version of the portion that's causing me problems:
boolean fileTerm;
setup() {
fileTerm = false;
}
loop() {
char character;
String content="";
while (Serial.available()) {
character = Serial.read();
content.concat(character);
delay(1);
}
if (content != "") {
Serial.println("> " + content);
/** Error from Serial command string.
* 0 = No error
* 1 = Invalid command
*/
int err = testInput(content);
}
int testInput(String content) {
if (content == "term") {
fileTerm = true;
Serial.println("Starting Terminal Mode");
return 0;
}
if (content == "exit" && fileTerm == true) {
fileTerm = false;
Serial.println("Exiting Terminal Mode");
return 0;
}
return 1;
}
(full source at http://pastebin.com/prEuBaRJ)
So the point is to catch the "term" command and enter some sort of filesystem terminal mode (eventually to access and manipulate files on the SD card). The "exit" command will leave the terminal mode.
However, whenever I actually compile and type these commands with others into the Serial monitor, I see:
> hello
> term
> test for index.html
> exit
> test
> foo
> etc...
I figure the function is catching those reserved terms and actually processing them properly, but for whatever reason, is not sending the desired responses over the Serial bus.
Just for the sake of proper syntax, I am also declaring the testInput() function in a separate header, though I would doubt this has any bearing on whether or not this particular error would occur.
Any explainable reason for this?
Thanks.
Model: Arduino Uno R3, IDE version: 1.0.4, though this behavior also happened on v1.0.5 in some instances..
It is kinda guessable how you ended up putting delay(1) in your code, that was a workaround for a bug in your code. But you didn't solve it properly. What you probably saw was that your code was too eager to process the command, before you were done typing it. So you slowed it down.
But that wasn't the right fix, what you really want to do is wait for the entire command to be typed. Until you press the Enter key on your keyboard.
Which is the bug in your code right now, the content variable doesn't just contain "term", it also contains the character that was generated by your terminal's Enter key. Which is why you don't get a match.
So fix your code, add a test to check that you got the Enter key character. And then process the command.
I come up with this code. It will execute correctly and return true. but it doesn't change Path variable's value. When I type like this --> setx Path "C:\Program Files\Java\jdk1.7.0_02\bin\"
in cmd, it works and change the Path value
here is the code
// Prepare shellExecutInfo
SHELLEXECUTEINFO ShRun = {0};
ShRun.cbSize = sizeof(SHELLEXECUTEINFO);
ShRun.fMask = SEE_MASK_NOCLOSEPROCESS;
ShRun.hwnd = NULL;
ShRun.lpVerb =NULL;
ShRun.lpFile = "C:\\Windows\\System32\\setx.exe";
ShRun.lpParameters = "Path \"\"\"C:\\Program Files\\Java\\jdk1.7.0_02\\bin\\\"\"\"";
ShRun.lpDirectory =NULL;
ShRun.nShow = SW_SHOWNORMAL;
ShRun.hInstApp = NULL;
// Execute the file with the parameters
if(ShellExecuteEx(&ShRun))
printf("done");
else
printf("no");
what will be the problem here??
Your quoting on the arguments is wrong. You have too many quotes. You need to write
ShRun.lpParameters = "Path \"C:\\Program Files\\Java\\jdk1.7.0_02\\bin\\\"";
To see that your version will fail I did the following experiment at the console:
C:\Users\heff>setx path """C:\Program Files\Java\jdk1.7.0_02\bin\"""
ERROR: Invalid syntax. Default option is not allowed more than '2' time(s).
Type "SETX /?" for usage.
I also note that you are using SEE_MASK_NOCLOSEPROCESS. Normally you do that so that you can then wait on the process handle that is returned. You don't appear to be doing that. What's more, you don't appear to be closing the process handle which is your responsibility when you use SEE_MASK_NOCLOSEPROCESS.