Transferring Data from dropdowns and numeric entry fields to a query table

Was a solution reached on this account? I am trying to do something similar, but I am only getting NULL as a result. Unless I am missing something, I have all the necessary names matching between my update query, params, and script.

This is my 'onActionPerformed' script for my button.

def runAction(self, event):
	
	
	personPerformingWork = self.getSibling("PPW Dropdown").props.value
	firewatch1 = self.getSibling("FW1 Dropdown").props.value
	firewatch2 = self.getSibling("FW2 Textfield").props.text
	area = self.getSibling("AOW Textfield").props.text
	typeOfWork = self.getSibling("TOW Textfield").props.text
	approvedBy = self.getSibling("AB Dropdown").props.value
	expirationDate = self.getSibling("DateTimeInput").props.value
	timeInitiated = self.getSibling("DateTimeInput_0").props.value
	timeFinished = self.getSibling("TF DateTime Picker").props.value
	
	params = {
		personPerformingWork : personPerformingWork,
		firewatch1 : firewatch1,
		firewatch2 : firewatch2,
		area : area,
		typeOfWork : typeOfWork,
		approvedBy : approvedBy,
		expirationDate : expirationDate,
		timeInitiated : timeInitiated,
		timeFinished : timeFinished
	}
	
	system.db.runNamedQuery("updateHotWorkRecordsTable", params)

Here is the query I made to create my db table:

CREATE TABLE hotWorkPermitRecords (
	personPerformingWork TEXT,
	firewatch1 TEXT,
	firewatch2 TEXT,
	area TEXT,
	typeOfWork TEXT,
	approvedBy TEXT,
	expirationDate DATETIME,
	timeInitiated DATETIME,
	timeFinished DATETIME)

Here is the query I made to insert the relative info I need.

INSERT INTO hotWorkPermitRecords (personPerformingWork, firewatch1, firewatch2, area, typeOfWork, approvedBy, expirationDate, timeInitiated, timeFinished)
	VALUES( :personPerformingWork, :area, :typeOfWork, :approvedBy, :expirationDate, :firewatch1, :firewatch2, :timeInitiated, :timeFinished) 

Here are the params I set up.

I am getting NULL on my rows.

Any input would be appreciated. Thanks!

Here are the screenshots.

Your code has a subtle but critical flaw.

	params = {
		personPerformingWork : personPerformingWork,
		firewatch1 : firewatch1,
		firewatch2 : firewatch2,
		area : area,
		typeOfWork : typeOfWork,
		approvedBy : approvedBy,
		expirationDate : expirationDate,
		timeInitiated : timeInitiated,
		timeFinished : timeFinished
	}

This is instantiating a dictionary (good) but your keys and values are the same - the actual values read from those properties. You need to create literal strings to use as your keys, by wrapping the keys in single or double quotes.

My personal preference, without any dramatic restructuring of anything else, would be to write your script like this:

def runAction(self, event):
    params = {
        "personPerformingWork": self.getSibling("PPW Dropdown").props.value,
        "firewatch1": self.getSibling("FW1 Dropdown").props.value,
        "firewatch2": self.getSibling("FW2 Textfield").props.text,
        "area": self.getSibling("AOW Textfield").props.text,
        "typeOfWork": self.getSibling("TOW Textfield").props.text,
        "approvedBy": self.getSibling("AB Dropdown").props.value,
        "expirationDate": self.getSibling("DateTimeInput").props.value,
        "timeInitiated": self.getSibling("DateTimeInput_0").props.value,
        "timeFinished": self.getSibling("TF DateTime Picker").props.value
    }

    system.db.runNamedQuery("updateHotWorkRecordsTable", params)
2 Likes

I tried your script and it stopped writing to the table all together, however, i did go back and write this

def runAction(self, event):

   	personPerformingWork = self.getSibling("PPW Dropdown").props.value
   	firewatch1 = self.getSibling("FW1 Dropdown").props.value
   	firewatch2 = self.getSibling("FW2 Textfield").props.text
   	area = self.getSibling("AOW Textfield").props.text
   	typeOfWork = self.getSibling("TOW Textfield").props.text
   	approvedBy = self.getSibling("AB Dropdown").props.value
   	expirationDate = self.getSibling("DateTimeInput").props.value
   	timeInitiated = self.getSibling("DateTimeInput_0").props.value
   	timeFinished = self.getSibling("TF DateTime Picker").props.value
   		
   	params = {
   		personPerformingWork : "personPerformingWork",
   		firewatch1 : "firewatch1",
   		firewatch2 : "firewatch2",
   		area : "area",
   		typeOfWork : "typeOfWork",
   		approvedBy : "approvedBy",
   		expirationDate : "expirationDate",
   		timeInitiated : "timeInitiated",
   		timeFinished : "timeFinished"
   		}
   		
   	system.db.runNamedQuery("updateHotWorkRecordsTable", params)

but it is still giving me NULL results. I am not sure if I misunderstand what you tried to tell me or if I am missing something obvious.

I have also been stuck in pretty much the same spot as you for a day or two now.

1 Like

You, did exactly the opposite of what @PGriffith was pointing out.

Your script, should have String Keys, and the values can then be variable.

It should be:

params = {
   		"personPerformingWork" : personPerformingWork,
   		"firewatch1" : firewatch1,
   		"firewatch2" : firewatch2,
   		"area" : area,
   		"typeOfWork" : typeOfWork,
   		"approvedBy" : approvedBy,
   		"expirationDate" : expirationDate,
   		"timeInitiated" : timeInitiated,
   		"timeFinished" : timeFinished
}

Where are you calling this script from?

2 Likes

I guess that would explain why @PGriffith script wasn't writing to my table. I have corrected my mistake and it still does not write to the table. I am calling this script from a submit button pictured below upon its activation.

Justin, I know this isn't the problem you're trying to solve right now but the UI needs some polish.

  • Use green and red for status if really needed but not for buttons.
  • You'll never see underline in a professionally designed user interface (or in newspapers, magazines, books, adverts, etc.) except for hyperlinks or some unusual requirement. For GUI applications the underline might be applied to one character to signify the Alt-hotkey for that command. You've applied it to the button and checkbox captions.
  • You have five or six different typeface sizes. Why?
  • Checkboxes are normally to the left of their labels. Why do you have the labels above the checkboxes? Why are they underlined?
  • What does red signify for the checkboxes? Is it indicating a problem?
  • Why is the 1st Firewatch Timer in red? Is there a problem with that?
    Use color sparingly, consistently and with purpose.

Most of the issues could be sorted out by removing the applied styles and using Ignition's defaults.

See my example to Tyler in the post above.

1 Like

I agree it isn't the prettiest, just waiting to finalize the end design when I can get it working properly and inserting the data to the table. I will keep your suggestions in mind.

1 Like

So you're inserting a row with all null values?

What event are you using to fire this script, how is the button configured?

This is currently what I have and still can't get anything to load at all unless I execute the query in the browser and then it gives me a row of 0's. I unbound my custom properties as a resort to see if something there was set up wrong and I could go back to custom properties after I debugged. I've tried adding print statements to debug but can't get anything to show up when I run my script. I matched all of my names to be the exact same in every single area to prevent simple errors.

onActionPerformed script on my submission button:


def runAction(self, event):

 # Fetch values from your Perspective components
   Code = self.getSibling("Code").props.value
   EmployeeNumber = self.getSibling("EmployeeNumber").props.value
   DowntimeMinutes = self.getSibling("DowntimeMinutes").props.value
    # Generate the current timestamp using Ignition's built-in function
    tStamp = system.date.now()

    # Prepare parameters for the named query
    params = {
        "Code": Code,
        "EmployeeNumber": EmployeeNumber,
        "DowntimeMinutes": DowntimeMinutes,
        "tStamp": tStamp
    }

    # Run the named query to insert data into the downtime_data table
    system.db.runNamedQuery("InsertDowntimeData", params)

As I said earlier:

I just mocked up a test. If I try to insert a Date into a Real column, I get a ClassCastException. If I try to insert the Miilis into an Integer I get an overflow error.

I'm sure you're getting an error somewhere.

If what you want in the database is a Date, then you should change the datatype in the Database to either datetime or datetime2 depending on if you need it to be TZ aware or not. And you should change the datatype of the tStamp parameter in the named query to a DateTime.

If for whatever reason you must use a Real datatype for the tStamp, then you should change the DataType of the parameter in the Named Query to float4 and use system.date.toMillis() in the script to convert system.date.now() into a millisecond representation.

Obviously the datetime option is the preferred practice.

The code as you have it wouldn't even let me run the query.

com.inductiveautomation.ignition.common.script.JythonExecException
Traceback (most recent call last):
  File "<function:runAction>", line 9, in runAction
	at com.inductiveautomation.ignition.gateway.db.namedquery.NamedQueryExecutor$NamedQueryInstance.execute(NamedQueryExecutor.java:407)
	at com.inductiveautomation.ignition.gateway.db.namedquery.NamedQueryExecutor.execute(NamedQueryExecutor.java:173)
	at com.inductiveautomation.ignition.gateway.db.namedquery.GatewayNamedQueryManager.execute(GatewayNamedQueryManager.java:92)
	at com.inductiveautomation.ignition.common.db.namedquery.SecuredNamedQueryManager.execute(SecuredNamedQueryManager.java:78)
	at com.inductiveautomation.ignition.gateway.script.GatewayDBUtilities.runNamedQuery(GatewayDBUtilities.java:419)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
java.lang.Exception: java.lang.Exception: java.lang.ClassCastException: Cannot coerce value 'Tue Mar 12 17:25:30 EDT 2024' into type: class java.lang.Integer

	at org.python.core.Py.JavaError(Py.java:545)
	at org.python.core.Py.JavaError(Py.java:536)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:192)
	at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction.__call__(ScriptManager.java:553)
	at org.python.core.PyObject.__call__(PyObject.java:477)
	at org.python.core.PyObject.__call__(PyObject.java:481)
	at org.python.pycode._pyx824.runAction$1(<function:runAction>:9)
	at org.python.pycode._pyx824.call_function(<function:runAction>)
	at org.python.core.PyTableCode.call(PyTableCode.java:173)
	at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
	at org.python.core.PyFunction.function___call__(PyFunction.java:474)
	at org.python.core.PyFunction.__call__(PyFunction.java:469)
	at org.python.core.PyFunction.__call__(PyFunction.java:464)
	at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:847)
	at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:829)
	at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:868)
	at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:1010)
	at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:950)
	at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:161)
	at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:98)
	at com.inductiveautomation.perspective.gateway.action.ScriptAction.runAction(ScriptAction.java:80)
	at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.lambda$call$0(ActionCollection.java:263)
	at com.inductiveautomation.perspective.gateway.api.LoggingContext.mdc(LoggingContext.java:54)
	at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:252)
	at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:221)
	at com.inductiveautomation.perspective.gateway.threading.BlockingTaskQueue$TaskWrapper.run(BlockingTaskQueue.java:154)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at com.inductiveautomation.perspective.gateway.threading.BlockingWork$BlockingWorkRunnable.run(BlockingWork.java:58)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.python.core.PyException
Traceback (most recent call last):
  File "<function:runAction>", line 9, in runAction
	at com.inductiveautomation.ignition.gateway.db.namedquery.NamedQueryExecutor$NamedQueryInstance.execute(NamedQueryExecutor.java:407)
	at com.inductiveautomation.ignition.gateway.db.namedquery.NamedQueryExecutor.execute(NamedQueryExecutor.java:173)
	at com.inductiveautomation.ignition.gateway.db.namedquery.GatewayNamedQueryManager.execute(GatewayNamedQueryManager.java:92)
	at com.inductiveautomation.ignition.common.db.namedquery.SecuredNamedQueryManager.execute(SecuredNamedQueryManager.java:78)
	at com.inductiveautomation.ignition.gateway.script.GatewayDBUtilities.runNamedQuery(GatewayDBUtilities.java:419)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
java.lang.Exception: java.lang.Exception: java.lang.ClassCastException: Cannot coerce value 'Tue Mar 12 17:25:30 EDT 2024' into type: class java.lang.Integer

	... 32 more
Caused by: java.lang.Exception
com.inductiveautomation.ignition.common.GenericTransferrableException: java.lang.ClassCastException: Cannot coerce value 'Tue Mar 12 17:25:30 EDT 2024' into type: class java.lang.Integer
	at com.inductiveautomation.ignition.gateway.db.namedquery.NamedQueryExecutor$NamedQueryInstance.execute(NamedQueryExecutor.java:407)
	at com.inductiveautomation.ignition.gateway.db.namedquery.NamedQueryExecutor.execute(NamedQueryExecutor.java:173)
	at com.inductiveautomation.ignition.gateway.db.namedquery.GatewayNamedQueryManager.execute(GatewayNamedQueryManager.java:92)
	at com.inductiveautomation.ignition.common.db.namedquery.SecuredNamedQueryManager.execute(SecuredNamedQueryManager.java:78)
	at com.inductiveautomation.ignition.gateway.script.GatewayDBUtilities.runNamedQuery(GatewayDBUtilities.java:419)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)
	... 29 more
Caused by: java.lang.ClassCastException
com.inductiveautomation.ignition.common.GenericTransferrableException: Cannot coerce value 'Tue Mar 12 17:25:30 EDT 2024' into type: class java.lang.Integer
	at com.inductiveautomation.ignition.common.TypeUtilities.coerce(TypeUtilities.java:1627)
	at com.inductiveautomation.ignition.common.TypeUtilities.coerceNullSafe(TypeUtilities.java:877)
	at com.inductiveautomation.ignition.gateway.db.namedquery.NamedQueryExecutor$NamedQueryInstance.coerce(NamedQueryExecutor.java:419)
	at com.inductiveautomation.ignition.gateway.db.namedquery.NamedQueryExecutor$NamedQueryInstance.execute(NamedQueryExecutor.java:384)
	... 38 more

Ignition v8.1.35 (b2023120517)
Java: Azul Systems, Inc. 17.0.8

I'm using an onActionPerformed event script. With the current script changes that were recommended to me above, the script is not firing anymore.

Table in the query browser shown below.

Made the changes. I get a timestamp if I manually execute the query now. Nothing via submit button. Thanks!

Update. I just tried to fire my update query via the testing tab on the named query, and I am getting this error.

GatewayException: com.microsoft.sqlserver.jdbc.SQLServerException: Operand type clash: datetime2 is incompatible with text
caused by Exception: com.microsoft.sqlserver.jdbc.SQLServerException: Operand type clash: datetime2 is incompatible with text

Ignition v8.1.32 (b2023091211)
Java: Azul Systems, Inc. 11.0.18

Does this mean my DateTime Input Components for selecting the dates on my page using text instead of the DateTime format?

You need to change the data type of the tStamp parameter to DateTime

Yes, you’re sending a string value instead of a date object. I’m away from my computer atm, so can’t get details.

I'm going to be honest. I don't know why this is what made things work. I added print statements before and after one of my parameters to try to debug and behold it works via the click of my submit button now.

def runAction(self, event):

    # Fetch values from your Perspective components
    print("Starting runAction function")
    Code = self.getSibling("Code").props.value
    print("code:", Code)
    EmployeeNumber = self.getSibling("EmployeeNumber").props.value
    DowntimeMinutes = self.getSibling("DowntimeMinutes").props.value
    
    # Generate the current timestamp using Ignition's built-in function
    tStamp = system.date.now()  # system.date.now() already returns a timestamp in milliseconds
    
    # Prepare parameters for the named query
    params = {
        "Code": Code,
        "EmployeeNumber": EmployeeNumber,
        "DowntimeMinutes": DowntimeMinutes,
        "tStamp": tStamp
    }

    # Run the named query to insert data into the downtime_data table
    system.db.runNamedQuery("InsertDowntimeData", params)

image

Finally got it printing to the table. My issue should have been obvious to me, but I did not notice it until I looked over everything once again, I just want to make the thread aware in case someone else has the same issue. My whole issue was the order of my parameters on my update query.

Before:

After:

Thanks for everyone's help in the thread.

4 Likes