How can I use timestamp or timestamp+incrementing mode for a kafka connect source connector? - jdbc

I have a database (Mariadb) relation with a column "modified" as "bigint(10)" that represents a timestamp, I believe in unix time format. When I try to run a kafka source connector with mode "timestamp" or "timestamp+incrementing" no events are pushed into the topic. If I run only incrementing, new entries are pushed to the topic. Can someone hint to me where I configured the connector wrongly? Or does the connector not recognize timestamps in unix time format?
I tried to run a connector (retrieval based only on timestamp) with the following properties:
curl -X POST http://localhost:8083/connectors -H "Content-Type: application/json" -d '{
"name":"only_ts",
"config": {
"numeric.mapping": "best_fit",
"connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector",
"connection.url": "jdbc:mysql://mariadb/moodle",
"connection.user": "user",
"connection.password": "",
"topic.prefix": "only_ts_",
"mode": "timestamp",
"timestamp.column.name":"modified",
"table.whitelist":"mdl_forum_posts",
"poll.intervals.ms": 10000
}
}'
I would expect to see entries from "mdl_forum_posts" to be pushed into a kafka topic "only_ts_mdl_forum_posts" whenever I create an entry or update an entry. However, using this connector, nothing happens.
If I use only mode "incrementing" this works fine and as expected. But to get DB UPDATES too, I need to add the mode timestamp.
Output for "describe mdl_forum_posts"
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| id | bigint(10) | NO | PRI | NULL | auto_increment |
| discussion | bigint(10) | NO | MUL | 0 | |
| parent | bigint(10) | NO | MUL | 0 | |
| userid | bigint(10) | NO | MUL | 0 | |
| created | bigint(10) | NO | MUL | 0 | |
| modified | bigint(10) | NO | | 0 | |
| mailed | tinyint(2) | NO | MUL | 0 | |
| subject | varchar(255) | NO | | | |
| message | longtext | NO | | NULL | |
| messageformat | tinyint(2) | NO | | 0 | |
| messagetrust | tinyint(2) | NO | | 0 | |
| attachment | varchar(100) | NO | | | |
| totalscore | smallint(4) | NO | | 0 | |
| mailnow | bigint(10) | NO | | 0 | |
| deleted | tinyint(1) | NO | | 0 | |
+---------------+--------------+------+-----+---------+----------------+
And output for "show create table moodle.mdl_forum_posts;":
| mdl_forum_posts | CREATE TABLE mdl_forum_posts (
id bigint(10) NOT NULL AUTO_INCREMENT,
discussion bigint(10) NOT NULL DEFAULT '0',
parent bigint(10) NOT NULL DEFAULT '0',
userid bigint(10) NOT NULL DEFAULT '0',
created bigint(10) NOT NULL DEFAULT '0',
modified bigint(10) NOT NULL DEFAULT '0',
mailed tinyint(2) NOT NULL DEFAULT '0',
subject varchar(255) NOT NULL DEFAULT '',
message longtext NOT NULL,
messageformat tinyint(2) NOT NULL DEFAULT '0',
messagetrust tinyint(2) NOT NULL DEFAULT '0',
attachment varchar(100) NOT NULL DEFAULT '',
totalscore smallint(4) NOT NULL DEFAULT '0',
mailnow bigint(10) NOT NULL DEFAULT '0',
deleted tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
KEY mdl_forupost_use_ix (userid),
KEY mdl_forupost_cre_ix (created),
KEY mdl_forupost_mai_ix (mailed),
KEY mdl_forupost_dis_ix (discussion),
KEY mdl_forupost_par_ix (parent)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='All posts are stored in this table' |
An example entry in the column "modified" is:
select modified from mdl_forum_posts;
1557487199
It is a timestamp in unix time as following seems to show:
select from_unixtime(modified) from mdl_forum_posts;
2019-05-10 11:19:59
The relevant log concerning the relevant connector (only timestamp) seems to show some query ?
kafka-connect_1 | [2019-05-10 11:48:47,434] DEBUG TimestampIncrementingTableQuerier{table="moodle"."mdl_forum_posts", query='null', topicPrefix='only_ts_', incrementingColumn='', timestampColumns=[modified]} prepared SQL query: SELECT * FROM `moodle`.`mdl_forum_posts` WHERE `moodle`.`mdl_forum_posts`.`modified` > ? AND `moodle`.`mdl_forum_posts`.`modified` < ? ORDER BY `moodle`.`mdl_forum_posts`.`modified` ASC (io.confluent.connect.jdbc.source.TimestampIncrementingTableQuerier)
kafka-connect_1 | [2019-05-10 11:48:47,435] DEBUG Resetting querier TimestampIncrementingTableQuerier{table="moodle"."mdl_forum_posts", query='null', topicPrefix='only_ts_', incrementingColumn='', timestampColumns=[modified]} (io.confluent.connect.jdbc.source.JdbcSourceTask)

I had the same problem. The only workaround for me was as mentioned here: https://github.com/confluentinc/kafka-connect-jdbc/issues/566.
It means that timestamp mode for unix timestamp (bigint) column can be used together with a custom query. You only need to use your own where clause. For example in your case, it could be something like:
SELECT id
FROM mdl_forum_posts
WHERE to_timestamp(modified/1000) > ? AND to_timestamp(modified/1000) < ? ORDER BY modified ASC
--
to_timestamp is a date conversion function in your DB dialect. And please note -- that allows to comment autogenerated where clause.

If you are using newer versions, you can use the "timestamp.granularity" option: which would allow you to work with other timestamp data types.

Related

Laravel get value from db with columns key/value

I have a table on my DB with these columnns:
+-----------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| value | varchar(255) | NO | | NULL | |
+-----------------+---------------------+------+-----+---------+----------------+
I would access to value values by name.
For example I have these datas:
+----+------------+------------+
| id | name | value |
+----+------------+------------+
| 1 | start_date | 2020-01-01 |
| 2 | end_date | 2021-01-01 |
+----+------------+------------+
I would to get '2020-01-01' by 'start_date'.
I tried this code, but I'm not satisfyed because with this code I get all values of the row, not only the value expected.
Configuration::get()->keyBy('start_date');
I'm not sure I was clear.
Let me know.
Thanks a lot!!
Assuming you want to get an array of key/value pairs, and each key in the name column is unique, you can simply use pluck() (https://laravel.com/docs/8.x/collections#method-pluck):
$configuration = Configuration::pluck('value', 'name');
dd($configuration);
// ['start_date' => '2020-01-01', 'end_date' => '2021-01-01']
Then, you'd use simply array access to use these configuration settings where applicable:
$startDate = $configuration['start_date']; // '2020-01-01'
$endDate = $configuration['end_date']; // '2021-01-01'
...

Undefined binding(s) detected when compiling SELECT query

I am following a tutorial for strapi and am stuck at a part where I query for dishes belonging to a restaurant. I'm sure everything is set up properly with a one(restaurant) to many(dishes) relationship defined but the query doesn't work. I've traced it to the actual query which is:
query {
restaurant(id: "1") {
id
name
dishes {
name
description
}
}
}
which returns an error when I run it in playground. The query doesn't show any issues while I write it and doesn't allow me to write anything like:
query {
restaurant(where:{id: "1"}) {
id
name
dishes {
name
description
}
}
}
My database is mysql and the two tables look like this:
mysql> describe dishes;
+-------------+---------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | MUL | NULL | |
| description | longtext | YES | | NULL | |
| price | decimal(10,2) | YES | | NULL | |
| restaurant | int(11) | YES | | NULL | |
| created_at | timestamp | NO | | CURRENT_TIMESTAMP | |
| updated_at | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------------+---------------+------+-----+-------------------+-----------------------------+
7 rows in set (0.00 sec)
mysql> describe restaurants;
+-------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | MUL | NULL | |
| description | longtext | YES | | NULL | |
| created_at | timestamp | NO | | CURRENT_TIMESTAMP | |
| updated_at | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------------+--------------+------+-----+-------------------+-----------------------------+
5 rows in set (0.00 sec)
These tables where auto generated by strapi.
The full error in playground is this:
{
"errors": [
{
"message": "Undefined binding(s) detected when compiling SELECT query: select `restaurants`.* from `restaurants` where `restaurants`.`id` = ? limit ?",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"restaurant"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Undefined binding(s) detected when compiling SELECT query: select `restaurants`.* from `restaurants` where `restaurants`.`id` = ? limit ?",
" at QueryCompiler_MySQL.toSQL (/Users/redqueen/development/deliveroo/server/node_modules/knex/lib/query/compiler.js:85:13)",
" at Builder.toSQL (/Users/redqueen/development/deliveroo/server/node_modules/knex/lib/query/builder.js:72:44)",
" at /Users/redqueen/development/deliveroo/server/node_modules/knex/lib/runner.js:37:34",
"From previous event:",
" at Runner.run (/Users/redqueen/development/deliveroo/server/node_modules/knex/lib/runner.js:33:30)",
" at Builder.Target.then (/Users/redqueen/development/deliveroo/server/node_modules/knex/lib/interface.js:23:43)",
" at runCallback (timers.js:705:18)",
" at tryOnImmediate (timers.js:676:5)",
" at processImmediate (timers.js:658:5)",
" at process.topLevelDomainCallback (domain.js:120:23)"
]
}
}
}
],
"data":
Any idea why this is happening?
It seems this was a bug with the alpha.v20 and alpha.v21 versions of strapi. A bug fix has been published to solve it, an issue thread on github is here.

mysql timestamp error with time.Now() golang

How to save time.Now() in mysql table, column name as created_at timestamp null.
I am getting error :
Error:Error 1292: Incorrect datetime value: '2017-08-05 19:06:14.190 +0000' for column 'created_at' at row 1
More Information as asked :- ( I am using fragmenta cms, so all reference code with their line number is given below )
Table schema :-
mysql> describe users;
+----------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
| status | int(11) | YES | | NULL | |
| role | int(11) | YES | | NULL | |
| name | varchar(250) | YES | | NULL | |
| email | varchar(250) | YES | | NULL | |
| title | varchar(250) | YES | | NULL | |
| summary | text | YES | | NULL | |
| text | text | YES | | NULL | |
| image_id | int(11) | YES | | NULL | |
| password_hash | varchar(250) | YES | | NULL | |
| password_reset_token | text | YES | | NULL | |
| password_reset_at | timestamp | YES | | NULL | |
+----------------------+--------------+------+-----+---------+----------------+
Code that is running it to save :-
At line no. 62 here ( https://github.com/fragmenta/fragmenta-cms/blob/master/src/pages/actions/setup.go#L62 )
It calls code
user := users.New()
in Line no. 51 at file here ( https://github.com/fragmenta/fragmenta-cms/blob/master/src/users/query.go#L51 )
New() function is setup.
Which is like :-
func New() *User {
user := &User{}
user.CreatedAt = time.Now()
user.UpdatedAt = time.Now()
user.TableName = TableName
user.KeyName = KeyName
user.Status = status.Draft
return user
}
and their connecting / mysql opening pattern is located here ( https://github.com/fragmenta/query/blob/master/adapters/database_mysql.go#L23 ) .
There is a bug in https://github.com/fragmenta/query. The TimeString method in query/adapters/database.go is not valid for all DBMS adapters.
// TimeString - given a time, return the standard string representation
func (db *Adapter) TimeString(t time.Time) string {
return t.Format("2006-01-02 15:04:05.000 -0700")
}
It's not valid for a MySQL timestamp: MySQL 5.7 Reference Manual, 11.3.1 The DATE, DATETIME, and TIMESTAMP Types. The MySQL TimeString method in query/adapters/database_mysql.go should be:
// TimeString - given a time, return the MySQL standard string representation
func (db *MysqlAdapter) TimeString(t time.Time) string {
return t.Format("2006-01-02 15:04:05.999999")
}
You are trying to insert it using a string query.go:36:
now := query.TimeString(time.Now().UTC())
that is generated by the package that you are using database.go:59:
return t.Format("2006-01-02 15:04:05.000 -0700")
MySQL expects it to be in the pattern of yyyy-MM-dd hh:mm:ss, use the following snippet to apply the pattern to you current Time.time object:
now := time.Now().UTC().Format("2006-01-02 03:04:05")
Anyway, why not to use the SQL function NOW() when inserting the record ?

Return filtered records from a returned set of data from two tables

I have three tables:
- Venue
- Space (belongs to Venue)
- Included Space (belongs to Space)
I receive the id of a Venue in the route and return all the related spaces that I know have Included Spaces(a field called num_included_spaces__c on the Space record that maintains a count of its children). Now that I have all the related parent Spaces for that Venue, I need to find all of the Included Spaces for them.
An Included Space is still a Space, it just happens to have a parent that resides in the same table. I'm trying to turn this:
Venue = Rockdog
- Space = Upstairs
- Space = Media Room
- Space = Courtyard
- Space = Downstairs
- Space = Front Patio
- Space = Indoor Bar
Into this:
Venue = Rockdog
- Space = Upstairs
-- Included Space = Media Room
-- Included Space = Courtyard
- Space = Downstairs
-- Included Space = Front Patio
-- Included Space = Indoor Bar
The Included Spaces table has belongs_to__c and space__c as fields, where belongs_to__c is the id of the parent space and space__c is the id of the child. So i'm looking to find all the Included Spaces where belongs_to_c matches the id of any #spaces returned below
#sub_spaces = Space.where("venue__c = ? AND num_included_spaces__c = ?", params[:venue],0)
#spaces = Space.where("venue__c = ? AND num_included_spaces__c > ?", params[:venue],0)
How would I write this Active Record Query for #included_spaces?
my database schema.
mysql> describe venues;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0,00 sec)
mysql> describe spaces;;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| venue_id | int(11) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0,00 sec)
ERROR:
No query specified
mysql> describe included_spaces;;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| space_id | int(11) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0,00 sec)
ERROR:
No query specified
Below function will somehow give you the result you need (in console ofcourse ) however it's not a good solution - it queries database more than needed. However it is the easy -))
def foo id
v = Venue.find(id)
puts v.name
v.spaces.each do |space|
puts space.name
space.included_spaces.each do |spis|
puts spis.name
end
end
end
You can also try a more complex query sth like,
mysql> SELECT spaces.name, included_spaces.name FROM `spaces` INNER JOIN `venues` ON `venues`.`id` = `spaces`.`venue_id` INNER JOIN `included_spaces` ON `included_spaces`.`space_id` = `spaces`.`id` WHERE `spaces`.`venue_id` = 1
-> ;
+------------+-----------+
| name | name |
+------------+-----------+
| Upstairs, | Front |
| Upstairs, | Patio, |
| Upstairs, | Indoor |
| Upstairs, | Bar |
| Downstairs | Media |
| Downstairs | Room, |
| Downstairs | Courtyard |
+------------+-----------+
7 rows in set (0,00 sec)
which should be translated to active record as
Space.joins(:venue)
.joins(:included_spaces)
.where(venue_id: 1)
.select('spaces.name, included_spaces.name')

MySQL has many through [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
1- Users may have many classrooms
2- Classrooms may have many users
3- Users may have many payments in their classrooms
how can I get a classroom payments through its users with SQL?
how can I get sum of the payments of a user per classroom?
-- Payments Table: --
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| amount | int(11) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
-- Users Table: --
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
-- Classrooms Table: --
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
-- Classroom_User Table: --
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| classroom_id| int(11) | NO | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
Without testing, I'd say:
SELECT p.amount, u.name, c.name
FROM payments p, users u, classrooms c, classroom_user ct
WHERE ct.user_id = u.id
AND ct.classroom_id = c.id
AND u.id = p.user_id
However: it's not clear what your tables are about. For instance: one record in the payments table can result in multiple records in the result set, namely when there are multiple records in the classroom_user table for the same user.
Something in your database design feels wrong, but it's hard to tell what's wrong without more info.
Suppose that you want to get the payments for each classroom. In that case, your database design is wrong because you only know the amount each user paid in total, not the amount the user paid per classroom.
The payments table should look like this:
+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| classroom_user_id | int(11) | NO | | NULL | |
| amount | int(11) | NO | | NULL | |
+-------------------+--------------+------+-----+---------+----------------+
In that case, you'd have:
SELECT c.name, u.name, p.amount
FROM payments p, users u, classrooms c, classroom_user ct
WHERE p.classroom_user_id = ct.id
AND ct.classroom_id = c.id
AND ct.user_id = u.id
Or, if you want to get the total amount per classroom:
SELECT c.name, SUM(p.amount)
FROM payments p, classrooms c, classroom_user ct
WHERE p.classroom_user_id = ct.id
AND ct.classroom_id = c.id
GROUP BY c.id
Note that I didn't test this. I don't have your database.

Resources