E/SQLiteDatabase﹕ Error inserting ,table accounts has no column named control_type (code 1): - android-sqlite

tHis is my code for create a db table
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
+ KEY_PH_NO + " TEXT" + KEY_CTRL_TYPE + " TEXT,"
+ KEY_USER_NAME + " TEXT,"+ KEY_PASSWORD + " TEXT "
+ ")";
db.execSQL(CREATE_CONTACTS_TABLE);
}
and this is for add a contact
void addContact(Accounts accounts) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_NAME, accounts.getName()); // Contact Name
values.put(KEY_PH_NO, accounts.getPhoneNumber()); // Contact Phone
values.put(KEY_CTRL_TYPE, accounts.getControlType()); //
values.put(KEY_USER_NAME, accounts.getUserName()); //
values.put(KEY_PASSWORD, accounts.getPassword()); //
// Inserting Row
db.insert(TABLE_CONTACTS, null, values);
db.close(); // Closing database connection
}
I am getting this error on accessing addContact
db.addContact(new Accounts(siteName,siteNum,ctype,username,pass));
29206-29206/com.atrolabe.tcpremote1 E/SQLiteDatabase﹕ Error inserting control_type=SHAULA 720 user_name=wetyu phone_number=123455566 password=fhhchhjh name=test
android.database.sqlite.SQLiteException: table accounts has no column named control_type (code 1): , while compiling: INSERT INTO accounts(control_type,user_name,phone_number,password,name) VALUES (?,?,?,?,?)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
the logcat points to this Line in addcontact
db.insert(TABLE_CONTACTS, null, values);

The problem is actually with the initial onCreate() method. The resulting SQL is constructed improperly and never creates the control_type column. See below:
"CREATE TABLE " + TABLE_CONTACTS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
+ KEY_PH_NO + " TEXT" + KEY_CTRL_TYPE + ...
After the phone number field the TEXT keyword is positioned next to the intended control_type column name; resulting in unexpected SQL. For example (filling in with expected values)
CREATE TABLE Contacts (
ContactID INTEGER PRIMARY KEY, ContactName TEXT,
ContactNumber TEXTcontrol_type ...
To fix this problem, simply re-format your CREATE_CONTACTS_TABLE string properly.

Related

JPA Query clause IN / Invalid relational operator

How to include the IN clause in the Query if the parameter is not null?
If I try to put the ":ramos is null" it gives an error
#Query(value = "SELECT r FROM ParceiroNegocio r " +
" WHERE (:razaoSocial is null or UPPER(r.razaoSocial) LIKE CONCAT('%',UPPER(:razaoSocial),'%')) " +
" AND (:nomeFantasia is null or UPPER(r.nomeFantasia) LIKE CONCAT('%',UPPER(:nomeFantasia),'%')) " +
" AND (:cnpj is null or r.cnpj =:cnpj) " +
" AND ((:ramos) is null or r.ramo IN (:ramos))")
Page<ParceiroNegocio> findByCnpjNomeFantasiaRazaoSocialRamoWithPagination(
#Param("razaoSocial") String razaoSocial,
#Param("nomeFantasia") String nomeFantasia,
#Param("cnpj") String cnpj,
#Param("ramos") List<Long> ramos,
Pageable pageable);
}
Error:
SqlExceptionHelperORA-00920: invalid relational operator
COALESCE helped me! :)
AND (COALESCE(:ramos) is null or r.ramo IN (:ramos))

How to parameterise Postgresql Interval for TimescaleDB `time_bucket` function with JPQL, Spring Data Repositories and Hibernate

I am using Spring Data JPA (with Hibernate underneath, JPA 2.1) with TimescaleDB extension on PostgreSQL 13, and wish to use the time_bucket function. This takes the bucket_width which is an INTERVAL and time which is the TIMESTAMP column of the data.
I want to put this in a Spring Data Repository and want to use a JPQL #Query to extract the data into a projection that represents the aggregate counts, averages etc. for the returned time buckets. I don't want to use a native query, because I want to join with some other tables, and populate their entities automatically.
I registered the time_bucket function to the PostgisPG95Dialect I am extending, like this:
public class CustomPostgresqlDialect extends PostgisPG95Dialect {
public CustomPostgresqlDialect() {
super();
this.registerFunction("time_bucket", new StandardSQLFunction("time_bucket", new OffsetDateTimeType()));
}
}
If the bucket_width is hardcoded, all this works fine. But I want the bucket_width to be a parameter of the query method.
The following works fine:
#Query("select sys as system, "
+ "function('time_bucket', '10 mins', vt.ts) as startTime, "
+ "count(vt) as total, avg(vt.speed) as avgSpeed "
+ "from Data vt "
+ "JOIN vt.system sys "
+ "where sys.sysId = :sysId and "
+ "function('time_bucket', '10 mins', vt.ts) between :from and :to "
+ "group by system, startTime "
+ "order by startTime")
List<SummaryAggregate> getSummaryData(
#Param("sysId") String sysId,
#Param("from") OffsetDateTime from,
#Param("to") OffsetDateTime to);
But when I try to parameterise the interval I can't get it to work. I tried passing the interval as a string, since that is how it is being written in the hardcoded version:
#Query("select sys as system, "
+ "function('time_bucket', :grouping, vt.ts) as startTime, "
+ "count(vt) as total, avg(vt.speed) as avgSpeed "
+ "from Data vt "
+ "JOIN vt.system sys "
+ "where sys.sysId = :sysId and "
+ "function('time_bucket', :grouping, vt.ts) between :from and :to "
+ "group by system, startTime "
+ "order by startTime")
List<SummaryAggregate> getSummaryData(
#Param("sysId") String sysId,
#Param("from") OffsetDateTime from,
#Param("to") OffsetDateTime to,
#Param("grouping") String grouping);
where grouping is passed a value like 10 mins.
But for this I get this error:
SQL Error: 0, SQLState: 42883
ERROR: function time_bucket(character varying, timestamp with time zone) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 61
I then tried to change it to a Duration, since Hibernate translates Duration to PostgreSQL Interval types
#Query("select sys as system, "
+ "function('time_bucket', :grouping, vt.ts) as startTime, "
+ "count(vt) as total, avg(vt.speed) as avgSpeed "
+ "from Data vt "
+ "JOIN vt.system sys "
+ "where sys.sysId = :sysId and "
+ "function('time_bucket', :grouping, vt.ts) between :from and :to "
+ "group by system, startTime "
+ "order by startTime")
List<SummaryAggregate> getSummaryData(
#Param("sysId") String sysId,
#Param("from") OffsetDateTime from,
#Param("to") OffsetDateTime to,
#Param("grouping") Duration grouping);
But I still got the same error, this time it is thinking that the Duration is a bigint not an Interval.
SQL Error: 0, SQLState: 42883
ERROR: function time_bucket(bigint, timestamp with time zone) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 61
Is there a way to parameterise an Interval using JPQL?
There is a way, but you will have to register a custom function for this purpose because you can't cast to an arbitrary SQL type.
public class CastInterval implements SQLFunction {
#Override
public boolean hasArguments() {
return true;
}
#Override
public boolean hasParenthesesIfNoArguments() {
return true;
}
#Override
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
return firstArgumentType;
}
#Override
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) throws QueryException {
return "cast(" + args.get(0) + " as interval)";
}
}
You will have to register the function within the Dialect.
So if the Dialect is being extended as indicated, this would be done with something like:
this.registerFunction("castInterval", new CastInterval());
Then you can use it like this: function('time_bucket', castInterval(:grouping), vt.ts)

JPA - Find items from a list that don't exist in a table

Given a list of emails, I need to find which ones don't exist in a table. Using SQL, I can do the following:
SELECT e.email
FROM
(
VALUES('email1'),('email2'),('email3'),('email4')
) AS e(email)
EXCEPT
SELECT username FROM dbo.UsersTbl;
How can I write equivalent JPQL? In the application, values email1, email2... need be dynamically built (not hardcoded) based on passed in list. Using a Spring Data JPA native query, I can do the following:
#Query( value =
"SELECT e.email " +
" FROM " +
"( " +
" VALUES('email1'),('email2'),('email3'),('email4') " +
" ) AS e(email) " +
" EXCEPT " +
" SELECT username FROM dbo.UsersTbl ",
nativeQuery=true)
List<String> findMissingEmails(List<String> emails);
But how can I pass in the list of emails to the query?
For fixed number of email arguments, this could work:
#Query( value =
"SELECT e.email " +
" FROM " +
"( " +
" VALUES(:email1),(:email2),(:email3),(:email4) " +
" ) AS e(email) " +
" EXCEPT " +
" SELECT username FROM dbo.UsersTbl ",
nativeQuery=true)
List<String> findMissingEmails(String email1, String email2, String email3, String email4);
For high and/or dynamic number of emails, a better approach could be to use NativeQuery constructed at runtime.
Old answer - more or less exactly the opposite of what was asked for, but I'll keep it here as reference.
Using of named parameter:
#Query("SELECT u.email FROM User AS u WHERE u.email NOT IN (:emails)")
List<String> findMissingEmails(#Param("emails")Collection<String> emails);
Alternatively, you could use a JPA query method:
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findAllByEmailNotIn(Collection<String> emails);
}
Unfortunately that method would fetch and return a list of Users instead of list of their emails.
To fetch just emails you could use a JPA projection.
Assuming that User entity has a field of type String named email, the following projection could be used:
public interface UserEmail {
String getEmail();
}
And this is the repository method:
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<UserEmail> findAllByEmailNotIn(Collection<String> emails);
}

How to fix: Error thrown mapping result set into return type

I am using JDBI 3 to run update query which might update multiple rows. I want to get updated rows from the resultset.
However, I'm getting ArrayIndexOutOfBoundsException: Error thrown mapping result set into return type
Tried to add #SingleValue to return signature, but still stuck with the same issue.
Unable to use #SqlBatch as this is a single query and #SqlBatch requires list.
#SqlUpdate(
"UPDATE task_sync SET "
+ " is_active = false, "
+ " version = version+1 "
+ " WHERE task_id IN (<taskIdList>) "
+ " AND barcode IN (<barcodeList>) "
+ " AND is_active = true ")
#GetGeneratedKeys("id")
List<Long> deactivateTaskSyncByTaskIdInAndBarcodeList(
#BindList("taskIdList") List<Long> taskIdList,
#BindList("barcodeList") Set<String> barcodeList,
#Bind("lastUpdatedById") Long lastUpdatedById);
Query generated:
UPDATE task_sync SET is_active = false, version = version+1 WHERE task_id IN (26) AND barcode IN ('8606850380_0', '8696930120_0', '6907922280_0', '4605723180_0', '2354050010_0', '5259987660_0', '6392185330_0'
) AND is_active = true
RETURNING "id"
I expect this to return a list of updated ids.
You are in the right track.
To make it work you need to tell Postgres that you want to return the id column of all affected rows. You can do this by a adding RETURNING id; to the end of your query. The code would look like this:
#SqlUpdate(
"UPDATE task_sync SET "
+ " is_active = false, "
+ " version = version+1 "
+ " WHERE task_id IN (<taskIdList>) "
+ " AND barcode IN (<barcodeList>) "
+ " AND is_active = true RETURNING id;")
#GetGeneratedKeys("id")
List<Long> deactivateTaskSyncByTaskIdInAndBarcodeList(
#BindList("taskIdList") List<Long> taskIdList,
#BindList("barcodeList") Set<String> barcodeList,
#Bind("lastUpdatedById") Long lastUpdatedById);
Notice that you can also return multiple columns (e.g.: RETURNING id, version;) or event the entire row (e.g: RETURNING *;).

Creating Select statement with variable in single quotes

This relates to taking data from a Google Fusion table.
When I first set up my site, GF tableid was a numeric value, (var tableid = 123456;) and I built a query like this:
layer.setQuery("SELECT 'Latitude' FROM " + tableid + " WHERE 'Name' contains etc etc
Now tableid is something like var tableid = '12DFty24'; and I'm having trouble converting the setQuery to handle it.
I've tried adding an extra single quote around tableid, but that doesn't work. Nor do backslashes.
Ideas would be gratefully received!
Paul
You are using the old syntax that can't work with encrypted ID, numeric ID's are deprecated.
You have to change your code using the new syntax; here is the documentation
Example:
new google.maps.FusionTablesLayer({ query: {[FusionTablesQuery object]}});
And here's the one that works...need to be careful with parentheses and commas!
function searchAddress()
{
var searchString = document.getElementById('searchAddressString').value.replace("'", "\\'");
// layer.setQuery("SELECT 'Latitude' FROM " + tableid + " WHERE 'Address' contains ignoring case '" + searchString + "'");
var layer = new google.maps.FusionTablesLayer({
query: {
select: 'Latitude',
from: tableid,
where: 'Address' contains ignoring case '" + searchString + "'"
}
});
layer.setMap(map);
}