ColdFusion processing a form more efficiently and a minor error - forms

I have a form processing that I am sure can be done more efficiently and there is an error in the result set although not "life threatening" just not correct.
The purpose of the page is to associate an item with a program and at the same time associate a designation within the program -- B and F fields are checkboxes allowing the item to be associated with multiple programs and designations within that specific program. (edited for clarity)
Example:
Item: Lightsaber
Program: Jedi Training
Designation: Tool(b) (yes)
Designation: Weapon(f) (no)
Program: Jedi Master
Designation: Tool(b) (yes)
Designation: Weapon(f) (yes)
Program: Smuggler
Designation: Tool(b) (no)
Designation: Weapon(f) (no)
Form:
<form action="#CGI.SCRIPT_NAME#" method="post" name="program">
<label>Item</label>
<select id="item" name="item">
<!---//loop through and display items --->
<cfloop query="getitems">
<option value="#itemid#">#itemname#</option>
</cfloop>
</select>
<table>
<!---//loop through and display programs --->
<cfloop query="getprogram">
<tr>
<td>#programname#</td>
<td><input type="checkbox" id="B#programid#" name="B#programid#"></td>
<td><input type="checkbox" id="F#programid#" name="F#programid#"></td>
</tr>
</cfloop>
</table>
<input type="submit">
</form>
Action Page:
<!---// is there is a form being processed --->
<cfif #CGI.REQUEST_METHOD# is 'post'>
<!---// create program list from query --->
<cfset pl = ValueList(query.var, ','>
<!---// set addtl form var's --->
<cfset listassid = 'form.item'>
<!---// loop over program list --->
<cfloop list="#pl#" index="i">
<!---// loop over form fields --->
<cfloop list="form.fieldnames" index="field">
<cfif #field# EQ 'B'&#i#>
<!---// if field is B and var, set designation true --->
<cfset b = 1>
<cfelse>
<!---// it's not, set to null --->
<cfset b = 'null'>
</cfif>
<cfif #field# EQ 'F'&#i#>
<!---// if field is F and var, set designation true --->
<cfset f = 1>
<cfelse>
<!---// it's not, set to null --->
<cfset f = 'null'>
</cfif>
<cfif b EQ 'null' AND f EQ 'null'>
<!---// if both are null then skip --->
//do nothing
<cfelse>
<!---//insert record into table --->
insert into table (table fields)
(#i#, #listassid#, #b#, #f# )
</cfif>
</cfloop>
</cfloop>
</cfif>
The result should be:
id item_id program_id B F
1 24 1 x
2 32 2 x x
The actual result is:
id item_id program_id B F
1 24 1 x
2 32 2 x
3 32 2 x
Thank you in advance for any clarification and efficiencies you can suggest.

I think a slightly different naming convention would help resolve the current issue, and improve the readability of the code.
One option is to store all of the project id's in a hidden form field. Be sure to use the same "name", so the id's are submitted as a CSV list. Also, I would recommend more meaningful names for the checkboxes, to improve readability. For example, "isSomething" rather than just "B" or "F":
<select id="item" name="itemID">
<cfoutput query="getitems">
<option value="#itemid#">#itemname#</option>
</cfoutput>
</select>
...
<cfoutput query="getPrograms">
<input type="hidden" name="programIDList" value="#programID#">
...
<!--- Set checkbox values to 1 / Yes --->
<td><input type="checkbox" name="isTool_#programID#" value="1"></td>
<td><input type="checkbox" name="isWeapon_#programID#" value="1"></td>
...
</cfoutput>
When the form is submitted, loop through the list of project id's and use the current id to extract the values of each set of checkboxes. If either box was checked, insert a record into the database.
* Note: Checkboxes are only submitted when "checked". Before accessing the field, either use structKeyExists to verify the field exists OR use cfparam to set a default value for the field.
<!--- Loop through list of available program id's --->
<cfloop list="#form.programIDList#" index="variables.programID">
<!--- Ensure fields exist. Set default value = 0 / No --->
<cfparam name="form.isTool_#variables.programID#" default="0">
<cfparam name="form.isWeapon_#variables.programID#" default="0">
<!--- Extract the current values --->
<cfset variables.isTool = FORM["isTool_"& variables.programID ] >
<cfset variables.isWeapon = FORM["isWeapon_"& variables.programID ] >
<!--- DEBUG ONLY: Display current values --->
<cfoutput>
<hr>variables.programID = #variables.programID#
<br>variables.isTool = #variables.isTool#
<br>variables.isWeapon = #variables.isWeapon#
<br>form.itemID = #form.itemID#
</cfoutput>
<!--- If either box was checked, save to database --->
<cfif variables.isTool || variables.isWeapon>
... run cfquery here
</cfif>
</cfloop>
Two important notes about database queries:
Never use raw client values in SQL. Instead use cfqueryparam. It helps protects your database against sql injection. It also improves query performance when a statement is executed multiple times (as in this case)
When executing multiple (related) queries, be sure to wrap them in a cftransaction to ensure consistency, ie All statements succeed or fail as a unit.

Related

T-SQL SUBSTRING with CHARINDEX AS LENGTH part is returning too much text

I have ploughed through the massive amount of queries on here relating to SUBSTRING and CHARINDEX but I cannot find one that answers my query.
I am extracting a single part of a long piece of text but it is returning 48 characters too much. E.g. in the first row of the results the length should be 44 characters rather than the 92 characters it is giving. I split out the various parts of the query into the last 3 columns to get the starting position and the length but when I put it together it doesn't work correctly. What am I doing wrong?
My code: (Updated to make consumable I hope)
IF OBJECT_ID('tempdb.dbo.#WQuery', 'U') IS NOT NULL
DROP TABLE #WQuery
CREATE TABLE #WQuery
(
IncidentID VARCHAR(100),
Description VARCHAR(250),
)
INSERT INTO #WQuery
(IncidentID, Description)
VALUES
('B209BBA0-9039-ED11-81AD-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />New to export (less than 1 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />United Kingdom<br /><br />'),
('13A75070-0F38-ED11-81AD-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />Novice exporter (1-3 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />Kazakhstan <br /><br />'),
('D2926CA8-EB28-ED11-81AC-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />New to export (less than 1 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />Zambia (central Africa)<br/'),
('7226B826-DF24-ED11-81AC-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />Experienced exporter (3+ years experience in multiple markets)<br /><br /><b>What is the destination market for your goods/services?</b><br />Spain<br'),
('E636692C-3C22-ED11-81AC-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />New to export (less than 1 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />India<br /><br />'),
('C13937A0-EF16-ED11-81AC-0050569FE3BD','<b>Please indicate your company''s export status:</b><br />New to export (less than 1 years experience)<br /><br /><b>What is the destination market for your goods/services?</b><br />Rotterdam<br /><br /><b>')
;
select
i.incidentid
, i.description
, SUBSTRING(i.description,
CHARINDEX('export status:</b><br />', i.description)+LEN('export status:</b><br />'),
CHARINDEX('<br /><br /><b>What is the destination market',i.description) - (CHARINDEX('export status:</b><br />', i.description)-LEN('export status:</b><br />')) ) As ExportStatus
--substring(string,start,length)--
--length is the number of characters to extract - must be positive--
--split the substring above to test the values--
,CHARINDEX('export status:</b><br />', i.description)+LEN('export status:</b><br />') as start
,CHARINDEX('<br /><br /><b>What is the destination market',i.description) as secondQStart
,CHARINDEX('<br /><br /><b>What is the destination market',i.description) - CHARINDEX('export status:</b><br />', i.description)-LEN('export status:</b><br />') as length
--charindex(substring,string,start)--
from #WQuery i
DROP TABLE #WQuery;
The expected results for column 3 (export status) should be:
However I am getting this:
When I added the code from the column 'Length' into the parameter of the SUBSTRING query it gave an error.
Msg 537, Level 16, State 3, Line 3
Invalid length parameter passed to the LEFT or SUBSTRING function.
When I added the brackets around that part of the SUBSTRING the query ran but as you can see it is not returning the same number of characters and the 'length' in the last column.
I am struggling to understand why the length parameter in the SUBSTRING query is not working the same as the same code in the 'length' column. And I also do not understand why the code needs brackets in the parameter of SUBSTRING query to work or throws the error.
Your text is almost valid XHTML. You just need to fix up the ends of the lines in some cases, I assume this is a copy-paste error.
For example, <br />Spain<br should be <br />Spain<br />, and Rotterdam<br /><br /><b> should be Rotterdam<br /><br /><b />.
Now you can just use XQuery to get the right piece of text, which appears to be the first text not enclosed by any node.
SELECT ExportStatus = CAST(wq.Description AS xml).value('(/text())[1]', 'nvarchar(max)')
FROM #WQuery wq
db<>fiddle

Show Calculated fields on New and Edit Form of SharePoint 2013 List Form

I have a SharePoint List with some columns. I have following scenario:
ColA: Test1, Test2, Test3
ColB: 0, 10, 55
ColC: $0, $12, $60
Col A is a dropdown. Col B and C are calculated fields. Based on the value selected in ColA, ColB and ColC values will be auto populate.
Since ColB and C are calculate columns, they are displayed in the list as well as in SharePoint display form. I want to show ColB and C fields in read only mode on SharePoint new and Edit form for users. I am using SharePoint List form not Infopath form.
Looking for suggestions to achieve this functionality.
You could use jquery to append readonly input to work as lookup column.
Here is simple demo script for your reference, you need update the update logic based on your logic.
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript">
$(function () {
var lookupValue = $('input[title="TxTField"]').val();
$('table.ms-formtable').append('<tr id="LookupColumnTR"><td class="ms-formlabel" nowrap="true" valign="top"><h3 class="ms-standardheader"><nobr>LookupColumn</nobr></h3></td><td><input disabled="disabled" type="value" value="' + lookupValue + '" class="text_box" /></td></tr>');
$('input[title="TxTField"]').change(function () {
var lookupValue = $(this).val();
$('table.ms-formtable tr#LookupColumnTR').remove();
$('table.ms-formtable').append('<tr id="LookupColumnTR"><td class="ms-formlabel" nowrap="true" valign="top"><h3 class="ms-standardheader"><nobr>LookupColumn</nobr></h3></td><td><input disabled="disabled" type="value" value="' + lookupValue + '" class="text_box" /></td></tr>');
})
})
</script>

Unable to set the ID of an instance

What is unique about my situation is that the ID's can not be randomly assigned so I set it's value within the instance. I created several instances of an entity using the modeler. Below is the XML created:
<cf:entity name="Test4" namespace="Amikids.TimeTracking" categoryPath="/Amikids.TimeTracking">
<cf:property name="Id" key="true" typeName="int" />
<cf:property name="Name" />
<cf:instance>
<cf:instanceValue name="Id">10</cf:instanceValue>
<cf:instanceValue name="Name">Test 1</cf:instanceValue>
</cf:instance>
<cf:instance>
<cf:instanceValue name="Id">20</cf:instanceValue>
<cf:instanceValue name="Name">Test 2</cf:instanceValue>
</cf:instance>
<cf:instance>
<cf:instanceValue name="Id">30</cf:instanceValue>
<cf:instanceValue name="Name">Test 3</cf:instanceValue>
</cf:instance>
</cf:entity>
There are 2 things that are not working as expected:
The records inserted do not use the ID specificed in the model/xml. Instead they were created incrementally starting at 1:
(The below is displayed in a code snippet only to prevent StackOverflow from reformatting my list so all records appear on one line)
ID Name
1 Test 1
2 Test 2
3 Test 3
When I build the model a second time duplicate records are inserted.
(The below is displayed in a code snippet only to prevent StackOverflow from reformatting my list so all records appear on one line)
ID Name
1 Test 1
2 Test 2
3 Test 3
4 Test 1
5 Test 2
6 Test 3
Although specifying the ID in the instance does not appear to be work, as a simple work around I created the records using code, which allowed me to specify the ID. This has been verified with the following code snippet.
Amikids.TimeTracking.Test4 test4 = new Amikids.TimeTracking.Test4();
test4.Id = 100;
test4.Name = "Test 100";
test4.Save();
test4 = new Amikids.TimeTracking.Test4();
test4.Id = 200;
test4.Name = "Test 200";
test4.Save();

Send query to CFWheels selectTag form helper, or list with commas in string elements

I have a query that returns names in <lastnamd>, <firstname> format such as
<cfquery name="instructorSelectList" dataSource="GIRSReport">
SELECT instructor_DBID,
last_name + ', ' + first_name as instructor_name,
hid
FROM instructors
WHERE working_status = 'active'
ORDER BY last_name, first_name
</cfquery>
I want to use this query for a selectTag form helper. If I do:
#selectTag
(
name="inst",
id="program",
options="#ValueList(instructorSelectList.instructor_name)#",
valueField="#ValueLIst(instructorSelectList.instructor_DBID)#",
display="#ValueList(instructorSelectList.instructor_name)#",
selected="",
label="HID",
multiple="no",
includeBlank="true",
size=1,
class="form-control",
prepend="<br/>"
)#
Then I get a list like <lastname1>, <firstname1>, <lastname2>, <firstname2>, ...
which is obviously not what I want.
If I just try to pass the options parameter a query, such as options="#instructorSelectList.instructor_name#", the options don't fill properly.
The idea is to use a form helper equivalent to
<cfselect
name="inst"
query="instructorSelectList"
queryPosition="below"
value="instructor_DBID"
display="instructor_name"
label="HID" size=1
class="form-control">
<option value=""></option>
</cfselect>
I think what you're needing is to pass a query name to Options, without quotes (or in quotes surrounded by hashes) while the column names are quoted.
#selectTag
(
name="inst",
id="program",
options=instructorSelectList,
valueField="instructor_DBID",
textField="instructor_name",
selected="",
label="HID",
multiple="no",
includeBlank="true",
size=1,
class="form-control",
prepend="<br/>"
)#
More Info: CFWheels selectTag() documentation

Group by in JPA

My Question is why the GROUP BY didn't show in the glassfish logs.
i added the following data below because someone wants to see it
public List<Message> listAllMessageBySender(String currentUserID) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnit");
EntityManager entityManager = emf.createEntityManager();
TypedQuery<Message> eq = entityManager.createQuery("SELECT m FROM Message m WHERE m.sendBy.userId = :userid GROUP BY m.sendTo.userId", Message.class);
eq.setParameter("userid", Integer.parseInt(currentUserID));
List<Message> message = eq.getResultList();
return message;
}
Glassfish 3.1.2.Logs
FINE: SELECT id, message, send_date, send_by, send_to FROM message WHERE (send_by = ?)
bind => [50]
Data:
User A : sendBy.userId = 50
User B : sendTo.userId = 44
User C : sendTo.userId = 43
id send_date send_by send_to message
1 2013-03-14 14:58:46 44 50 50 send message to 44
2 2013-03-14 14:58:46 50 44 reply from 44 to 50
3 2013-03-14 17:38:52 44 50 2nd reply to 50
6 2013-03-14 18:22:10 50 44 44 reply to 50
7 2013-03-14 18:22:10 50 43 new
in the query above is i want to list all the user sent from User A. it causes duplication because there is two send_to 44. the xhtml below shows :
<ui:repeat value="#{messageController.items}" var="messageItem">
<br />
<div onclick="loadMessage()">
<h:panelGroup layout="block" >
<p:graphicImage height="50" width="50" value="#{messageItem.sendTo.profilePicture}"/>
</h:panelGroup>
<h:panelGroup layout="block" style="width: 270px;">
<h:outputText value="#{messageItem.sendTo.registerName}"/>
<h:panelGroup layout="block" style="float:right;">
<h:outputText value="#{messageItem.sendDate}" >
<f:convertDateTime pattern="HH:mm"/>
</h:outputText>
</h:panelGroup>
</h:panelGroup>
</div>
<p:remoteCommand name="loadMessageBean" action="#{messageController.loadMessage(messageItem.id)}" /> </ui:repeat>
ERD
User Table Message Table
user_id message_id
register_name send_date
send_to ----> referenced by user_id User Table
send_by ----> referenced by user_id User Table
This request doesn't make sense. group by is used when the select clause contains at least one aggregation function (sum, avg, min, max, etc.). And all the other columns must appear in the group by clause.
So for example, the following query would make sense:
SELECT max(m.length), sender.userId from Message m
inner join m.sendBy sender
GROUP BY sender.userId
It would return, for each message sender, the length of its longest message.
Tell us, with example data, what you would like your query to return.
If you want to get all the distinct users whom user A sent a message to, the query should simply be
select distinct m.sendTo from Message m
where m.sendBy.userId = :userid