MUMPS $Functions in SQL Statements - intersystems-cache

Can $Functions like $Extract, $P be used in SQL statements? If they can, please provide and example. Ex Select $P(Field1,"*") from MyTable.
This returns an error saying "A term expected beginning with either..."

If your question is can I use some of the standard $ functions in CacheSQL the answer is yes. The following $ functions are available in CacheSQL
SQL functions: $EXTRACT $FIND $LENGTH $LIST
I suspect your issue is the usage of " characters.
If you did
SELECT $PIECE(Name,',',1) AS LastName,
$PIECE(Name,',',2) AS FirstName
FROM Sample.Person
you should get results.

MUMPS itself does not have any support of SQL, but in Caché it is possible to use some of system functions. But in SQL you should use full name for such functions, so $p is not available for use. All list of available functions you can find in the documentation here.

Related

VFP macro expansion in USE statement

A table is being opened in a folder whose name is being provided by the user.
lFolder = Getfile()
lFilename = lFolder + “mytable.dbf”
USE &lFilename IN 0 ALIAS . . .
This usually works fine. However, if the folder whose name is supplied by the user has an embedded space, so ‘My folder’, the USE instruction fails. But this instruction works successfully :
USE (lFilename) IN 0 . . .
Are there any rules which say when one should use the Ampersand (&) construct and when one should use the bracket construct? And is this only applicable to the USE statement?
Thanks. Andrew
The proper way to write that code is:
local lFolder, lFilename
lFolder = Getdir()
lFilename = addbs(m.lFolder) + 'mytable.dbf'
* or a single GetFile() to select the dbf directly
USE (m.lFilename) IN 0 ALIAS . . .
There are more than one point in this code:
1) Declare your variables as local. Without that declaration, it would work and VFP would implicitly declare them as private. It is a good practice to declare local and also would help with intellisense, if you use tools like ISX.
2) Using addbs() ensures a backslash. It is just coding safe.
3) Use m. (aka mdot) for memory variables. Using mdot, you are telling VFP explicitly that it is a memory variable. Using mdot there is no harm, but if you don't you might get into hard to catch bugs (and also in tight loops, it is proven to be much faster using mdot).
4) Finally, your original question. A Filename is a "name" so do not use a macro expansion (&) operator but "name expression" anywhere there is a Name. A "name expression" is simply a set of parentheses. If something is a "name", then use "name expression" (a fieldName, fileName, folderName, variableName ...).
Apart from rules, unfortunately many VFP developers abuse the & and use it too often. In reality, probably it has too few places where using makes sense and that is SQL clauses. Not something like:
lcSQL = "select * from ..." + ... + "..."
&lcSQL
(which often you may see this pattern as well) but this one where parts of SQL use macro expansion. ie:
select &fieldList ;
from (m.tableName) ;
where &lcWhere ;
order by &lcOrder
Note that m.tableName is a "name" and thus used with "name expression". FieldList variable might be holding a single fieldName or a series of fieldNames (ie: "CustomerId" or "CustomerId, CompanyName, ContactName") and cannot be used as a "name expression", needs to be macro expanded.

Retrieving String with single quotes from database and storing in Perl

I have a SQL query
select name from Employee
Output :
Sharma's
How can I store this output in perl string.
I tried below :
$sql =qq {select Name from Employee};
$Arr = &DataBaseQuery( $dbHandle, $sql );
$name = $Arr;
But when I print $name I get output as
Sharma::s
How can I store the single quote in the $name.
First of all, non of standard DBI/DBD exibits behavior you listed, in my experience.
Without knowing details of what DataBaseQuery() does it's impossible to answer conclusively, but a plausible theory can be formed:
Apostrophe is a valid package separator in Perl, equivalent to "::".
Reference: perldoc perlmod
The old package delimiter was a single quote, but double colon is now the preferred delimiter, in part because it's more readable to humans, and in part because it's more readable to emacs macros. It also makes C++ programmers feel like they know what's going on--as opposed to using the single quote as separator, which was there to make Ada programmers feel like they knew what was going on. Because the old-fashioned syntax is still supported for backwards compatibility, if you try to use a string like "This is $owner's house" , you'll be accessing $owner::s ; that is, the $s variable in package owner , which is probably not what you meant. Use braces to disambiguate, as in "This is ${owner}'s house" .
perl -e 'package A::B; $A::B=1; 1;
package main;
print "double-colon: $A::B\n";
print "apostrophe: $A'"'"'B\n";'
double-colon: 1
apostrophe: 1
I have a strong suspicion something within your own libraries inside DataBaseQuery() call was written to be "smart" and to convert apostrophes to double-colons because of this.
If you can't figure out root cause, you can always do one of the following:
Write your own DB wrapper
Assuming your text isn't likely to contain "::", run a regex to fix s#::#'#g; on all results from DataBaseQuery() (likely, in a function serving as a wrapper-replacement for DataBaseQuery())

Postgres / SQL::Abstract "Not In Range" Operation

Postgres has some cool range operators for handling ranges:
http://www.postgresql.org/docs/devel/static/functions-range.html
...but doesn't appear to have anything to handle 'not' being in a range. For instance, the #> operator means 'contains element' or 'contains range'. But equally helpful would be the !#> operator, which doesn't seem to exist.
If I'm trying to say "query where date is not in range", is there any solution other than using a conditional expression? I'm using SQL::Abstract, which doesn't support expressions without using literal SQL, which I would like to avoid.
I do it this way
FALSE = INT4RANGE(1,5) #> 5
I would recommend using NOT BETWEEN date AND date.
Sorry, you may still end up using a SQL literal.

Same piped call to isql works on Solaris but not on RHEL

Background: I need to port a ksh script from SunOS 5.10 to RHEL 5.8. It makes a call to isql to retrieve some data and, quite contrary to the intended application of final endpoint client utilities such as isql, it parses its out to be used by a variable in the shell script. Please note that I just inherited this and by no means did design such a hack myself. I certainly never would be parsing isql out to assign value to a var in shell -- if the script needed that info, I would use Perl with some API like DBD::DBI that is designed to marshall data between the application and the data store. But I have what I have and must work within the parameters.
What is happening is that the following piped input does return data on SunOS but not in RHEL:
echo "SELECT some_field FROM some_table WHERE some_crtra = 'X' \ngo" | isql -U$USER -P$PASS -D$DB -S$SERVER
That output on Solaris being:
some_field
------
Y
(1 row affected)
From that point, the script uses awk to extract just the field value from the above stream but let's ignore that because that's not the problem.
Also please note that I am able to get the data executing the piped commands separately, i.e. by going manually into isql and running the SQL. So the SQL or the connection string are not the problem -- it is either how the piping streams data OR isql itself works differently on the different platforms.
Can anybody see why there is disparate response to the same input on the two systems? Any idea how I can change the piping to make it work?
Thanks
echo "SELECT some_field FROM some_table WHERE some_crtra = 'X' \ngo"
is non portable.
I would suggest instead:
printf "SELECT some_field FROM some_table WHERE some_crtra = 'X' \ngo\n"
From the ksh93 manual page:
When the first arg does not begin with a -, and none of the
arguments contain a \, then echo prints each of its arguments
separated by a space and terminated by a new-line. Otherwise,
the behavior of echo is system dependent and print or printf
described below should be used. See echo(1) for usage and
description.

Escaping & in perl DB queries

I need to manipulate some records in a DB and write their values to another table. Some of these values have an '&' in the string, i.e. 'Me & You'. Short of finding all of these values and placing a \ before any &'s, how can insert these values into a table w/o oracle choking on the &?
Use placeholders. Instead of putting '$who' in your SQL statement, prepare with a ? there instead, and then either bind $who, or execute with $who as the appropriate argument.
my $sth = $dbh->prepare_cached('INSERT INTO FOO (WHO) VALUES (?)');
$sth->bind_param(1, $who);
my $rc = $sth->execute();
This is safer and faster than trying to do it yourself. (There is a "quote" method in DBI, but this is better than that.)
This is definitely a wheel you don't need to reinvent. If you are using DBI, don't escape the input; use placeholders.
Example:
my $string = "database 'text' with &special& %characters%";
my $sth = $dbh->prepare("UPDATE some_table SET some_column=?
WHERE some_other_column=42");
$sth->execute($string);
The DBD::Oracle module (and all the other DBD::xxxxx modules) have undergone extensive testing and real world use. Let it worry about how to get your text inserted into the database.