I'm brand new to Lua/LuaPlus and trying to figure out how metatables work.
In this code taken from the manual:
LuaObject metaTableObj = state->GetGlobals().CreateTable("MultiObjectMetaTable");
metaTableObj.SetObject("__index", metaTableObj);
metaTableObj.RegisterObjectFunctor("Print", &MultiObject::Print);
In the first line we create a new table, but the second line is a little confusing. In this table we just created, we are setting the element with key __index equal to the table itself. Why is __index chosen as a key and why set an element of the table to be equal to the table itself?
And then in the next section of code:
MultiObject obj1(10);
LuaObject obj1Obj = state->BoxPointer(&obj1);
obj1Obj.SetMetaTable(metaTableObj);
state->GetGlobals().SetObject("obj1", obj1Obj);
We create a C++ object, associate its address with a LuaObject via the BoxPointer call, and set the metatable so that we can use the Print function.
But for the last line, is that just creating a global Lua variable called "obj1"? At this point "obj1" and "MultiObjectMetaTable" will be global Lua variables?
This is not standard Lua, it looks like you're using some C++ wrapper that I'm unfamiliar with, but I can make some guesses
In the first line we create a new table, but the second line is a
little confusing. In this table we just created, we are setting the
element with key __index equal to the table itself. Why is __index
chosen as a key and why set an element of the table to be equal to the
table itself?
__index is a special key when using metatables. If I have a table t and I try to index into it with a key of foo for example, naturally, I'll get back the value associated with that key. But lets say there's nothing there. Normally if you try to index into a spot that has nothing, you'll get nil back.
But not if you have a metatable with the special key __index in it! If you have a metatable with an __index function or table, it'll use that to find you your value. If you have a table assigned to __index as you do here, it'll look into that table and return the value at the key you provided. This allows you get inheritance-like behavior. i.e. if table t doesn't have this value, default to the value in this other table instead.
But for the last line, is that just creating a global Lua variable called "obj1"? At this point "obj1" and "MultiObjectMetaTable" will be global Lua variables?
As I mentioned, this is not standard Lua, so I'm not totally sure what's happening there. (Mixing C++ and Lua can get tricky though, so while you're still learning Lua it's probably better that you stick to the C interface so you can understand whats really happening. Once you understand that you can move on to more automated solutions)
Related
I read the documentation for cascading delete, but one thing I'm not clear on is if it's possible to set up a database so that a child row can be shared by more than one parent and the child row only be deleted when the last referencing parent row is deleted?
(Basically I want foreign keys that act like a std::shared_ptr.)
If that's not possible with the built-in CASCADE DELETE setting, can it be done with a trigger? What would that look like?
The final option I have is that although it is possible in the library I'm writing to create this shared-reference situation, I could simply make it throw an exception when an attempt to construct such a thing takes place.
Specifically, I have a self referencing table that stores something like an abstract syntax tree. Each node has an operation and two child nodes. In my C++ program which is using the database, the objects which represent rows in this table have overloaded operators which return values that simultaneously cause rows to be created in the table. For instance "a << b" would return a temporary value "c" and the database would have a row like: (c_id, '<<', a_id, b_id). However you could follow that with a call to "a << x", in which case the database would contain two rows referencing "a".
The C++ classes are written to insert the table row in their constructor and delete the table row in their destructor. Essentially, I want the creation and destruction of temporary objects in the C++ code to be mirrored in the state of the database. But I want to suppress deleting a child row if it is still referenced by a different parent.
This is possible with a trigger.
When there are no parents with the same child left, delete the child:
CREATE TRIGGER t
AFTER DELETE ON Parent
WHEN NOT EXISTS (SELECT 1 FROM Parent WHERE ChildID = OLD.ChildID)
BEGIN
DELETE FROM Child WHERE ID = OLD.ChildID;
END;
I have two tables in different databases. In a table A is the data, in the other table B are information for incremental load of the data from the first table. I want to load from table B and store the date of the last successful load from table A in a mapping variable $$LOAD_DATE. To achieve this, I read a date from table B and use the SETVARIABLE() function in a expression to set the $$LOAD_DATE variable. The port in which I do this is marked as output and writes into a dummy flat file. I only read on row of this source!
Then I use this $$LOAD_DATE variable in the Source Filter of the Source Qualifier of table A to only load new records which are younger than the date stored in the $$LOAD_DATE variable.
My problem is that I am not able to set the $$LOAD_DATE variable correctly. It is always the date 1753-1-1-00.00.00, which is the default value for mapping variables of the type date/time.
How do I solve this? How can I store a date in that variable and use it later in a Source Qualifiers source filter? Is it even possible?
EDIT: Table A has too much records to read them all and filter them later. This would be to expensive, so they have to be filtered at source filter level.
Yes, it's possible.
In the first map you have to initialize the variable, like this:
In first session configuration you have to define the Post-session on success variable assignment:
The second map (with your table A) will get the variable after this configuration of the session in Pre-session variable assignment:
It will work.
It is not possible to set a mapping variable and use it's value somewhere else in the same run, because, the variable is actually set when the session completes.
If you really want to implement it using mapping variables you have to create two mappings, one for setting the mapping variable and another for actual incremental load. You can pass a mapping variable value from one session to another in a workflow using a workflow variable. https://stackoverflow.com/a/26849639/2626813
Other solutions could be to use a lookup on B and a filter after that.
You can also write some scripts to query table B and modify the parameter file with the latest $LOAD_DATE value prior to executing the mapping.
Since we're having two different DBs, use two sessions. Get values in the first one and pass the parameters to the second one.
I wasn't sure how to word the title, but here we go.
Let's say I made a Lua function to create a 2D box appear on the screen - for example:
box = createObject("Box")
How would I create properties for box that would subsequently change how box looks or reacts? For example I may want to do
box.PositionX = 0
box.PositionY = 60
How do I do that in C++?
Just answering the direct question itself, things are simple:
Just use the standard metatable-aware add/set-table-index API.
If we look at how box itself should look, things get interesting:
If createObject "Box" returns a Lua table and you don't need to react immediately on change, just don't do anything special.
If createObject "Box" returns a Lua table but you need to react immediately, let it act as a proxy object, aka force using the metatable function by never adding that element to the table itself. Remap to another index or another table saved at a dedicated index or in the metatable/metatable function closures.
If createObject "Box" returns a userdata, do the same as for 2, maybe saving non-lua-values in C for faster access/higher efficiency, using the environment table for all other values.
I have a database which uses GUIDs instead of, say, an ordinary counter for the ID fields. But I can't seem to put NULL (instead of GUID_NULL) into such fields in DB even though. Yes, the field in the database does take NULL.
Let's say there is a parent-child relationship between two tables. So there is a parent and a child GUID references from one table to another. But the "root" parent does not have any parent and there I would like to be able to put NULL into its ParentUID database field. If I put GUID_NULL there then I will need a corresponding default row in the referenced table which has a GUID-value of GUID_NULL so that the foreign key constraint won't break.
Also, using GUID_NULL with default-rows at referenced tables will give me a resultset back when doing a standard join operation...which is not desirable.
They way it's done in code when inserting values into database is using a CCommand which takes structure that contains the values of the row fields to be inserted. One of these is a GUID type variable.
So it creates an SQL statement string looking like
INSERT INTO [tablename] (field1, field2, field3,...) VALUES(?,?,?,...)
and then in a loop there is something like:
command.field1 = 1;
command.field2 = 2;
command.GUIDField = ?????? //I want to put NULL here instead of GUID_NULL
command.Open(...);
I hope it is understandable what I wish to do and what the conditions in code are.
Thankful for help!
UPDATE:
Ok, it was very hard to exaplin correctly, but this is exactly what I want to do http://support.microsoft.com/kb/260900
Just that when I follow that example, it makes no difference...still I get FK constraint violation on insert so I suspect it is trying to insert GUID_NULL instead of NULL. :(
The link I had in my Update-section does work, my bad: http://support.microsoft.com/kb/260900
It is the answer to my problems, perhaps it will help someone else as well! :3
Lua tables can have a table as a key, for instance:
a = {[{}]=true}
I'm wondering how I can index this from the lua C++ api. For instance, I can do:
lua_getfield(L, -1, variablename);
To get a string key'd value of a table on the stack. How would I put a table-valued key onto the stack?
lua_getfield is nothing more than syntactic sugar around a series of commands you could do on your own:
lua_pushstring(L, variablename);
lua_gettable(L -1 - 1); //The second minus one represents the fact that your table is actually one index below the top now.
You push the key onto the stack, then use lua_gettable to access it. This is true regardless of what kind of key it is.
The only question you have to answer is how to actually get that key in the first place. For that... you're on your own. Every Lua table has a different value from every other Lua table. And if your Lua script just jammed a freshly-created Lua table in the key like that, without handing a reference to the table to you or storing a reference globally, you're hosed.
Your only recourse then is to just iterate through the table with lua_next and hope that a key who's type is "table" is the key you're looking for.
I would say you need to iterate the table with lua_next.
This link describes the process: http://pgl.yoyo.org/luai/i/lua_next.
Investigate the iterated tables and determine if its the one that you are searching for.