Trying to query data where string has a single quote - procedure

Trying to go through a list of values where there might be one with a single quote in it. When I try to pass it through a function, it fails.
It gives the error,
Execution error in store procedure REPORT_PRESENTATION_DATA: SQL compilation error: parse error line 1 at position 164 near '<EOF>'. syntax error line 1 at position 158 unexpected 't'. At Statement.execute, line 90 position 41
I then add
myCommonValue = myCommonValue.replace("'","''");
but now get the error,
JavaScript execution error: Uncaught TypeError: Cannot read property 'replace' of null in REPORT_PRESENTATION_DATA at ' myCommonValue = myCommonValue.replace("'","''");' position 36 stackstrace: REPORT_PRESENTATION_DATA line: 85
Here's a code sample:
CREATE OR REPLACE PROCEDURE MY_SNOWFLAKE_PROCEDURE()
RETURNS VARIANT
LANGUAGE JAVASCRIPT
AS
$$
...
sqlText = ` SELECT fields FROM MYTABLE `;
statement = snowflake.createStatement({ sqlText });
const rs = statement.execute();
let results = [];
while (rs.next()) {
let myColumnValue = rs.getColumnValue(1);
myColumnValue = myColumnValue.replace("'","''");
// Using the column value which could contain a single quote in the string,
// get a second result set. IE: "gov't" may be the string value passed into Query_GroupValues
sqlText = ` SELECT * FROM table(Query_GroupValues('${startdate}', '${enddate}', ARRAY_CONSTRUCT('${myColumnValue}'))) `;
statement = snowflake.createStatement({ sqlText });
const rsTableValue = statement.execute();
if (statement.getRowCount() > 0) {
let myValue = rsTableValue.getColumnValue(1);
struct = {
attributes: {
value: myValue
}
}
results.push(struct);
}
}
...
$$;

Looks like myColumnValue was null when it's replace() method was invoked. Adding a guard should fix it. For Example: if (myColumnValue!=null) myColumnValue = myColumnValue.replace("'","''");

Related

snowflake stored procedure is throwing unexpected Token error

I have written down a procedure by following the snowflake documentation to generate a list of 'SET' statement and execute them in Snowflake. I'm getting Unexpected identifier error while calling the procedure. could somebody please help me out here.
create or replace procedure SET_ENV()
returns string
language JavaScript
as
$$
MASTER_QUERY = {sqlText: SELECT ('SET '||TABLE_NAME||'=
CONCAT($Database_pre,'||'''.'''||',$Schema_pre,'||'''.'''||','''||TABLE_NAME||''');') AS
QUERY
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'
AND( TABLE_NAME NOT LIKE 'TMP_%' AND TABLE_NAME NOT LIKE '%WRK_%')};
STATEMENT = snowflake.createStatement(MASTER_QUERY);
rs = STATEMENT.execute();
var s = '';
while (rs.next()) {
EXECUTION_QUERY = {sqlText: rs.getColumnValue("QUERY")};
stmtEx = snowflake.createStatement(EXECUTION_QUERY);
stmtEx.execute();
s += rs.getColumnValue(1) + "\n";
}
return s;
$$
;
CALL SET_ENV()
The error i'm getting is as follows.
JavaScript compilation error: Uncaught SyntaxError: Unexpected identifier in SET_ENV at 'MASTER_QUERY = {sqlText: 'SELECT ('SET '||TABLE_NAME||'= ' position 35
I'm able to run it after I add backtick (`) characters to enclose the SQL command:
create or replace procedure SET_ENV()
returns string
language JavaScript
execute as CALLER
as
$$
MASTER_QUERY = {sqlText: `SELECT ('SET '||TABLE_NAME||'=
CONCAT($Database_pre,'||'''.'''||',$Schema_pre,'||'''.'''||','''||TABLE_NAME||''');') AS
QUERY
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'
AND( TABLE_NAME NOT LIKE 'TMP_%' AND TABLE_NAME NOT LIKE '%WRK_%')` };
STATEMENT = snowflake.createStatement(MASTER_QUERY);
rs = STATEMENT.execute();
var s = '';
while (rs.next()) {
EXECUTION_QUERY = {sqlText: rs.getColumnValue("QUERY")};
stmtEx = snowflake.createStatement(EXECUTION_QUERY);
stmtEx.execute();
s += rs.getColumnValue(1) + "\n";
}
return s;
$$;
set DATABASE_PRE='DBPRE';
set Schema_pre = 'SCHPRE';
call SET_ENV();
Important: You should also define the procedure as "execute as CALLER" to be able to access session variables. I suggest you define arguments instead of accessing session variables.

How to find the SearchImpressionShare for a particular keyword?

One could easily find the average position for a keyword using getAveragePositon() method but the same is not available for SearchImpressionShare.
EDIT
I tried to get the SearchImpressionShare by querying the data but that gives me inconsistent data.
function main() {
var keywordId = 297285633818;
var last14dayStatsQuery = "SELECT Id, SearchTopImpressionShare FROM KEYWORDS_PERFORMANCE_REPORT WHERE Id = "+keywordId+" DURING LAST_14_DAYS"
var last14dayReport = AdWordsApp.report(last14dayStatsQuery);
var last14dayRows = last14dayReport.rows();
var last14dayRow = last14dayRows.next();
Logger.log('Keyword: ' + last14dayRow['Id'] + ' SearchTopIS: ' + last14dayRow['SearchTopImpressionShare']);
}
For example, below are the two outputs I received after running the same code twice.
Output 1:
10/16/2019 10:47:29 AM Keyword: 297285633818 SearchTopIS: 0.0
Output 2:
10/16/2019 10:47:45 AM Keyword: 297285633818 SearchTopIS: 0.17
Keywords performance report provides you those data https://developers.google.com/adwords/api/docs/appendix/reports/keywords-performance-report#searchimpressionshare
sample use:
function main () {
var query = "SELECT SearchImpressionShare, Criteria FROM KEYWORDS_PERFORMANCE_REPORT WHERE Clicks > 15 DURING YESTERDAY"
var report = AdWordsApp.report(query)
var rows = report.rows()
while (rows.hasNext()) {
var row = rows.next()
Logger.log('Keyrword %s, Impressions Share %s', row['Criteria'], row['SearchImpressionShare'])
}
}
update:
please note that if you have the same keyword within several ad group you'll get aslo several rows in report, each row for each adgroup. for the whole list of keywords use the following approach:
function main() {
var keywordId = 350608245287;
var last14dayStatsQuery = "SELECT Id, SearchTopImpressionShare FROM KEYWORDS_PERFORMANCE_REPORT WHERE Id = "+keywordId+" DURING LAST_14_DAYS"
var last14dayReport = AdWordsApp.report(last14dayStatsQuery);
var last14dayRows = last14dayReport.rows();
while (last14dayRows.hasNext()) {
var last14dayRow = last14dayRows.next();
Logger.log('Keyword: ' + last14dayRow['Id'] + ' SearchTopIS: ' + last14dayRow['SearchTopImpressionShare']);
}
}
You might find it useful to add ad group parameters to your query such as AdGroupName, AdGroupId.

readString is throwing TypeError: malformed UTF-8

This function returns a ctypes.unsigned_char.array() and I do read string on it. It is getting the titles of windows. The problem is sometimes it throws TypeError.
try {
console.error('straight readString on XWindowGetProperty data:', rez_GP.data.readString());
} catch (ex) {
console.error('ex on straight readString:', ex);
}
Please notice the rez_GP.data.readString()
For example this instance: TypeError: malformed UTF-8 character sequence at offset 48. In this situation the window title is Editing js-macosx/bootstrap.js at base-template · Noitidart/js-macosx - Mozilla Firefox The 48th offset is that dot chracter you see, it's chracter code is 183. How to do readString() on this buffer without getting this error?
Thanks
readString expects a utf-8 encoded string. This is true for strings returned by _NET_WM_NAME, but not for WM_NAME.
I found a way to read the string propertly even ifs not utf-8, but im not sure if its he best way or the recommended way. This works though, i have to cast it to unsigned_char (must be this, so not char or jschar) then do fromCharCode:
function readAsChar8ThenAsChar16(stringPtr, known_len, jschar) {
// when reading as jschar it assumes max length of 500
// stringPtr is either char or jschar, if you know its jschar for sure, pass 2nd arg as true
// if known_len is passed, then assumption is not made, at the known_len position in array we will see a null char
// i tried getting known_len from stringPtr but its not possible, it has be known, i tried this:
//"stringPtr.contents.toString()" "95"
//"stringPtr.toString()" "ctypes.unsigned_char.ptr(ctypes.UInt64("0x7f73d5c87650"))"
// so as we see neither of these is 77, this is for the example of "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox"
// tries to do read string on stringPtr, if it fails then it falls to read as jschar
var readJSCharString = function() {
var assumption_max_len = known_len ? known_len : 500;
var ptrAsArr = ctypes.cast(stringPtr, ctypes.unsigned_char.array(assumption_max_len).ptr).contents; // MUST cast to unsigned char (not ctypes.jschar, or ctypes.char) as otherwise i dont get foreign characters, as they are got as negative values, and i should read till i find a 0 which is null terminator which will have unsigned_char code of 0 // can test this by reading a string like this: "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox" at js array position 36 (so 37 if count from 1), we see 183, and at 77 we see char code of 0 IF casted to unsigned_char, if casted to char we see -73 at pos 36 but pos 77 still 0, if casted to jschar we see chineese characters in all spots expect spaces even null terminator is a chineese character
console.info('ptrAsArr.length:', ptrAsArr.length);
//console.log('debug-msg :: dataCasted:', dataCasted, uneval(dataCasted), dataCasted.toString());
var charCode = [];
var fromCharCode = []
for (var i=0; i<ptrAsArr.length; i++) { //if known_len is correct, then will not hit null terminator so like in example of "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox" if you pass length of 77, then null term will not get hit by this loop as null term is at pos 77 and we go till `< known_len`
var thisUnsignedCharCode = ptrAsArr.addressOfElement(i).contents;
if (thisUnsignedCharCode == 0) {
// reached null terminator, break
console.log('reached null terminator, at pos: ', i);
break;
}
charCode.push(thisUnsignedCharCode);
fromCharCode.push(String.fromCharCode(thisUnsignedCharCode));
}
console.info('charCode:', charCode);
console.info('fromCharCode:', fromCharCode);
var char16_val = fromCharCode.join('');
console.info('char16_val:', char16_val);
return char16_val;
}
if (!jschar) {
try {
var char8_val = stringPtr.readString();
console.info('stringPtr.readString():', char8_val);
return char8_val;
} catch (ex if ex.message.indexOf('malformed UTF-8 character sequence at offset ') == 0) {
console.warn('ex of offset utf8 read error when trying to do readString so using alternative method, ex:', ex);
return readJSCharString();
}
} else {
return readJSCharString();
}
}

JDBC ARRAY(ORACLE CollectionTYPE) use String Value Encoding in JAVA

I'm not good at English
and my English is Grammar is wrong
wish for understanding
I am using ARRAY CLASS in OJDBC6.
Use it(ARRAY class) to send data to oracle database(procedure).
Data of number type and date type is very well in oracle.
Howerver data of varchar2 type is null in oracle (ARRAY)
I see diffrent solution (java path setup orai18n.jar file)
but it have error of java.lang.NoSuchMethodError: oracle.i18n.text.converter.CharacterConverterOGS.getInstance(I)Loracle/i18n/text/converter/CharacterConverter;
I don't found A solution to this problem
Please How to solve this problem ~~ ~~
I use JDK1.7,OJDBC6.jar
----------------------------------------------orclae code----------------------------------
CREATE OR REPLACE
TYPE XXXXXXXX_TYPE AS OBJECT(
nnnnnnn1 NUMBER
,nnnnnnn2 NUMBER
,nnnnnnn3 NUMBER
,vvvvvvv1 VARCHAR2(150)
,nnnnnnn4 NUMBER
,dddddddd1 DATE
,vvvvvvv2 VARCHAR2(250)
,nnnnnnn5 NUMBER
,dddddddd2 DATE
,nnnnnnn6 NUMBER
,dddddddd3 DATE
,nnnnnnn7 NUMBER
,vvvvvvv3 VARCHAR2(10)
,vvvvvvv4 VARCHAR2(30)
,vvvvvvv5 VARCHAR2(20)
,vvvvvvv6 VARCHAR2(80)
--XXXXXXXX_TYPE end
CREATE OR REPLACE
TYPE XXXXXXXXXXX_TBL AS TABLE OF XXXXXXXX_TYPE
-- XXXXXXXXXXX_TBL end
------------------------------------------java----------------------------------
public class Ex_mainJava {
public static void main(String[] args){
DBPoolCon db = DBPoolCon.getInstance();
String str = "{call xxx_xxx_xxxx_xxxx_result_pkg.XX_XX_result(?,?,?)}";
try {
Connection oracleConn = (OracleConnection) db.buildPoolConnection();
CallableStatement callStatement = oracleConn.prepareCall(str);
Object[][] x_ctr_tbl = new Object[1][16];
x_ctr_tbl[0][0] = 1;
x_ctr_tbl[0][1] = 2;
x_ctr_tbl[0][2] = 3;
x_ctr_tbl[0][3] = "ABC";
x_ctr_tbl[0][4] = 4;
x_ctr_tbl[0][5] = java.sql.Date.valueOf("2014-06-18");
x_ctr_tbl[0][6] = "DEF";
x_ctr_tbl[0][7] = 5;
x_ctr_tbl[0][8] = java.sql.Date.valueOf("2014-06-18");
x_ctr_tbl[0][9] = 6;
x_ctr_tbl[0][10] = java.sql.Date.valueOf("2014-06-18");
x_ctr_tbl[0][11] = 7;
x_ctr_tbl[0][12] = "HHHH";
x_ctr_tbl[0][13] = "KKKK";
x_ctr_tbl[0][14] = "JJJJ";
x_ctr_tbl[0][15] = "MMMM";
ArrayDescriptor oracleCollection2 = ArrayDescriptor.createDescriptor("XXXXXXXXXXX_TBL ".toUpperCase(),oracleConn);
ARRAY oraArry2 = new ARRAY(oracleCollection2, oracleConn,x_ctr_tbl);
System.out.println(oraArry2.dump());
callStatement.registerOutParameter(1, java.sql.Types.VARCHAR);
callStatement.registerOutParameter(2, java.sql.Types.INTEGER);
callStatement.setArray(3,oraArry2);
callStatement.execute();
String s =callStatement.getString(1);
int i = callStatement.getInt(2);
System.out.println("error:"+s);
System.out.println("code:"+i);
callStatement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
---------console-----------------------------------
System.out.println(oraArry2.dump());
nnnnnnn1 1
,nnnnnnn2 2
,nnnnnnn3 3
vvvvvvv1 ??? <---problem
nnnnnnn4 4
dddddddd1 2014-06-18 00:00:00.0
vvvvvvv2 ??? <---problem
nnnnnnn5 5
dddddddd2 2014-06-18 00:00:00.0
nnnnnnn6 6
dddddddd3 2014-06-18 00:00:00.0
nnnnnnn7 7
vvvvvvv3 ??? <---problem
vvvvvvv4 ??? <---problem
vvvvvvv5 ??? <---problem
vvvvvvv6 ??? <---problem
EXAMPLE CODE SOURCE
please help me to problem of ??? (problem)
Thank you.
you read my source for my problem

JQL performance - natural sort for custom text field

I am struggling with a JQL query.
We have a custom field called 'Build Reported' which is a text field. It has values like '4.7.323H', '5.1.123L', '3.1.456E', etc.
I need to write a simple query that will give me all issues reported after the user-specified version.
JQL function prototype: searchIssues('Build Integrated', '>', '4.7.323B')
To do this, I am firing a JQL Query that gives me the Build Reported for all the issues, I then iterate through each issue and perform a char-by-char comparison to determine if the Build Reported version of the current issue is greater than the one specified by the user. This seems to take too long to execute since I have to retrieve all the issues from jira database.
Is there a faster way to achieve this? Here is what I have so far:
// Get all the arguments
java.util.List args = operand.getArgs();
CustomField cf = customFieldManager.getCustomFieldObjectByName((String)args.get(0));
Long cfID = cf.getIdAsLong();
String operator = (String)args.get(1);
String userVersion = (String)args.get(2);
String jiraVersion = "";
java.util.List issues;
Iterator issuesIterator;
Issue issue;
issues = getAllIssues(user, interestedInVersion, cfID);
issuesIterator = issues.iterator();
// Iterate over all the issues
while(issuesIterator.hasNext())
{
issue = (Issue)issuesIterator.next();
// Get the Build reported value
jiraVersion = (String)issue.getCustomFieldValue(cf);
if(jiraVersion != null &&
!jiraVersion.equals(""))
{
// Compare user-specified version to the one retrieved from database
if(compareVersions(jiraVersion, userVersion, operator))
{
// Add the issue to the result set
literals.add(new QueryLiteral(operand, issue.getId()));
}
}
}
// cfID is the ID for the custom field Build Reported
private java.util.List getAllIssues(User user, Long cfID) throws SearchException, ParseException
{
JqlQueryBuilder builder = JqlQueryBuilder.newBuilder();
builder.where().project("SDEV").and().customField(cfID).isNotEmpty();
Query query = builder.buildQuery();
SearchResults results = searchService.search(user, query, PagerFilter.getUnlimitedFilter());
return results.getIssues();
}
Please note that I do not have any other filters that I could use for the JQL Query Builder to help me reduce the size of the result set.
I found an alternative to the issue I described in my question. Instead of using JQL, I ended up firing a direct SELECT and this turned out to be way quicker. The function below is a part of the JQL Plugin. Here is the code:
This is what I ended up doing:
public java.util.List getValues(#NotNull QueryCreationContext queryCreationContext, #NotNull FunctionOperand operand, #NotNull TerminalClause terminalClause)
{
try
{
// User
User user = queryCreationContext.getUser();
// Args
java.util.List args = operand.getArgs();
CustomField cf = customFieldManager.getCustomFieldObjectByName((String)args.get(0));
Long cfID = cf.getIdAsLong();
String operator = (String)args.get(1);
String userVersion = (String)args.get(2);
// Locals
java.util.List literals = new java.util.LinkedList();
MutableIssue issue = null;
String issueId = "";
String jiraVersion = "";
// DB
Connection conn = null;
String url = "jdbc:jtds:sqlserver://*****:*****/jiradb";
String driver = "net.sourceforge.jtds.jdbc.Driver";
String userName = "*******";
String password = "*******";
String sqlQuery = null;
Statement statement = null;
ResultSet resultSet = null;
Class.forName(driver).newInstance();
conn = DriverManager.getConnection(url, userName, password);
// Get all the issues that has the custom field set
sqlQuery = " SELECT t2.id AS IssueId, t1.stringvalue AS JiraVersion " + "\n" +
" FROM jiradb.jiraschema.customfieldvalue t1 " + "\n" +
" INNER JOIN jiradb.jiraschema.jiraissue t2 " + "\n" +
" ON t1.issue = t2.id " + "\n" +
" WHERE t1.customfield = " + Long.toString(cfID) + " " + "\n" +
" AND t1.stringvalue IS NOT NULL " + "\n" +
" AND t1.stringvalue != '' " + "\n" +
" AND t2.pkey LIKE 'SDEV-%' ";
// Iterate over the result set
statement = conn.createStatement();
resultSet = statement.executeQuery(sqlQuery);
while (resultSet.next())
{
issueId = resultSet.getString("IssueId");
jiraVersion = resultSet.getString("JiraVersion");
// Compare the version from jira with the user provided version
// This is my own function that does char-by-char comparison
if(compareVersions(jiraVersion, userVersion, operator))
{
// Get the issue object to add to the result
issue = ComponentManager.getInstance().getIssueManager().getIssueObject(Long.parseLong(issueId));
// Add the issue to the result
literals.add(new QueryLiteral(operand, issue.getId()));
}
}
// Return all the matching issues here
return literals;
}
catch(Exception e)
{
// Exception handling
}
return null;
}
And this is how the plugin is used:
issue in searchIssues('Build Reported', '>', '5.1.104');

Resources