Attempt to de-reference a null when try to save button click this error trigger fire - apex

Requirement : ChangingFirstlttrUpper
Trigger
--------
trigger ChangingFirstlttrUpper on Account (before insert,before update) {
ChanignToCaps.Change(trigger.new);
if(trigger.isBefore )
if(trigger.IsInsert ||trigger.IsUpdate )
ChanignToCaps.Change(trigger.new);
}
handler helper class
global class ChanignToCaps{
global static void Change( Project__c [] Pro){
for(Project__c P :Pro){
if(P.PoPupfield__c !=null || P.PoPupfield__c != ' '){
P.PoPupfield__c = formatToUpper(P.PoPupfield__c );
}
}
handler helper class
public class FirstlttrUpper{
public static String formatToUpper (String Str) {
String result = '';
for (String iter : Str.split('[ ]+')) {
if (iter != null && iter != '') {
if (iter.length() > 1) {
result += iter.substring(0,1).toUpperCase() + iter.substring(1,iter.length()) + ' ';
}
else
result += iter.substring(0,1).toUpperCase() + ' ';
}
}
return result;
}
}
ERROR!
ChangingFirstlttrUpper: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object Class.FirstlttrUpper.formatToUpper: line 4, column 1 Class.ChanignToCaps.Change: line 10, column 1 Trigger.ChangingFirstlttrUpper: line 2, column 1

This line on the helper class here stands out:
if(P.PoPupfield__c !=null || P.PoPupfield__c != ' ')
That if condition will always evaluate to true, even if there is a null value in the field. It looks like the error is pointing to a null value being fed into the parameter for formatToUpper.
To fix that, I would recommend the following:
if(P.PoPupfield__c !=null && P.PoPupfield__c != ' ')
If that's not it, can you provide some data from the record you tried to save?

Related

Solidity method taking in bytes32 and hashing but values with previous hash don't match

Here's the code:
function playGame(bytes32 hashedMove) public returns (bool) {
require(
playerOne != address(0x0) && playerTwo != address(0x0),
"Game needs more players to join first"
);
require(
msg.sender == playerOne || msg.sender == playerTwo,
"You did not join the game as a player"
);
if (msg.sender == playerOne && hashedPlayerOneMove == "") {
hashedPlayerOneMove = hashedMove;
emit PlayerMadeMove(playerOne);
} else if (msg.sender == playerTwo && hashedPlayerTwoMove == "") {
hashedPlayerTwoMove = hashedMove;
emit PlayerMadeMove(playerTwo);
} else {
return false;
}
return true;
}
The above method takes in a hashedMove argument which I am using the following site to get: https://emn178.github.io/online-tools/keccak_256.html
I send a value of 2test2 hashed which is 0x0698472c4668bddd0c694601ca101551bd7b5cfe6dc780ab37bccfc99ad22e4c
Now another method takes in the constituents of the hash which are 2 and test2 to compare it with the stored hash:
function revealPlayerChoice(uint256 move, bytes32 password)
public
returns (uint256)
{
require(
hashedPlayerOneMove != bytes32(0x0) &&
hashedPlayerTwoMove != bytes32(0x0),
"The game is still running!"
);
bytes32 hashedAnswer = getSaltedHash(move, password);
console.logBytes32(hashedAnswer);
console.logBytes32(hashedPlayerOneMove);
if (msg.sender == playerOne && hashedAnswer == hashedPlayerOneMove) {
playerOneMove = move;
} else if (
msg.sender == playerTwo && hashedAnswer == hashedPlayerTwoMove
) {
playerTwoMove = move;
}
if (playerOneMove != 0 && playerTwoMove != 0) {
getGameOutcome();
}
}
I'm sending 2 as uint and 0x0000000000000000000000000000000000000000000000000000007465737432 (test2 in bytes) to the revealPlayerChoice method. However the values I'm getting from the console log are different. hashedAnswer is the hash I'm calculating in the method and hashedPlayerOneMove is the hash stored in playGame method.
for example, The console log outputs are
0x566d7dd4e9dc72e9beef887f2982703a0d0f9dd1b6505ee3ff5310c7383637bd
0x0698472c4668bddd0c694601ca101551bd7b5cfe6dc780ab37bccfc99ad22e4c
I would like to understand why the values are different? I'm using keccak256 to hash in solidity (pragma solidity ^0.8.0;) as well:
function getSaltedHash(uint answer, bytes32 salt) pure returns (bytes32) {
return keccak256(abi.encodePacked(answer, salt));
}
The key to your problem might be what abi.encodePacked(answer, salt) is returning.
When you pass the following arguments:
uint256 answer = 2
bytes32 salt = 0x0000000000000000000000000000000000000000000000000000007465737432
abi.encodePacked(answer, salt) returns:
0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000007465737432
And then, if you run the keccak256(bytes) with the previous value, it returns:
0x566d7dd4e9dc72e9beef887f2982703a0d0f9dd1b6505ee3ff5310c7383637bd

FATAL_ERROR|System.LimitException: Too many SOQL queries: 201

I am getting too many SOQL queries 201 error in apex class
I tried to check the no of queries within loop
Below is exact error -
11:48:43.9 (2785518121)|FATAL_ERROR|System.LimitException: Too many SOQL queries: 201
Class.GEN_CalculateActToWinScores.calcUserEligible: line 1343, column 1
Class.GEN_ActonFactsScoreUserEligibleBatch.execute: line 74, column 1
11:48:43.9 (2851114444)|CODE_UNIT_FINISHED|GEN_ActonFactsScoreUserEligibleBatch
11:48:43.9 (2852614277)|EXECUTION_FINISHED
Below is the code for method GEN_CalculateActToWinScores.calcUserEligible -
// Method for set user as ready for AoF
public static void calcUserEligible(List<User> usersList ){
List<Act_on_Facts__c> actOnFactDelete = new List<Act_on_Facts__c>();
Set<String> oppOpenStageNameSet = new Set<String>();
oppOpenStageNameSet.add(GEN_Constants.OPPORTUNITY_IDENTIFY);
oppOpenStageNameSet.add(GEN_Constants.OPPORTUNITY_QUALIFY);
oppOpenStageNameSet.add(GEN_Constants.OPPORTUNITY_PROPOSE);
oppOpenStageNameSet.add(GEN_Constants.OPPORTUNITY_NEGOTIATE);
Set<String> oppReadOnlyRecordTypeNameSet = new Set<String>();
oppReadOnlyRecordTypeNameSet.add(GEN_Constants.READONLY_SINGLE_ACCOUNT_OPP_RECORDTYPENAME);
oppReadOnlyRecordTypeNameSet.add(GEN_Constants.READONLY_WON_AND_DONE_OPP_RECORDTYPENAME);
oppReadOnlyRecordTypeNameSet.add(GEN_Constants.READONLY_CHILD_OPP_RECORDTYPENAME);
oppReadOnlyRecordTypeNameSet.add(GEN_Constants.READONLY_MULTI_ACCOUNT_OPP_RECORDTYPENAME);
if(usersList.size() > 0){
List<Id> idList = new List<Id>();
Integer countResult = 0;
List<User> newUserList = new List<User>();
Integer limitQuery; //10000 //2001
Integer limitResult; //2000
if(CSL_ActOnFactsLimits__c.getValues('QUERY_LIMIT') != null){
limitQuery = Integer.valueOf(CSL_ActOnFactsLimits__c.getValues('QUERY_LIMIT').Value__c);
}
if(CSL_ActOnFactsLimits__c.getValues('MAX_QUERY_RESULTS') != null){
limitResult = Integer.valueOf(CSL_ActOnFactsLimits__c.getValues('MAX_QUERY_RESULTS').Value__c);
}
Boolean eligible = true;
for (User userElement : usersList){
String logDetail = ' QUERY_LIMIT:limitQuery: '+limitQuery+' MAX_QUERY_RESULTS:limitResult: '+limitResult;
logDetail += ' userElement.id: '+userElement.id;
eligible = true;
CSH_ActOnFacts_UserEligible__c userEligible = null;
if(CSH_ActOnFacts_UserEligible__c.getValues(userElement.id) != null){
userEligible = CSH_ActOnFacts_UserEligible__c.getValues(userElement.id);
}
CSH_ActOnFacts_UserEligible__c profileEligible = null;
if(CSH_ActOnFacts_UserEligible__c.getValues(userElement.ProfileId) != null){
profileEligible = CSH_ActOnFacts_UserEligible__c.getValues(userElement.ProfileId);
}
List<Act_on_Facts__c> actonfacts = [select id from Act_on_Facts__c where Lookup_User__c = : userElement.id limit 1];
if(userElement.ManagerId == null){
userElement.Line_Manager_Optional__c = true;
userElement.Act_On_Facts_Manager_List__c = null;
}
if(userElement.Default_Macro_Segment__c == null){
userElement.Default_Macro_Segment__c = 'None';
}
if (userElement.IsActive == false){
eligible = false;
}else if(profileEligible != null || userEligible != null) {
eligible = false;
}else{
countResult = [select count() from Account WHERE OwnerId = :userElement.id LIMIT :limitQuery];
logDetail += ' Account.countResult: '+countResult;
if(countResult!=null && countResult > limitResult ){
eligible = false;
}
if(eligible){
if(oppOpenStageNameSet !=null && oppOpenStageNameSet.size()>0 && oppReadOnlyRecordTypeNameSet !=null && oppReadOnlyRecordTypeNameSet.size()>0){
countResult = [select count() from Opportunity WHERE OwnerId = :userElement.id AND StageName IN:oppOpenStageNameSet AND RecordType.DeveloperName NOT IN: oppReadOnlyRecordTypeNameSet LIMIT :limitQuery];
logDetail += ' Opportunity.countResult: '+countResult;
if(countResult!=null && countResult > limitResult ){
eligible = false;
}
}
}
}
if(!eligible){
userElement.Act_on_Facts_Eligible__c = false;
// remove user from Act on Facts
if(actonfacts != null && actonfacts.size()>0){
for(Act_on_Facts__c a : actonfacts){
actOnFactDelete.add(a);
}
}
}else{
userElement.Act_on_Facts_Eligible__c = true;
}
logDetail += ' userElement.Act_on_Facts_Eligible__c: '+userElement.Act_on_Facts_Eligible__c;
ApplicationLog.logEntry(ApplicationLog.SEVERITY_INFO, 'A2WBatch', 'GEN_ActonFactsScoreUserEligibleBatch:'+userElement.id+': ', logDetail);
newUserList.add(userElement);
}
try{
if(newUserList.size()>0){
update newUserList;
system.debug('HC Update- newUserList ' + newUserList);
}
if(actOnFactDelete.size()>0){
delete actOnFactDelete;
system.debug('HC Update- actOnFactDelete ' + actOnFactDelete);
}
}catch (Exception e){
system.debug('Error updating user ' + e);
}
}
}
Code for GEN_ActonFactsScoreUserEligibleBatch.execute-
global void execute(Database.BatchableContext BC, List<sObject> scope){
CSH_A2W_Settings__c a2wCS = CSH_A2W_Settings__c.getInstance();
if(scope != null){
List<User> userList = scope;
if(userList.size()>0){
if(CSL_ActOnFactsLimits__c.getValues('run_userTrigger') != null){
CSL_ActOnFactsLimits__c run_userTrigger = CSL_ActOnFactsLimits__c.getValues('run_userTrigger');
run_userTrigger.Value__c = 'false';
update run_userTrigger;
}
//GEN_CalculateActOnFactsScores.calcUserEligible(userList); //Commented as part of Decommission activity of AoF
if(a2wCS != null && a2wCS.Enabled_in_Batches__c == True){
GEN_CalculateActToWinScores.calcUserEligible(userList);
}
}
}
}
I am trying to analysis what will be the best possible ways to remove these errors or is there any alternate way to implement the same.
All these are queries in a loop:
for (User userElement : usersList){
...
List<Act_on_Facts__c> actonfacts = [select id from Act_on_Facts__c where Lookup_User__c = : userElement.id limit 1];
...
countResult = [select count() from Account WHERE OwnerId = :userElement.id LIMIT :limitQuery];
...
[select count() from Opportunity WHERE OwnerId = :userElement.id AND StageName IN:oppOpenStageNameSet AND RecordType.DeveloperName NOT IN: oppReadOnlyRecordTypeNameSet LIMIT :limitQuery];
As a very quick & dirty solution you can change the batch's size (how many records are passed to each execute). Default is 200.
Call your class with optional parameter Database.executeBatch(new GEN_ActonFactsScoreUserEligibleBatch(), 10); and see if it helps.
"Proper" fix would require some restructuring, taking queries out of the loop, maybe using some Maps where user's id is the key...
If these were custom objects a "pro" Apex developer would cheat, make these queries in one go, pulling user and related lists, something like
SELECT Id,
(SELECT Id FROM Accounts__r LIMIT 1),
(SELECT Id FROM Opportunities__r WHERE ... LIMIT 1),
(SELECT Id FROM Act_On_Facts__r)
FROM User
WHERE Id IN :scope
This won't work here because relation from Account to owner doesn't have a nice name ("Accounts" won't work). You should be still able to do it on the custom object (last subquery in my example, you can call it outside of the loop)
You might still be able to pull something like that off but it'd probably require looking at sharing-related tables... I'd say doable but if you have time to play with it. If you don't - change scope size and call it a day. Will execute bit longer but 1-liner fix is a win in my book.

Inline T-SQL OR subquery

Trying to figure out what would be the most efficient approach to use a subquery in an inline SQL statement. Inline SQL is not something I have much experience with, but I have no choice at my organization alas.
SELECT *
FROM dbo.VW_RMISPayment
WHERE ProcDate BETWEEN '7/2/2018' AND '3/8/2019'
AND Status = 'P'
AND Fund = '359'
AND Amount > 0
AND (BatchNotate = 'B' OR BatchNotate IS NULL)
ORDER BY ProcDate, Amount
How could I parameterized the (BatchNotate = 'B' OR BatchNotate IS NULL) part?
My variable passed in as a List<string>, but I could change it to be anything. I'm just not sure how I can create this subquery from my variable
if (BatchNotate.Count() > 0)
{
query += " AND BatchNotate= #BatchNotate";
}
cmd.Parameters.AddWithValue("#BatchNotate", batchNotate);
Use this:
BatchNotate = COALESCE(#inVariable,'B')
If the variable (#inVariable) is null then it will "default to B.
If it is something else it will compare against that.
Could you do something like this?
SELECT *
FROM dbo.VW_RMISPayment
WHERE ProcDate BETWEEN '7/2/2018' AND '3/8/2019'
AND Status = 'P'
AND Fund = '359'
AND Amount > 0
AND BatchNotate = COALESCE(#BatchNotate, BatchNotate)
ORDER BY ProcDate, Amount
Neither of those worked for what I'm after. Here is what I ended up doing. It's kinda hacky, but it works.
public static string AddParametersOR<T>(SqlParameterCollection parameters,
string fieldName,
string pattern,
SqlDbType parameterType,
int length,
IEnumerable<T> values)
{
if (parameters == null)
throw new ArgumentNullException("parameters");
if (pattern == null)
throw new ArgumentNullException("pattern");
if (values == null)
throw new ArgumentNullException("values");
if (!pattern.StartsWith("#", StringComparison.CurrentCultureIgnoreCase))
throw new ArgumentException("Pattern must start with '#'");
var parameterNames = new List<string>();
foreach (var item in values)
{
var parameterName = parameterNames.Count.ToString(pattern, CultureInfo.InvariantCulture);
string parameterWithFieldName = string.Empty;
if (item.ToString().ToUpper() == "NULL")
{
parameterWithFieldName = string.Format("{0} IS NULL", fieldName);
}
else if (item.ToString().ToUpper() == "NOTNULL")
{
parameterWithFieldName = string.Format("{0} IS NOT", fieldName);
}
else
{
parameterWithFieldName = string.Format("{0}= {1}", fieldName, parameterName);
}
parameterNames.Add(parameterWithFieldName);
parameters.Add(parameterName, parameterType, length).Value = item;
}
return string.Join(" OR ", parameterNames.ToArray());
}
Usage:
if (batchNotate.Count() > 0)
{
query += " AND ({#BatchNotate})";
}
string batchNotateParamNames = SqlHelper.AddParametersOR(cmd.Parameters, "BatchNotate", "#B0", SqlDbType.VarChar, 1, batchNotate);
cmd.CommandText = query.Replace("{#BatchNotate}", batchNotateParamNames);
Depending on how many items are in your list the output will look like this:
(BatchNotate= 'B' OR BatchNotate= 'N' OR BatchNotate IS NULL)
If it finds "NULL" or "NOTNULL" it will replace these with IS NULL or IS NOT NULL

android sqlite group query error:android.database.CursorIndexOutOfBoundsException:

My query in android sqlite is given below
MY column name topic,correct_answer and total_mark,test_id
MY database name no_question_list
My query given here
String query = "SELECT topic,SUM(correct_answer),SUM(total_mark) from no_question_list Where test_id='" + test_id + "'" + "group by topic,correct_answer,total_mark";
Cursor c = database.rawQuery(query , null);
if (c != null) {
if (c.moveToFirst()) {
do {
topic= c.getString(0);
}
while (c.moveToNext());
}
}
When i execute the query no error when getting error in value of Cursor
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.stepone.netquestion/com.stepone.netquestion.ResultActivity}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
and i tried this cursor part,it doest execute
if (c != null) {
if (c.moveToFirst()) {
do {
String topic =c.getString(c.getColumnIndex("topic"));
}
while (c.moveToNext());
}
thank for answer in advance
I do not think you need this test if(c != null) try this code
public String getCol_MPW(){
db = getReadableDatabase();
String q = "SELECT * FROM masterPW";
Cursor cursor = db.rawQuery(q,null);
if(cursor.moveToFirst()){
int i = cursor.getInt(cursor.getColumnIndex(Col_IDI));
str = cursor.getString(cursor.getColumnIndex(Col_MPW));
}
cursor.close();
db.close();
return str;
// This routine called from MainActivity determine's if a
// password has been entered in the db table named "TABLE_PW"
// See onLoad() method in MainActivity
}

Returning value from a recursive function involving Promise

I am trying to return value from a recursive function involving Promises.
Here's the example method:
getRecursionValue = function(count, i, num, isFound) {
if (i < count && !isFound) {
somePage.someNum.then(function(numVal) {
if (numVal == num) {
console.log('Matched at index: ' + i);
<RETURN VALUE OF I>
} else {
element(by.css('css.for.next.link')).click();
utils.getRecursionValue(count, i + 1, num, false);
}
});
}
}
I am not able to return the value of 'i' correctly! Any suggestions for a way to achieve this?
Thanks,
Sakshi
You are returning from inside a promise but the promise in turn returns nothing to the function. You can solve this by returning the first promise which will in turn return the value of i:
getRecursionValue = function(count, i, num, isFound) {
if (i < count && !isFound) {
return somePage.someNum.then(function(numVal) {
if (numVal == num) {
console.log('Matched at index: ' + i);
<RETURN VALUE OF I>
}