Update a column name that starts with a number in a dbf-file with oledb - oledb

I'm trying to update a column named value in a dbf-file. Since value is a reserved word I need to add the tablename to the query. So this works:
UPDATE "C:\TEMP\TEST_PARAM.DBF" SET TEST_PARAM.value='new value' WHERE Id='Some ID';
But now I have the problem that many of my dbf-files start with numbers in the filenames and following does not work:
UPDATE "C:\TEMP\0016_PARAM.DBF" SET 0016_PARAM.value='new value' WHERE Id='Some ID';
I've tried enclosing the table_name in single quotes, double quotes, [,... but nothing of that works. Is there something else I could try?

You don't say what language you're doing this in, but here we go in C#. The same approach should work in any language.
You need to open the DBF under an alias, and you need to be able to send multiple commands through OLEDB.
This should work.
* -- Open the dbf in the first available work area under the alias 'param'.
* -- Now you don't have to worry about the zeroes.
OleDbCommand myCommand = new OleDbCommand(#"execscript([use 'C:\TEMP\0016_PARAM.DBF' in 0 alias param])", myConnection);
var result = myExecuteNonQuery();
* -- Now do the update, referring to the alias, not the DBF filename.
myCommand = new OleDbCommand(#"execscript([update param set param.value='new' where id='some id'])", myConnection);
result = myCommand.ExecuteNonQuery();
Regarding the square brackets, Visual FoxPro has three default string delimiters, namely the usual single and double quotes, but also square brackets.
So we're using the double quotes for the C# string. The Visual Foxpro command we're running via ExecScript needs quotes too, around 'new' and 'some id', so that's using single quotes. But we need to pass that command to Execscript as a string, so that string is using the brackets.

Related

BBEdit: how to write a replacement pattern when a back reference is immediately followed by a number

I'm new to GREP in BBEdit. I need to find a string inside an XML file. Such string is enclosed in quotes. I need to replace only what's inside the quotes.
The problem is that the replacement string starts with a number thus confuses BBEdit when I put together the replacement pattern. Example:
Original string in XML looks like this:
What I need to replace it with:
01 new file name.png
My grep search and replace patterns:
Using the replacement pattern above, BBEdit wrongly thinks that the first backreference is "\101" when what I really need it understand is that I mean "\01".
TIA for any help.
Your example is highly artificial because in fact there is no need for your \1 or \3 as you know their value: it is " and you can just type that directly to get the desired result.
"01 new file name.png"
However, just for the sake of completeness, the answer to your actual question (how to write a replacement group number followed by a number) is that you write this:
\0101 new file name.png\3
The reason that works is that there can only be 99 capture groups, so \0101 is parsed as \01 (the first capture group) followed by literal 01.

Lua heredoc with variable interpolation?

Is there a way to use a heredoc type of notation in Lua that references variables within the string?
The basic idea of what I'm trying to do would look something like follows. The heredoc piece is fine, but within Lua you can't actually reference the variable in the manner I'm showing below.
username = "bigtunacan"
sql=[=[
SELECT * FROM users WHERE username='$bigtunacan';
]=]
There's no built-in string interpolation, but it can be trivially implemented with gsub and replacement table.
sql=[=[
SELECT * FROM users WHERE username='$username';
]=]
print((sql:gsub('$(%w+)', { username = 'bigtucan' })))
-- SELECT * FROM users WHERE username='bigtucan';
Note an extra set of () - this is so only first return - the interpolated string is used from gsub and the 2nd - number of replacements made - silently discarded. This might be important if you use result of gsub as last in list of arguments to some function where adding one more argument might produce different behavior.
Also if you want to use this in SQL context, you really should use placeholders instead.
There is no Lua construct that allows variable interpolation within any string. See Literal Strings in the official reference guide.
You could of course write a function that would parse it and do the substitutions.

String queries in BreezeJS that contain single or double quotes return error

I have a text input for a search field where the string is then passed to an EntityQuery. When ever the query includes a single quote I get a message like the following:
There is an unterminated string literal at position 39 in 'substringof(O'Malley,FirstName) eq true'.
It even happens when just hard coding the query like this:
var query = breeze.EntityQuery
.from("Users")
.expand("GroupUsers.Group")
.where("lastName", "contains","O'Malley")
.skip(skipAmt)
.take(pageSize)
.inlineCount(true);
I've tried escaping the single quote by doing double single quotes or doing \' and it still comes back with an error. This also happens similarly with double quotes. What is the proper way to escape the string literal characters?
I can't repro this. You should be able to escape a single ' by simply doubling it. For example, the following query works without a problem on v 1.2.8.
var q = EntityQuery.from("Employees")
.where("lastName", "contains", "O''Malley");
Does the problem still occur if you 'simplify' the query down to just the where 'clause'?

Create virtualedit block around selection

I'm trying to create a script what permits me to select a few lines and create a virtualedit block around it; 1 column after the longest line.
This is my code
function! VirtualEdit()
let EndLine = line("'>")
set virtualedit = all
let maxlength = max(map(range(line("'<"), line("'>")), "virtcol([v:val, '$'])"))-1
call cursor(1,maxlength+1)
normal "^Q".EndLine."jc<space><ESC>"
set virtualedit = ''
endfunction
What it must do is
1) Control the longest line in my selection (maxlength).
2) Put the cursor on the first line in the selection at the column of the longest line +1 column.
3) Than Activate Visual Block selection (on my windows pc the command is C-Q)
4) Extend the visual block till the last line in the selection (the command on my pc for moving down = "j").
5) Than use the "c" key to insert a "space" character and ESC to exit the insert mode in order to fill the virtual block column with spaces.
However I can't find out how to use a variable (Endline) in a normal command.
I noted also that keys as and don't work in my above example.
What did I wrong?
You have many errors here:
:set does not let you have spaces around =
:set does not accept expressions, thus set ve='' is let &ve="''", not let &ve='' which is :set ve=.
:normal command also does not accept expressions, it accepts strings that are just executed. Thus :normal "^ is trying to use register ^, fails (no such register) and stops processing the rest of the line. Use :execute to pass expressions to :normal.
:normal command does not accept <Key> syntax. Neither do viml expressions, they have "\<Key>" instead (note: only double quotes and with backslash). ^Q syntax is not accepted by anybody and having raw control codes (displayed by vim as ^Q) inside a text file is not the best idea.
Don’t use :normal without a bang. Most of time you don’t need it (you need to replace ^Q with \<C-v> in this case though because it is a mapping).
Don’t hardcode virtualedit value. Instead of
set ve=all
<...>
set ve=
use
let savedve=&ve
set ve=all
try
<...>
finally
let &ve=savedve
endtry
{N}j means “N lines down”, not “go to N’th line”. “Go to N’th line” is {N}gg or {N}G.
You have let maxlen=<...>-1 and the on only line where maxlen is used you have maxlen+1. It is strange.
If you fix this you can proceed, but you don’t need adjusting virtualedit and using :normal at all:
function AddSpaces()
let [lstart, lend]=[line("'<"), line("'>")]
if lstart>lend
let [lstart, lend]=[lend, lstart]
endif
let maxcol=max(map(range(lstart, lend), "virtcol([v:val, '$'])"))
let newlines=map(range(lstart, lend), 'printf("%-'.maxcol.'s", getline(v:val))')
call setline(lstart, newlines)
endfunction

Funny CSV format help

I've been given a large file with a funny CSV format to parse into a database.
The separator character is a semicolon (;). If one of the fields contains a semicolon it is "escaped" by wrapping it in doublequotes, like this ";".
I have been assured that there will never be two adjacent fields with trailing/ leading doublequotes, so this format should technically be ok.
Now, for parsing it in VBScript I was thinking of
Replacing each instance of ";" with a GUID,
Splitting the line into an array by semicolon,
Running back through the array, replacing the GUIDs with ";"
It seems to be the quickest way. Is there a better way? I guess I could use substrings but this method seems to be acceptable...
Your method sounds fine with the caveat that there's absolutely no possibility that your GUID will occur in the text itself.
On approach I've used for this type of data before is to just split on the semi-colons regardless then, if two adjacent fields end and start with a quote, combine them.
For example:
Pax;is;a;good;guy";" so;says;his;wife.
becomes:
0 Pax
1 is
2 a
3 good
4 guy"
5 " so
6 says
7 his
8 wife.
Then, when you discover that fields 4 and 5 end and start (respectively) with a quote, you combine them by replacing the field 4 closing quote with a semicolon and removing the field 5 opening quote (and joining them of course).
0 Pax
1 is
2 a
3 good
4 guy; so
5 says
6 his
7 wife.
In pseudo-code, given:
input: A string, first character is input[0]; last
character is input[length]. Further, assume one dummy
character, input[length+1]. It can be anything except
; and ". This string is one line of the "CSV" file.
length: positive integer, number of characters in input
Do this:
set start = 0
if input[0] = ';':
you have a blank field in the beginning; do whatever with it
set start = 2
endif
for each c between 1 and length:
next iteration unless string[c] = ';'
if input[c-1] ≠ '"' or input[c+1] ≠ '"': // test for escape sequence ";"
found field consting of half-open range [start,c); do whatever
with it. Note that in the case of empty fields, start≥c, leaving
an empty range
set start = c+1
endif
end foreach
Untested, of course. Debugging code like this is always fun….
The special case of input[0] is to make sure we don't ever look at input[-1]. If you can make input[-1] safe, then you can get rid of that special case. You can also put a dummy character in input[0] and then start your data—and your parsing—from input[1].
One option would be to find instances of the regex:
[^"];[^"]
and then break the string apart with substring:
List<string> ret = new List<string>();
Regex r = new Regex(#"[^""];[^""]");
Match m;
while((m = r.Match(line)).Success)
{
ret.Add(line.Substring(0,m.Index + 1);
line = line.Substring(m.Index + 2);
}
(Sorry about the C#, I don't known VBScript)
Using quotes is normal for .csv files. If you have quotes in the field then you may see opening and closing and the embedded quote all strung together two or three in a row.
If you're using SQL Server you could try using T-SQL to handle everything for you.
SELECT * INTO MyTable FROM OPENDATASOURCE('Microsoft.JET.OLEDB.4.0',
'Data Source=F:\MyDirectory;Extended Properties="text;HDR=No"')...
[MyCsvFile#csv]
That will create and populate "MyTable". Read more on this subject here on SO.
I would recommend using RegEx to break up the strings.
Find every ';' that is not a part of
";" and change it to something else
that does not appear in your fields.
Then go through and replace ";" with ;
Now you have your fields with the correct data.
Most importers can swap out separator characters pretty easily.
This is basically your GUID idea. Just make sure the GUID is unique to your file before you start and you will be fine. I tend to start using 'Z'. After enough 'Z's, you will be unique (sometimes as few as 1-3 will do).
Jacob

Resources