adding indexes to dependent maps in datanucleus - jdo

I have a dependent map on my persistant class... I was thinking the indexed="true" would cause DN to add an index to the key and value columns on the generated table, but it seems completely ignored. Of course I can manually add the index.. but is there a way to make DN do it for me either via annotations (preferred) or xml?
#Persistent
#Key(types=String.class,indexed="true",index = "key_idx")
#Value(types=String.class,dependent="true",indexed="true",index = "value_idx")
#Join
private Map<String,String> metadata = new HashMap<>();
in response to DN's comment it is using mysql... here are the relevant logs I can find and the resulting schema... is there something else I can add to help figure out what I'm doing wrong?:
DataNucleus.Datastore.Schema:58 - Column "account_metadata.id_oid" added to internal representation of table.
DataNucleus.Datastore:58 - Field [com.core.data.account.Account.metadata] -> Column(s) [account_metadata.id_oid] using mapping of type "org.datanucleus.store.mapped.mapping.PersistableMapping" (org.datanucleus.store.rdbms.mapping.IntegerRDBMSMapping)
DataNucleus.Datastore.Schema:58 - Column "account_metadata.`key`" added to internal representation of table.
DataNucleus.Datastore:58 - Field [com.core.data.account.Account.metadata] -> Column(s) [account_metadata.`key`] using mapping of type "org.datanucleus.store.mapped.mapping.StringMapping" (org.datanucleus.store.rdbms.mapping.VarCharRDBMSMapping)
DataNucleus.Datastore.Schema:58 - Column "account_metadata.`value`" added to internal representation of table.
DataNucleus.Datastore:58 - Field [com.core.data.account.Account.metadata] -> Column(s) [account_metadata.`value`] using mapping of type "org.datanucleus.store.mapped.mapping.StringMapping" (org.datanucleus.store.rdbms.mapping.ClobRDBMSMapping)
DataNucleus.Datastore.Schema:58 - Validating 2 index(es) for table account_metadata
DataNucleus.Datastore.Schema:58 - Validating 1 foreign key(s) for table account_metadata
DataNucleus.Datastore.Schema:58 - Validating 1 unique key(s) for table account_metadata
CREATE TABLE `account_metadata` (
`id_oid` int(11) NOT NULL,
`key` varchar(64) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`value` mediumtext,
PRIMARY KEY (`id_oid`,`key`),
KEY `account_metadata_n49` (`id_oid`),
CONSTRAINT `account_metadata_fk1` FOREIGN KEY (`id_oid`) REFERENCES `account` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

SVN trunk of DataNucleus now supports indexes on key/value columns of map join tables where the key/value are non-persistent (previously supported for embedded key/values only).

Related

How to set a table field primary in design-time Firedac?

I want to make a not-null non-auto-inc integer my primary key, but I am unable to do so in design time with Firedac. There is no parameter for the TIntegerfield that allows me to make it primary. There is also no parameter of the TFDTable where I can choose the primary field out of all available fields.
I get that it may be possible doing it in code & combining it with my design time table but that beats the whole purpose of doing it all in design time.
Earlier I did have a auto-inc ID in my table, and this was automatically set to primary key. I deleted this field now because I need another integer to be the primary.
Also I can't find information about the primary key & TFDTable on the official Embacadero website.
It's best to experiment with this using a new table in your database and a minimal new Delphi project.
Update: See below for database DDL and Form's DFM.
You need to have your ID field marked as a primary key in your database.
After you've added an FDConnection and an FDTable to your project, select the FDTable's TableName from the drop down list. Then, click in the FDTable's IndexName field and you should find an automatically-named index on the table's Primary Key. Just select it so that the IndexName takes its value. That's all there is to it.
For the table created using the DDL below, the IndexName property of the FDTable appears as sqlite_autoindex_test_1
If you then dbl-click the FDTable and use the pop-up Fields editor to set up persistent fields on the FDTable and then select your ID field, you should find that if you examine its ProviderFlags, they should include pfInKey, which is what tells FireDAC to use the field as the table's primary key when generating the SQL to update it, do inserts, etc.
You should find that the ID field's Required field is autmatically set to True, btw.
If you want to supply the ID Field's value yourself when adding a new record, use the table's OnNewRecord to generate the ID value an assign it to the field.
DDL for test Sqlite database
create table test(
id int not null primary key,
AName nchar(12)
)
Project DFM extract
object Form2: TForm2
object DBGrid1: TDBGrid
DataSource = DataSource1
end
object DBNavigator1: TDBNavigator
DataSource = DataSource1
end
object FDConnection1: TFDConnection
Params.Strings = (
'Database=D:\aaad7\sqlite\MADB1.sqlite'
'DriverID=SQLite')
Connected = True
LoginPrompt = False
end
object DataSource1: TDataSource
DataSet = FDTable1
end
object FDTable1: TFDTable
IndexName = 'sqlite_autoindex_test_1'
Connection = FDConnection1
UpdateOptions.UpdateTableName = 'test'
TableName = 'test'
object FDTable1id: TIntegerField
FieldName = 'id'
Origin = 'id'
ProviderFlags = [pfInUpdate, pfInWhere, pfInKey]
Required = True
end
object FDTable1AName: TWideStringField
FieldName = 'AName'
Origin = 'AName'
FixedChar = True
Size = 12
end
end
end

MariaDB - Foreign key constraint incorrect?

I tried to re-engineer a database, that I use at work. The one at work is MS Access. At home, it's MariaDB. For convenience, I use MySQL Workbench.
When sending the complete SQL dump to the server, I get an error concerning some foreign key not being correctly formed. I guess, it is a minor mistake, but still I cannot find it.
My InnoDB status tells me this:
LATEST FOREIGN KEY ERROR
2018-10-03 00:18:29 409c7450 Error in foreign key constraint of table `mydb`.`IF`:
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblBelegPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tblBelege_tblECKassenschnittPositionen10`
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblECKassenschnittPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
Create table '`mydb`.`IF`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns near '
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblBelegPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tblBelege_tblECKassenschnittPositionen10`
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblECKassenschnittPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB'.
The really weird thing is that I do not have any table named "IF"...
Can anyone make heads or tails of this for me? That would be very much appreciated.
-- Table `mydb`.`tblBelegPositionen`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`tblBelegPositionen` ;
SHOW WARNINGS;
CREATE TABLE IF NOT EXISTS `mydb`.`tblBelegPositionen` (
`belegposid` INT NOT NULL AUTO_INCREMENT,
`belegposBetrag` DOUBLE NOT NULL,
`zahlartfID` INT NOT NULL,
`belegfID` INT NOT NULL,
PRIMARY KEY (`belegposid`))
ENGINE = InnoDB;
SHOW WARNINGS;
-- Table `mydb`.`tblECKassenschnittPositionen`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`tblECKassenschnittPositionen` ;
SHOW WARNINGS;
CREATE TABLE IF NOT EXISTS `mydb`.`tblECKassenschnittPositionen` (
`ecposid` INT NOT NULL AUTO_INCREMENT,
`belegfID` INT NOT NULL,
`ecposBetrag` DOUBLE NOT NULL,
`kassenschnittfID` INT NOT NULL,
PRIMARY KEY (`ecposid`))
ENGINE = InnoDB;
SHOW WARNINGS;
-- Table `mydb`.`tblBelege`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`tblBelege` ;
SHOW WARNINGS;
CREATE TABLE IF NOT EXISTS `mydb`.`tblBelege` (
`belegid` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`belegKassierer` INT NOT NULL,
`belegDatum` DATETIME NOT NULL,
`kassefID` INT NOT NULL,
`belegSchicht` INT NULL,
`gvfID` INT NOT NULL,
`belegJahr` YEAR NULL,
`belegDruckErfolgt` TINYINT(1) NULL,
`belegDruckDatum` DATETIME NULL,
`belegPeriodenfremdeBuchung` TINYINT(1) NULL,
PRIMARY KEY (`belegid`, `gvfID`, `kassefID`),
CONSTRAINT `fk_tblBelege_tblBelegPositionen10`
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblBelegPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tblBelege_tblECKassenschnittPositionen10`
FOREIGN KEY (`belegid`)
REFERENCES `mydb`.`tblECKassenschnittPositionen` (`belegfID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SHOW WARNINGS;
Ok, so there are a couple of things to know here, as there were a couple of errors. You must check all the items that the error mentions, for correctness, to avoid trouble.
The cannot find an index in the referenced table portion of the error message means that the column/field specified in the REFERENCES clause must be indexed in the other table.
Then, the column type definition of the column specified in the FOREIGN KEY clause must match the column type of the column specified in the REFERENCES clause too, so even though the first item corrects part of the problem, there will still be an error related to another portion of the message: ...or column types in the table and the referenced table do not match.
So, to fix item 1, run these 2 queries:
ALTER TABLE `tblbelegpositionen` ADD INDEX(`belegfID`);
ALTER TABLE `tbleckassenschnittpositionen` ADD INDEX(`belegfID`);
Then to fix item 2, I had to change the first column of table tblBelege
from this:
`belegid` INT UNSIGNED NOT NULL AUTO_INCREMENT,
to this:
`belegid` INT NOT NULL,
...so that they matched the same type as the belegfID column as defined in the other tables. After those two changes, I was able to successfully run your CREATE TABLE `tblBelege` statement.
So, to recap:
Run your create table statements for tblbelegpositionen and
tbleckassenschnittpositionen.
Then run the 2 ALTER statements shown above for item 1.
Modify the first column of table tblBelege to match the column types as defined to belegfID in the other tables for item 2.
Then run your modified CREATE TABLE statement (with the item 2 change applied) to create the tblBelege table.
I'm a little confused about the same FOREIGN KEY referencing 2 different tables, but if it works for you, then ok. (not saying that it cannot be done, I've never used a foreign key that way) Perhaps you meant the opposite, to have a foreign key in the other 2 tables (1 in each table) that refer to tblBelege instead? If so, then you could add unsigned to the type definition for belegfID and it would work, and would not need the change that I mentioned with item 2.
Oh, and after you run the ALTER statements, you can view the table structure by running:
SHOW CREATE TABLE `tblbelegpositionen`;
SHOW CREATE TABLE `tbleckassenschnittpositionen`;
...to get the KEY definition that was added to include with your CREATE TABLE statements. Since they both create the same key, you really only need to run one of those statements and then add the KEY definition to both table statements.

sqlite integer primary key not null constraint failed

According to the SQLite documentation / FAQ a column declared INTEGER PRIMARY KEY will automatically get a value of +1 the highest of the column if omitted.
Using SQLite version 3.22.0 2018-01-22 18:45:57
Creating a table as follows:
CREATE TABLE test (
demo_id INTEGER PRIMARY KEY NOT NULL,
ttt VARCHAR(40) NOT NULL,
basic VARCHAR(25) NOT NULL,
name VARCHAR(255) NOT NULL,
UNIQUE(ttt, basic) ON CONFLICT ROLLBACK
) WITHOUT ROWID;
Then inserting like this:
INSERT INTO test (ttt, basic, name) VALUES ('foo', 'bar', 'This is
a test');
gives:
Error: NOT NULL constraint failed: test.demo_id
sqlite>
When it is expected to create a record with a demo_id value of 1. Even if the table already contains values, it'll fail inserting the row without explicitly specifying the id with the same error.
What am I doing wrong?
The documentation says that you get autoincrementing values for the rowid. But you specified WITHOUT ROWID.

A primary key in ORACLE 11g became nullable

I have a table named 'ROUTE'. What "desc ROUTE" does is as follow:
Name Null Type
-------------------- ---- --------------
ROUTE_GUID RAW(16 BYTE)
LINE_GUID RAW(16 BYTE)
EVENT_GUID RAW(16 BYTE)
DESCRIPTION VARCHAR2(254)
Where ROUTE_GUID IS PK. When I tried altering the table, it showed "ORA-01442: column to be modified to NOT NULL is already NOT NULL". The real problem is that a .NET application has to use this table but it cannot unless a non-nullable column is found. There are also many database views associated with this table so that these view cannot be retrieved by .NET as well. Anyone got the same problem?
I came across this issue in Oracle 12g r 2. The desc MY_TABLE did not show the NOT NULL for a column that did have a NOT NULL constraint. Querying the DBA_TAB_COLS table for the NULLABLE column did not show it either. If I queried the DBA_CONS_COLUMNS and
DBA_CONSTRAINTS it did show up! The web site https://logic.edchen.org/how-to-resolve-ora-01442-column-to-be-modified-to-not-null-is-already-not-null/ almost helps; it showed the case where the constraint was in DISABLED status; my situation, the status was ENABLED. I just did a disable followed by an enable, and it worked; the NOT NULL is displayed now.
Code to display NOT NULL constraint name:
select a.constraint_name, b.status
from dba_cons_columns a
inner join dba_constraints b
on a.constraint_name = b.constraint_name
where a.table_name = 'MY_TABLE'
and a.owner = 'SCOTT' and a.owner=b.owner
and a.column_name = 'USER_NAME'
and b.constraint_type = 'C' and search_condition_vc like '%NOT NULL';
Code to disable and enable constraint:
alter table scott.my_table modify constraint SYS_C0019940 DISable;
alter table scott.my_table modify constraint SYS_C0019940 ENable;

setting default value while creating table in SQLite

I am working on SQLite. I want to create a table namely user_role with two column role_id and role_name. And there is an another table namely default that contain role_name and default_val.
I want to set Default value of role_id in the time of creating the table user_role and the Default value have to be retrieved from the table default.
I am new to SQLite and have to idea about the way to doing such recursive query. Please help.
The documentation says:
An explicit DEFAULT clause may specify that the default value is NULL, a string constant, a blob constant, a signed-number, or any constant expression enclosed in parentheses.
You would need to use a subquery, which is not allowed.
However, you could use a trigger that sets the ID if none was specified:
CREATE TRIGGER user_role_id_default
AFTER INSERT ON user_role
FOR EACH ROW
WHEN NEW.role_id IS NULL
BEGIN
UPDATE user_role
SET role_id = (SELECT default_val
FROM "default"
WHERE role_name = NEW.role_name)
WHERE rowid = NEW.rowid;
END;

Resources