Update data field in progress 4gl - openedge

Can someone please help me?
All I want to do is update a field in a table, lets say for example membership number if it meets certain conditions.
For example: I have a list of membership numbers. IF the numbers on the list match the membership number in the table - we don't do anything.
If it doesn't match - then we change the membership number to another number that is stored in my input CSV. (i know this sounds back to front, but this is just an analogy)
So in essence I am asking - how do you update a field in a database table? This doesn't seem to be working:
def stream inputStream.
def stream outStream.
def var abcData as char extent 4 no-undo.
def var vl-XYZ# as integer.
def var vl-link# as integer.
def var vl-orig-ABC# as char.
def var vl-new-ABC# as char.
/* def var vl-error as char. */
def var vl-match as char.
def var vl-status as char.
def buffer bMembers for members.
input stream inputStream from "/home/abc.csv".
output stream outStream to "/home/xyz.csv".
export stream outStream delimiter "'" "ABCID" "Match".
repeat:
assign
abcData = "".
import stream inputStream delimiter "'" abcData.
assign
vl-link# = integer(abcdata[1])
vl-XYZ# = integer(abcData[2])
vl-orig-ABC# = string(abcData[3])
vl-new-ABC# = string(abcData[4]) .
for each account no-lock where account.link# = vl-link#,
First members no-lock where members.XYZ# = vl-XYZ#:
if members.abc# = vl-orig-ABC# then
assign
vl-status = "Needs amending".
if members.abc# <> vl-orig-ABC# then
assign
vl-status = "No action needed"
members.abc# = vl-new-ABC#.
export stream outStream delimiter "'" vl-link# vl-XYZ# vl-orig-ABC# members.abc# vl-status
]

The problem with updating the members records will be in the FOR EACH. You need to use EXCLUSIVE-LOCK with the members table to be able to update records.
for each account no-lock where account.link# = vl-link#,
First members EXCLUSIVE-LOCK where members.XYZ# = vl-XYZ#:
The selection criteria for the members table does also not seem to be right, in a joined FOR EACH statement, the second table should depend on the first one like
for each account no-lock where account.link# = vl-link#,
First members EXCLUSIVE-LOCK where members.<somefield of members> = account.<matchine ield in account>
AND members.XYZ# = vl-XYZ#:

Related

Creating a C# List collection equivalent VBscript two dimensional array

VBscript:
arytwoDim(1,intLastBucketBlockIndex) = "08:30 AM" 'TIME
arytwoDim(2,intLastBucketBlockIndex) = 5 'Resource QTY
I would like to create a List collection equivalent to vb array, so that I can mirror the logic with hard coded row,cols.
I tried loading list like this:
List<List<String>> arytwoDim = new List<List<String>>(); //Creates new nested List
arytwoDim .Add(new List<String>()); //Adds new sub List
arytwoDim [1][intLastBucketBlockIndex] = "08:30 AM"; //TIME
arytwoDim [2][intLastBucketBlockIndex] = 5; //Resource QTY
I received this error: 'Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index'
I confirmed that value intLastBucketBlockIndex contains is 0.
Please advise, thank you in advance for your help!

Problems with migration from swift2 to swift3 with ranges

I have strings and determine the ranges of indexes. I will need later for instance .last .count for these ranges. How should I initialise the range for string to be able to get functionality .last .count for these ranges (that is obvious in swift2 but not in swift3) ?
For example, I am often using the .count for range of string in my code in swift2, like this
var str = "Hello, playground"
let myRange = str.rangeOfString("Hello")
let myCountOfRange = myRange.count
Now it is not possible to do this in swift3
var str = "Hello, playground"
let myRange = str.range(of: "Hello")
let myCountOfRange = myRange.count // type index does not conform to protocol strideable
In Swift3, to find the size of a range you can do:
var str = "Hello, playground"
let myRange = str.range(of: "Hello")
let myCountOfRange = str[myRange!].characters.count
I don't know if this is the best way, but it works.
Alternatively:
let myCountOfRange = str.distance(from: myRange!.lowerBound, to: myRange!.upperBound)
Both require access to the original collection (ie. string), and that apparently is a limitation of Swift 3. The new model for collections and indices is discussed here.
If you want to store the ranges in an array and call .count and .last on them, you can convert the Range<Index> to a CountableRange<Int> while you still have access to the collection:
var str = "Hello, playground"
let myRange = str.range(of: "Hello")!
let lb = str.distance(from: str.startIndex, to: myRange.lowerBound) as Int
let ub = str.distance(from: str.startIndex, to: myRange.upperBound) as Int
let newRange = lb..<ub
newRange.count // 5
newRange.last // 4

DynamoDB Xcode6 Swift using three columns as key

I am trying to use a DynamoDB table to store this data:
DartsPlayerInsultTable
CustomerId String
PlayerId String
PlayerInsult String
Using the method (concept, not code) described here:
https://java.awsblog.com/post/Tx3GYZEVGO924K4/The-DynamoDBMapper-Local-Secondary-Indexes-and-You
here:
http://mobile.awsblog.com/post/TxTCW7KW8BGZAF/Amazon-DynamoDB-on-Mobile-Part-4-Local-Secondary-Indexes
and here:
http://labs.journwe.com/2013/12/15/dynamodb-secondary-indexes/comment-page-1/#comment-116
I want to have multiple insult records per customer-player.
CustomerId is my Hash Key
PlayerId is my Range Key
and I a trying to use PlayerInsult in a key so that
a second PlayerInsult value inserts a second record
rather than replacing the existing one.
Have tried both Global and Secondary indexes for this,
but if I try to add a row with a new insult, it still
replaces the insult with the same customer-player key
rather than adding a new one.
Any suggestions on the best approach to use for this is
DynanoDB? Do I need to create a hybrid column for a range-key?
Trying to keep this simple...
class func createDartsPlayerInsultTable() -> BFTask {
let dynamoDB = AWSDynamoDB.defaultDynamoDB()
let hashKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
hashKeyAttributeDefinition.attributeName = "CustomerId"
hashKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S
let hashKeySchemaElement = AWSDynamoDBKeySchemaElement()
hashKeySchemaElement.attributeName = "CustomerId"
hashKeySchemaElement.keyType = AWSDynamoDBKeyType.Hash
let rangeKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
rangeKeyAttributeDefinition.attributeName = "PlayerId"
rangeKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S
let rangeKeySchemaElement = AWSDynamoDBKeySchemaElement()
rangeKeySchemaElement.attributeName = "PlayerId"
rangeKeySchemaElement.keyType = AWSDynamoDBKeyType.Range
/*
let indexRangeKeyAttributeDefinition = AWSDynamoDBAttributeDefinition()
indexRangeKeyAttributeDefinition.attributeName = "PlayerInsult"
indexRangeKeyAttributeDefinition.attributeType = AWSDynamoDBScalarAttributeType.S
let rangeKeySchemaElement = AWSDynamoDBKeySchemaElement()
rangeKeySchemaElement.attributeName = "PlayerId"
rangeKeySchemaElement.keyType = AWSDynamoDBKeyType.Range
let indexRangeKeyElement = AWSDynamoDBKeySchemaElement()
indexRangeKeyElement.attributeName = "PlayerInsult"
indexRangeKeyElement.keyType = AWSDynamoDBIndexRangeKeyType.
*/
//Add non-key attributes
let playerInsultAttrDef = AWSDynamoDBAttributeDefinition()
playerInsultAttrDef.attributeName = "PlayerInsult"
playerInsultAttrDef.attributeType = AWSDynamoDBScalarAttributeType.S
let provisionedThroughput = AWSDynamoDBProvisionedThroughput()
provisionedThroughput.readCapacityUnits = 5
provisionedThroughput.writeCapacityUnits = 5
// CREATE GLOBAL SECONDARY INDEX
/*
let gsi = AWSDynamoDBGlobalSecondaryIndex()
let gsiArray = NSMutableArray()
let gsiHashKeySchema = AWSDynamoDBKeySchemaElement()
gsiHashKeySchema.attributeName = "PlayerId"
gsiHashKeySchema.keyType = AWSDynamoDBKeyType.Hash
let gsiRangeKeySchema = AWSDynamoDBKeySchemaElement()
gsiRangeKeySchema.attributeName = "PlayerInsult"
gsiRangeKeySchema.keyType = AWSDynamoDBKeyType.Range
let gsiProjection = AWSDynamoDBProjection()
gsiProjection.projectionType = AWSDynamoDBProjectionType.All;
gsi.keySchema = [gsiHashKeySchema,gsiRangeKeySchema];
gsi.indexName = "PlayerInsult";
gsi.projection = gsiProjection;
gsi.provisionedThroughput = provisionedThroughput;
gsiArray .addObject(gsi)
*/
// CREATE LOCAL SECONDARY INDEX
let lsi = AWSDynamoDBLocalSecondaryIndex()
let lsiArray = NSMutableArray()
let lsiHashKeySchema = AWSDynamoDBKeySchemaElement()
lsiHashKeySchema.attributeName = "CustomerId"
lsiHashKeySchema.keyType = AWSDynamoDBKeyType.Hash
let lsiRangeKeySchema = AWSDynamoDBKeySchemaElement()
lsiRangeKeySchema.attributeName = "PlayerInsult"
lsiRangeKeySchema.keyType = AWSDynamoDBKeyType.Range
let lsiProjection = AWSDynamoDBProjection()
lsiProjection.projectionType = AWSDynamoDBProjectionType.All;
lsi.keySchema = [lsiHashKeySchema,lsiRangeKeySchema];
lsi.indexName = "PlayerInsult";
lsi.projection = lsiProjection;
//lsi.provisionedThroughput = provisionedThroughput;
lsiArray .addObject(lsi)
//Create TableInput
let createTableInput = AWSDynamoDBCreateTableInput()
createTableInput.tableName = DartsPlayerInsultTableName;
createTableInput.attributeDefinitions = [hashKeyAttributeDefinition, rangeKeyAttributeDefinition, playerInsultAttrDef]
//createTableInput.attributeDefinitions = [hashKeyAttributeDefinition, rangeKeyAttributeDefinition]
createTableInput.keySchema = [hashKeySchemaElement, rangeKeySchemaElement]
createTableInput.provisionedThroughput = provisionedThroughput
//createTableInput.globalSecondaryIndexes = gsiArray as [AnyObject]
createTableInput.localSecondaryIndexes = lsiArray as [AnyObject]
return dynamoDB.createTable(createTableInput).continueWithSuccessBlock({ (var task:BFTask!) -> AnyObject! in
if ((task.result) != nil) {
// Wait for up to 4 minutes until the table becomes ACTIVE.
let describeTableInput = AWSDynamoDBDescribeTableInput()
describeTableInput.tableName = DartsPlayerInsultTableName;
task = dynamoDB.describeTable(describeTableInput)
for var i = 0; i < 16; i++ {
task = task.continueWithSuccessBlock({ (task:BFTask!) -> AnyObject! in
let describeTableOutput:AWSDynamoDBDescribeTableOutput = task.result as! AWSDynamoDBDescribeTableOutput
let tableStatus = describeTableOutput.table.tableStatus
if tableStatus == AWSDynamoDBTableStatus.Active {
return task
}
sleep(15)
return dynamoDB .describeTable(describeTableInput)
})
}
}
return task
})
}
Putting this as an answer and not another comment in case it gets long...
It sounds like the average user's insults might fit into a single record. With the disclaimer that I know absolutely nothing about swift, this might at least be something relatively simple. Keep your customer and player keys. Before you persist the insults, turn the whole list into one big string using whatever version of join("|") swift has. When you fetch the record, do a split("|") to get your list back. (Just be a little judicious with your choice of separators, I'm only using "|" as an example, you don't want to choose something that might appear in an insult...)
There's going to be that one user with enough insults to take you over the 400kb object limit. Set a max list size constant in your code -- when you turn your lists into strings to persist them to dynamo, check the player's list length against that limit. If you exceed it, break your list into chunks of that size and use hash and range keys like ("foo", "bar"), ("foo", "bar1"), ("foo", "bar2"), etc. Yes, the first one does not have a bucket number at the end...
When you query for the data, just do a straight query first and assume you'll be in the good case (just "foo" and "bar", no other buckets). When you unpack that first list, check its length. If it's equal to your max list size constant, you know that you got a "bad" user and need to do a range query. That second one can use the hash key "foo" and the range "bar" to "bar9999". You will fetch back all those buckets with that range query. Unpack and concatenate all the lists.
This is a little gory, but it should also ultimately be straight ahead to code up. Hopefully it's still simple enough to hook into the patterns you mentioned.
What I decided to do was make a conventional dynamodb table with just one hash key, but the new hash key is a combined string of:
CustomerId + "|" + PlayerId
It is not too hard to maintain synchrony between players and insults tables because once a player is inserted into the player table, modifying the player name results in a new row being inserted. Thus, insults do not need to be modified if the player name changes. You only need to cleanup insults if a player is deleted.
This update behavior is just the way dynamodb works if you make Player name a hash key, which I did to insure they were unique.

Split the string of a row of datatable in asp.net

I am using asp.net. I am trying to split the data which is in datatable. I have a code sample like this:
{ dt=objErrorLoggingDataAccess.GetErrorDetails(errorID);
string[] stringSeparators = new string[] { "Message" };
string error = dt.Rows[0]["Message"].ToString();
string[] test = error.Split(stringSeparators, StringSplitOptions.None);
string PageName = test[0].ToString();
PageNameLabel.Text = PageName;
stringSeparators=new string[] {HttpContext.Current.Request.Url.ToString()};
error = dt.Rows[0]["Message"].ToString();
test = error.Split(stringSeparators, StringSplitOptions.None);
string Message = test[0].ToString();
MessageLabel.Text = Message;}
in the datatable following data is there:
{....ID.......Message.......................................................................................................................
....1........http://localhost:10489/images/CategoryIcon/images Message : File does not exist. UserName: naresh#naresh.com
....2........http://localhost:10489/images/CategoryIcon/images Message : File does not exist. UserName: iswar#iswar.com}
My problem is: how can I split the Message and store in the label? I want
{http://localhost:10489/images/CategoryIcon/images}
separately and UserName separately and the message separately. How can I do that? By executing the above code I am able to split
{ http://localhost:10489/images/CategoryIcon/images
}
only. How can I split the Message column and store in pageLabel, MessageLabel, UserNamelabel?
I would use a regular expression in this case. Because only by splitting this string looks a little bit to inflexible to me.
I tested your data example against this quick and dirty RegEx:
(?<id>\d+)\.*(?<url>\w+:\/\/[\w#][\w.:#]+\/?[\w\.?=%&=\-#/$,]*)\s*Message\s*:\s*(?<message>.*)UserName:\s*(?<username>([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3}))
It supports valid URLs and EMail patterns.
Regex regex = new Regex(
"(?<id>\\d+)\\.*(?<url>\\w+:\\/\\/[\\w#][\\w.:#]+\\/?[\\w\\.?"+
"=%&=\\-#/$,]*)\\s*Message\\s*:\\s*(?<message>.*)UserName:\\s"+
"*(?<username>([a-zA-Z0-9_\\-\\.]+)#((\\[[0-9]{1,3}\\.[0-9]{1"+
",3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|"+
"[0-9]{1,3}))",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
// Capture the first Match, if any, in the InputText
Match m = regex.Match(InputText);
// Capture all Matches in the InputText
MatchCollection ms = regex.Matches(InputText);
// Test to see if there is a match in the InputText
bool IsMatch = regex.IsMatch(InputText);
// Get the names of all the named capture groups
// I included your fields as groups: id, url, message and username
string[] GroupNames = regex.GetGroupNames();
I don't know how often you need to call this code. Maybe you get in performance troubles if you have too much data. This regex is q&d - please adjust it to your needs.

Create a VB.NET Array with two columns of values?

I know how to create an array and loop through it normally - but what if I need a multi-column array. e.g. usually I might do something like:
For Each row in NameofArray
Dim name as String = row
Response.Write("Hello " & name & "!")
Next
But what if I want to do something like:
For Each row in NameofArray
Dim name as String = row.name
Dim age as Integer = row.age
Response.Write("Hello " & name & "! You are " & age & " years old!"
Next
If this isn't possible with an array, is there another way I can accomplish this?
Create your custom data type:
public struct DataType
public string Name;
public int Age;
}
Such type you can than use in an array like that:
DataType[] myData = new DataType[100];
myData[0].Name = "myName";
myData[0].Age = 100;
Note, if looping through that array via foreach, the elements returned for each iteration cannot get altered. If this is an requirement for you, consider using 'class' rather than 'struct' in the above DataType declaration. This will come with some other implications though. For example, the instances of a class DataType will explicitely have to be created via the 'new' keyword.
After reading your comment I think my other answer is probably what you are looking for.
What type is row and what type is NameOfArray?
If you would like to make row into a coumpound type with several members then there a several options.
Structure Row
Public Name as String
Public Age as Integer
End Structure
for instance. If you would prefer a reference type substitute Class for Structure.
Or using anonymous types,
Dim row = New With {Name = "Bob", Age = 21}
Then you can use generics to make a list of rows that you can iterate through using ForEach.
Dim NameOfList As System.Collections.Generic.List(of Row)
or if it were a result of a LINQ query somthing that supported
IEnumerable(of New With{Name As String, Age As Int}). //Not sure if this is VB
I'm not certain I uderstand your question and hope this is the kind of thing you were looking for.
As you can see from my fellow answerers, the support for anonymous types is superior in C# but, since you asked the question in VB.Net I will limit myself to that context.
After reading your comment I think I understand the question.
You can do
///Spacer Top
Dim NameOfArray = {New With {.Age = 21, .Name = "Bob"}, New With {.Age = 74, .Name = "Gramps"}}
///Spacer Bottom
If you want to create an IEnumberable anonymous type of Name Age tuples ;-p
Did you tried Dictionary Class. You can loop through the Dictionary using KeyValue pair class.
// Create a new dictionary of strings, with string keys.
//
Dictionary<string, string> openWith =
new Dictionary<string, string>();
// Add some elements to the dictionary. There are no
// duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");
foreach(var item in openWith)
{
Console.WriteLine(item.Key +" can be open with " + item.value);
}
You need to (can) index into your array using the two dimensions ie...
Dim array(,) As Object = { _
{"John",26}, _
{"Mark",4} _
}
For row As Integer = 0 to array.GetUpperBound(0)
Dim name as String = CStr(array(row,0))
Dim age as Integer = CInt(array(row,1))
Response.Write("Hello " & name & "! You are " & age & " years old!")
Next
Though would be better storing this sort of information in a class or user defined type of some kind.

Resources