Pentaho: how to read automatically column names and save them in variables? - pentaho

I am new in Pentaho and I Need a help.
I am getting data from database table, and then I need to count the number of columns of these tables and save their names into variables. Does somebody know how to make this? Or how to read the column names in Java Script step? Thank you for your help.

First of all, please note, that you will not be able to see variable value in the same transformation, where you have set/changed it. Basically, variable values for transformation are read on its initalization. So, you can change variable value for parent/grandparent job, but not for same transformation.
Option 1 (Metadata structure of stream step):
One option is to use Metadata structure of stream step http://wiki.pentaho.com/display/EAI/Metadata+Structure+of+Stream
The step will give you following fields:
Position: The position of the field in the inbound data stream
Fieldname: The field name in the inbound data stream
Comments: undocummented
Type: String, Integer, Number etc
Length: The field length
Precision: Applicable for Integer, Number and -1 if not applicable
(e.g. Strings)
Origin: The step where the meta data was derived from.
The output of this step can subsequently used to set variable values.
Option 2 (Javascript):
Java Script step has getInputRowMeta() function
Which returns RowMetaInterface object.
Further you may call getValueMetaList() method, which will return you List of ValueMetaInterface objects. Then you can just iterate through all items in the list and call getName() for each object to get a name of each input field.
Example (most of the code here is actually just to illustrate output):
// get instance of RowMetaInterface, which represents metadata of your input row:
var rowMetaInterface = getInputRowMeta();
// get List of ValueMetaInterface objects, which represent each of your input fields:
var valueMetaList = rowMetaInterface.getValueMetaList();
// get this object to be able to iterate over the list:
var iterator = valueMetaList.iterator();
// I am going to save all results into this JS object, then convert it to JSON string and pass into a variable
var allFields = [];
while (iterator.hasNext()) {
// get current ValueMetaInterface object:
var valueMetaInterface = iterator.next();
// The name of current field:
var fieldName = valueMetaInterface.getName();
// getType() returns just an internal integer number of the type:
var typeIndex = valueMetaInterface.getType();
// typeName will hold the actual String name of the type:
var typeName = org.pentaho.di.core.row.ValueMetaInterface.typeCodes[typeIndex];
// You proabably don't need the following part. It is here just for illustration purpose:
// Prepare data to be converted to JSON:
var field = {};
// wrap Java String into a JavaScript String object to be able to convert them into Json
field.fieldName = String(fieldName);
field.fieldType = String(typeName);
allFields.push(field)
}
var allFieldsJson = JSON.stringify(allFields);
/* scope of the variable:
"s": System scope
"r": root
"p": parent
"g": grandparent*/
var variableScope = "r";
setVariable("inputFields", allFieldsJson, variableScope);
writeToLog("b", "JSON string:");
writeToLog("b", allFieldsJson);
// In other job/transformation you'll be able to parse json object into a javascript object back:
var fields = JSON.parse(allFieldsJson);
for (var i = 0; i < fields.length; i++) {
fieldName = fields[i].fieldName;
fieldType = fields[i].fieldType;
writeToLog("b", "Field number " + i + ":");
writeToLog("b", fieldName);
writeToLog("b", fieldType);
}
In the log you will see following output:
2016/10/13 15:33:09 - Modified Java Script Value.0 - Optimization level set to 9.
2016/10/13 15:33:09 - Modified Java Script Value.0 - JSON string:
2016/10/13 15:33:09 - Modified Java Script Value.0 - [{"fieldName":"test","fieldType":"String"},{"fieldName":"test 2","fieldType":"Integer"},{"fieldName":"another field","fieldType":"BigNumber"}]
2016/10/13 15:33:09 - Modified Java Script Value.0 - Field number 0:
2016/10/13 15:33:09 - Modified Java Script Value.0 - test
2016/10/13 15:33:09 - Modified Java Script Value.0 - String
2016/10/13 15:33:09 - Modified Java Script Value.0 - Field number 1:
2016/10/13 15:33:09 - Modified Java Script Value.0 - test 2
2016/10/13 15:33:09 - Modified Java Script Value.0 - Integer
2016/10/13 15:33:09 - Modified Java Script Value.0 - Field number 2:
2016/10/13 15:33:09 - Modified Java Script Value.0 - another field
2016/10/13 15:33:09 - Modified Java Script Value.0 - BigNumber
2016/10/13 15:33:09 - Modified Java Script Value.0 - Finished processing (I=0, O=0, R=1, W=1, U=0, E=0)

Related

Karate : dynamic test data using scenario outline is not working in some cases

I was tryiny to solve dynamic test data problem using dynamic scenario outline as mentioned in the documentation https://github.com/karatelabs/karate#dynamic-scenario-outline
It worked perfectly fine when I passed something like this in Example section
Examples:
|[{'entity':country},{'entity':state},{'entity':district},{'entity':corporation}]]
But I tried to generate this json object programatically , I am getting aa strange error
WARN com.intuit.karate - ignoring dynamic expression, did not evaluate to list: users - [type: MAP, value: com.intuit.karate.ScriptObjectMap#2b8bb184]
Code to generate json object
* def user =
"""
function(response){
entity_type_ids =[]
var entityTypes = response.entityTypes
for(var i =0;i<entityTypes.length;i++ ){
object = {}
object['entity'] = entityTypes[i].id
entity_type_ids.push(object)
}
return JSON.stringify(entity_type_ids)
}
"""

Gatling use session.set and feed simultaneously

If I use .get("/***/quotes-${endPoint}/quotes?source=rtbp&userid=test&symbol=${pTypeSymbol}${authM}${pEqSymbol}") then ${pEqSymbol} work but
${pTypeSymbol} will be ${pEqSymbol} it's incorrect example of get it should be in code below
val getApiKeyScenario = scenario("getApiKey")
.feed(getApiKeyData)
.feed(pEqSymbolFeed)
.feed(pOptionSymbol)
.feed(pOtherSymbol)
.exec(session => session
.set("endPoint", "v1")
.set("pTypeSymbol", "${pEqSymbol}")
.set("authM", "&apikey=***********"))
.exec(http("getApiKeyRequest")
.get("/******/quotes-${endPoint}/quotes?source=rtbp&userid=test&symbol=${pTypeSymbol}${authM}")
.check(status.is(200))
.check(checkIf(doLogResponse) {
bodyString.saveAs("pResponse")
})
)
.doIf(doLogResponse) {
logResponse()
}
If I try .set("pTypeSymbol", pEqSymbolFeed.readRecords.head("pEqSymbol")) will be loop
If I try .set("pTypeSymbol", s"${pEqSymbol.isDefined}") not found: value pEqSymbol
If I try s"${pEqSymbol}" not found: value pEqSymbol
I logs now is GET *******/quotes-v1/quotes?source=rtbp&userid=test&symbol=${pEqSymbol}&apikey=******
But should be GET *******/quotes-v1/quotes?source=rtbp&userid=test&symbol="Here my value from feed"&apikey=******
Please read the official documentation:
This Expression Language only works on String values being passed to Gatling DSL methods. Such Strings are parsed only once, when the Gatling simulation is being instantiated.
For example queryParam("latitude", session => "${latitude}") wouldn’t work because the parameter is not a String, but a function that returns a String.
In your example, you don't need to copy pEqSymbol into pTypeSymbol, you can directly write:
.exec(session => session
.set("endPoint", "v1")
.set("authM", "&apikey=***********"))
.exec(http("getApiKeyRequest")
.get("/******/quotes-${endPoint}/quotes?source=rtbp&userid=test&symbol=${pEqSymbol}${authM}")
)
)
But if you insist on copying, you have to use the Session API:
.set("pTypeSymbol", session("pEqSymbol").as[String])

IntelliJ IDEA LiveTemplate auto increment between usages

I am trying to make my life easier with Live Templates in intelliJ
I need to increment some param by 1 every-time I use the snippet.
So I tried to develop some groovyScript, and I am close, but my groovy capabilities keeps me back. the number is not incremented by 1, but incremented by 57 for some reason... (UTF-8?)
here is the script:
File file = new File("out.txt");
int code = Integer.parseInt(file.getText('UTF-8'));
code=code+1;
try{
if(_1){
code = Integer.parseInt(_1);
}
} catch(Exception e){}
file.text = code.toString();
return code
So whenever there's param passed to this script (with _1) the initial value is set, and otherwise simply incremented.
this script needs to be passed to the live template param with:
groovyScript("File file = new File(\"out.txt\");int code = Integer.parseInt(file.getText(\'UTF-8\'));code=code+1;String propName = \'_1\';if(this.hasProperty(propName) && this.\"$propName\"){code = Integer.parseInt(_1);};file.text =code.toString();return code", "<optional initial value>")

Iterate over a CSV Data Set Config with varying starting index in Apache JMeter

My requirement is to iterate over a CSV Data Set Config in Apache JMeter with a varying starting index. Let us assume I have started a test plan in JMeter today and my CSV file has 8 variables. The first time my sampler will run from 1st row to 8th row. The next time I will start running my test plan I want sampler to pick values from 2nd index to 8th index. In this manner, I want to iterate over CSV file using CSV Data set config.
I am able to initialize a counter for every test run in Apache JMeter using setUp ThreadGroup and tearDown Thread group. I am able to extract the same using _P(count) in JMeter.
In setUp Thread group I have included JSR 223 Sampler and written a script like
def file = new File('number')
if (!file.exists() || !file.canRead()) {
number = '1'
}
else {
number = file.text
}
props.put('number', number as String)
In tearDown Thread Group the JSR223 Sampler has a script like
def number = props.get('number') as int
number++
new File('number').text = number
I want to loop over my CSV data set config file with the counter through properties file( which is getting incremented by 1 for every test run)
Please check the below plan:-
Input CSV example:-
If Controller has the below code:-
${__groovy(vars.get('Used').take(1)!='Y')}
In JSR223 post processor, I have the below code:-
def inputFile = new File("C:\\Path\\toFile\\Excel\\OutputCSV.csv")
def lines = inputFile.readLines()
boolean isWrite = false;
lines.each { String line ->
if(line.contains('Used'))
{
inputFile.write(line + '\n')
}
else
{
if(line.startsWith('Y'))
{
inputFile.append(line + '\n')
}
else if (!isWrite)
{
inputFile.append('Y' + line + '\n')
isWrite = true;
}
else
{
inputFile.append(line + '\n')
}
}
}
First Run output:-
Second Run output:-
As you can see, in first run sample 1 execute 4 time and in 2nd it is executed 3 times.
This is not the nicest or best code, just first try.
Please check if helps.

VTD-XML Exception: Name space qualification Exception: prefixed attribute not qualified

I receive an XML via a web service and I am using legacy code (which uses dom4j) to perform some xml transformation. Loading/parsing the original XML into VTD-XML (VTDGen) works fine, no exceptions thrown. However, after loading the xml into dom4j, I noticed some of the element namespace declarations and attributes are re-arranged. Apparently, this re-arrangement causes VTD-XML to throw the following exception:
Exception:
Name space qualification Exception: prefixed attribute not qualified
Line Number: 101 Offset: 1827
Here is the element at this line number in the original XML:
<RR_PerformanceSite:PerformanceSite_1_4 RR_PerformanceSite:FormVersion="1.4" xmlns:NSF_ApplicationChecklist="http://apply.grants.gov/forms/NSF_ApplicationChecklist-V1.1" xmlns:NSF_CoverPage="http://apply.grants.gov/forms/NSF_CoverPage-V1.1" xmlns:NSF_DeviationAuthorization="http://apply.grants.gov/forms/NSF_DeviationAuthorization-V1.1" xmlns:NSF_Registration="http://apply.grants.gov/forms/NSF_Registration-V1.1" xmlns:NSF_SuggestedReviewers="http://apply.grants.gov/forms/NSF_SuggestedReviewers-V1.1" xmlns:PHS398_CareerDevelopmentAwardSup="http://apply.grants.gov/forms/PHS398_CareerDevelopmentAwardSup_1_1-V1.1" xmlns:PHS398_Checklist="http://apply.grants.gov/forms/PHS398_Checklist_1_3-V1.3" xmlns:PHS398_CoverPageSupplement="http://apply.grants.gov/forms/PHS398_CoverPageSupplement_1_4-V1.4" xmlns:PHS398_ModularBudget="http://apply.grants.gov/forms/PHS398_ModularBudget-V1.1" xmlns:PHS398_ResearchPlan="http://apply.grants.gov/forms/PHS398_ResearchPlan_1_3-V1.3" xmlns:PHS_CoverLetter="http://apply.grants.gov/forms/PHS_CoverLetter_1_2-V1.2" xmlns:RR_Budget="http://apply.grants.gov/forms/RR_Budget-V1.1" xmlns:RR_KeyPersonExpanded="http://apply.grants.gov/forms/RR_KeyPersonExpanded_1_2-V1.2" xmlns:RR_OtherProjectInfo="http://apply.grants.gov/forms/RR_OtherProjectInfo_1_2-V1.2" xmlns:RR_PerformanceSite="http://apply.grants.gov/forms/PerformanceSite_1_4-V1.4" xmlns:RR_PersonalData="http://apply.grants.gov/forms/RR_PersonalData-V1.1" xmlns:RR_SF424="http://apply.grants.gov/forms/RR_SF424_1_2-V1.2" xmlns:RR_SubawardBudget="http://apply.grants.gov/forms/RR_SubawardBudget-V1.2" xmlns:SF424C="http://apply.grants.gov/forms/SF424C-V1.0" xmlns:att="http://apply.grants.gov/system/Attachments-V1.0" xmlns:codes="http://apply.grants.gov/system/UniversalCodes-V2.0" xmlns:globlib="http://apply.grants.gov/system/GlobalLibrary-V2.0">
Here is the same element after loaded into dom4j:
<RR_PerformanceSite:PerformanceSite_1_4 xmlns:RR_PerformanceSite="http://apply.grants.gov/forms/PerformanceSite_1_4-V1.4" xmlns:NSF_ApplicationChecklist="http://apply.grants.gov/forms/NSF_ApplicationChecklist-V1.1" xmlns:NSF_CoverPage="http://apply.grants.gov/forms/NSF_CoverPage-V1.1" xmlns:NSF_DeviationAuthorization="http://apply.grants.gov/forms/NSF_DeviationAuthorization-V1.1" xmlns:NSF_Registration="http://apply.grants.gov/forms/NSF_Registration-V1.1" xmlns:NSF_SuggestedReviewers="http://apply.grants.gov/forms/NSF_SuggestedReviewers-V1.1" xmlns:PHS398_CareerDevelopmentAwardSup="http://apply.grants.gov/forms/PHS398_CareerDevelopmentAwardSup_1_1-V1.1" xmlns:PHS398_Checklist="http://apply.grants.gov/forms/PHS398_Checklist_1_3-V1.3" xmlns:PHS398_CoverPageSupplement="http://apply.grants.gov/forms/PHS398_CoverPageSupplement_1_4-V1.4" xmlns:PHS398_ModularBudget="http://apply.grants.gov/forms/PHS398_ModularBudget-V1.1" xmlns:PHS398_ResearchPlan="http://apply.grants.gov/forms/PHS398_ResearchPlan_1_3-V1.3" xmlns:PHS_CoverLetter="http://apply.grants.gov/forms/PHS_CoverLetter_1_2-V1.2" xmlns:RR_Budget="http://apply.grants.gov/forms/RR_Budget-V1.1" xmlns:RR_KeyPersonExpanded="http://apply.grants.gov/forms/RR_KeyPersonExpanded_1_2-V1.2" xmlns:RR_OtherProjectInfo="http://apply.grants.gov/forms/RR_OtherProjectInfo_1_2-V1.2" xmlns:RR_PersonalData="http://apply.grants.gov/forms/RR_PersonalData-V1.1" xmlns:RR_SF424="http://apply.grants.gov/forms/RR_SF424_1_2-V1.2" xmlns:RR_SubawardBudget="http://apply.grants.gov/forms/RR_SubawardBudget-V1.2" xmlns:SF424C="http://apply.grants.gov/forms/SF424C-V1.0" xmlns:att="http://apply.grants.gov/system/Attachments-V1.0" xmlns:codes="http://apply.grants.gov/system/UniversalCodes-V2.0" xmlns:globlib="http://apply.grants.gov/system/GlobalLibrary-V2.0" RR_PerformanceSite:FormVersion="1.4">
The problem is regarding the attribute (at offset 1827, at the end of the element) in the new XML element: RR_PerformanceSite:FormVersion="1.4"
Here is what removes the exception:
1. Adding the RR_PerformanceSite xmlns declaration for this element to the root element of the XML doc.
2. Replacing new element with original element. This SEEMS to lead me to believe that the order of the attributes/ns declarations affects VTD when parsing.
NOTE: I parse the xml doc setting ns aware to 'true' with both xml docs (original and post-dom4j xml). Also, new VTD objects are created for each xml, original and post-dom4j.
I tried to put 'RR_PerformanceSite:FormVersion="1.4"' at the beginning of the element like the original but that does not remove the exception. The offset in the error message is different due to the change of location of the attribute. Does the order of the xmlns declarations affect VTD?
I have looked at the VTDGen source code and cannot figure out why this exception is being thrown.
Why would dom4j parse the new doc and vtd is unable to? Can anyone can shed some light on this?
It appears to be a bug on VTD-XML, related with namespace declaration order.
Always reproducible using the following Java code
public class SchemaTester {
/**
* #param args
*/
public static void main(String[] args) throws Exception {
String bad = "C:/Temp/VTD_bad.xml"; // XML files to test
String good = "C:/Temp/VTD_good.xml";
StringBuilder sb = new StringBuilder();
char[] buf = new char[4*1024];
FileReader fr = new FileReader(bad);
int readed = 0;
while ((readed = fr.read(buf, 0, buf.length)) != -1) {
sb.append(buf, 0, readed);
}
fr.close();
String x = sb.toString();
//instantiate VTDGen
//and call parse
VTDGen vg = new VTDGen();
vg.setDoc(x.getBytes("UTF-8"));
vg.parse(true); // set namespace awareness to true
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot (vn);
ap.selectXPath("//*/#*");
int i= -1;
while((i=ap.evalXPath()) != -1) {
// i will be attr name, i+1 will be attribute value
System.out.println("\t\tAttribute ==> " + vn.toNormalizedString(i));
System.out.println("\t\tValue ==> " + vn.toNormalizedString(i+1));
}
}
}
The OP has uploaded the XML to https://gist.github.com/2696220