Back to The tech awesomeness
Table of contents
Java chapters

The article for today.

The following three java classes will implement the possibility for storing the news messages from RSS sources into SQL relational database, for example, https://en.wikipedia.org/wiki/List_of_relational_database_management_systems.

The prerequisites are: java, JDK, SQL relational database, java to SQL relational database connector.

In order to find and compile these codes for that I used some codes from https://vogella.com/ and https://mkyong.com/ and https://stackoverflow.com/ and https://www.baeldung.com/.

I have implemented RSSXMLMessageParser and other RSSMessageParsers as, for example, RSSJSONMessageParser, I have not implemented yet.

Optionally I used some database client tools which provides interfaces for powerful filtering, querying of the RSS news data at the https://en.wikipedia.org/wiki/Comparison_of_database_tools.

Optionally to add regular reading and persising of the codes the following sentence might help.


ssh user@$IP nohup "echo -e '0 * * * * java RSSMessageReadAndPersistTest' | crontab -u user -"

and in for jar:


ssh user@$IP nohup "echo -e '0 * * * * java -cp rssclientwithpersistencetest.jar info.ideasmatter.RSSMessageReadAndPersistTest' | crontab -u user -"

The update from 2020-04-16.

I added the custom extra control characters to replace in XML for each RSS source.


public class RSSMessageReadAndPersistTest {
    
        private static final String DATABASE_URL =
                "jdbc:mysql://thetechawesomeness.ideasmatter.info:3306/test";
        private static final String DATABASE_USER = "DATABASE_USER";
        private static final String DATABASE_PASSWORD = "DATABASE_PASSWORD";
    
        static class RssSource {
            public String url = "",
                    //new String(new byte []{(byte) 0x8c})
                    //"\\x0C"
                    extraCharacters = "";
            
            public RssSource(String url, String extraCharacters) {
                this.url = url;
                this.extraCharacters = extraCharacters;
            }
        }
        
    public static void main(String[] args) {
            RssSource rssSources[] = {
                new RssSource("http://thetechawesomeness.ideasmatter.info/rss.xml", "")
            };
            for (RssSource rssMessageUrl: rssSources) {
                System.out.println(rssMessageUrl);
                try {
                    readRSSMessages(rssMessageUrl);
                } catch (IOException ex) {
                    Logger.getLogger(RSSMessageReadAndPersistTest
                            .class.getName()).log(Level.SEVERE, null, ex);
                }
            }
    }
        
        public static void readRSSMessages(final RssSource rssSource)
                throws IOException {
            RSSXMLMessageParser parser = new RSSXMLMessageParser(
                    rssSource);
            List < RSSMessage > rssMessages = parser.readRSSMessages();
            System.out.println(rssSource.url);
            String SQL_INSERT = 
                    "INSERT INTO rss_message (title, link, description, "
                    +                   "author, language, "
                    +                   "copyright, pub_date, guidd" + ")"
                    +        " VALUES (?,?,?,?,?,?,?,?)";

            for (RSSMessage message : rssMessages) {
                //System.out.println(message);
                try (Connection conn = DriverManager.getConnection(
                        DATABASE_URL, DATABASE_USER, DATABASE_PASSWORD);
                     PreparedStatement preparedStatement =
                             conn.prepareStatement(SQL_INSERT)) {

                    preparedStatement.setString(1, message.getTitle());
                    preparedStatement.setString(2, message.getLink());
                    preparedStatement.setString(3, message.getDescription());
                    preparedStatement.setString(4, message.getAuthor());
                    preparedStatement.setString(5, message.getLanguage());
                    preparedStatement.setString(6, message.getCopyright());
                    preparedStatement.setString(7, message.getPubDate());
                    preparedStatement.setString(8, message.getGuidd());

                    List existingNews = getByLink(message.getLink());
                    System.out.println(existingNews);
                    if (existingNews.size() == 0) {
                        int row = preparedStatement.executeUpdate();
                        // rows affected
                        System.out.println(row); 
                    }


                } catch (SQLException e) {
                    System.err.format("SQL State: %s\n%s",
                            e.getSQLState(), e.getMessage());
                } catch (Exception e) {
                    Logger.getLogger(RSSMessageReadAndPersistTest
                            .class.getName()).log(Level.SEVERE, null, e);
                }
            }
            System.out.println(rssMessages.size());
        }
        
        public static List < String > getByLink(final String link) {

            List < String > result = new ArrayList < >();

            String SELECT_SQL = "SELECT link FROM rss_message " +
                    " WHERE link LIKE (?) ";

            try (Connection conn = DriverManager.getConnection(
                                DATABASE_URL, DATABASE_USER, DATABASE_PASSWORD);
                             PreparedStatement preparedStatement =
                                     conn.prepareStatement(SELECT_SQL)) {

                preparedStatement.setString(1, "%"+link+"%");

                try (ResultSet rs = preparedStatement.executeQuery()) {
                    while (rs.next()) {
                        result.add(rs.getString("link"));
                    }
                }
            } catch (SQLException e) {
                System.err.format("SQL State: %s\n%s",
                        e.getSQLState(), e.getMessage());
            }
            return result;
        }
}



public class RSSXMLMessageParser {
    static final String TITLE = "title";
    static final String DESCRIPTION = "description";
    static final String CHANNEL = "channel";
    static final String LANGUAGE = "language";
    static final String COPYRIGHT = "copyright";
    static final String LINK = "link";
    static final String AUTHOR = "author";
    static final String ITEM = "item";
    static final String PUB_DATE = "pubDate";
    static final String GUID = "guid";

    final URL url;
        private String extraCharacters = "";

    public RSSXMLMessageParser(final RSSMessageReadAndPersistTest.RssSource
    rssSource) {
            try {
                    this.url = new URL(rssSource.url);
                    this.extraCharacters = rssSource.extraCharacters;
            } catch (MalformedURLException e) {
                    throw new RuntimeException(e);
            }
    }

    public List < RSSMessage > readRSSMessages() throws IOException {
            List < RSSMessage > rssMessages = new ArrayList < >();
            try {
                    boolean isRSSMessageHeader = true;
                    // Set header values intial to the empty string
                    String description = "";
                    String title = "";
                    String link = "";
                    String language = "";
                    String copyright = "";
                    String author = "";
                    String pubdate = "";
                    String guid = "";

                    // First create a new XMLInputFactory
                    XMLInputFactory inputFactory =
                            XMLInputFactory.newInstance()
                                    //newDefaultFactory()
                                            ;
                    // Setup a new eventReader
                    InputStream in = read();
                    InputStream inputStream2 = null;
                    InputStream inputStream3 = null;
                    // Saving another opening and closing of the 
                    // HttpURLConnection where one HttpURLConnection
                    // per one RSS source in cost of
                    // internal access memory usage.
                    try {
                        ByteArrayOutputStream byteArrayOutputStream =
                                new ByteArrayOutputStream();
                        byte[] buffer = new byte[1024];
                        int len;

                        while ((len = in.read(buffer)) > -1 ) {
                            byteArrayOutputStream.write(buffer, 0, len);
                        }

                        byteArrayOutputStream.flush();

                        inputStream2 = new ByteArrayInputStream(
                                byteArrayOutputStream.toByteArray()); 
                        inputStream3 = new ByteArrayInputStream(
                                byteArrayOutputStream.toByteArray());
                        in.close();
                    } catch (IOException ex) {
                        Logger.getLogger(RSSXMLMessageParser.class
                                .getName()).log(Level.SEVERE, null, ex);
                    }

                    in = inputStream2;
                    XMLStreamReader xmlStreamReader = XMLInputFactory
                            .newInstance()
                            .createXMLStreamReader( in );
                    String fileEncoding = xmlStreamReader.getEncoding(); 
                    System.out.println(fileEncoding);
                    try {
                        in.close();
                    } catch (IOException ex) {
                        Logger.getLogger(RSSXMLMessageParser.class
                                .getName()).log(Level.SEVERE, null, ex);
                    }
                    in = inputStream3;//read();
                    //fileEncoding = "UTF-8"
                    //fileEncoding = "windows-1251";
                    System.out.println("fileEncoding inside: " + fileEncoding);
                    //replaceAll("[\\x00-\\x09\\x11\\x12\\x14-\\x1F\\x7F]", "")
                    //replaceAll("[\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F]", "")
                    if (!extraCharacters.isEmpty()) {
                        BufferedReader bufferedReader =
                                new BufferedReader(new InputStreamReader(in));
                        String result = "";
                        String temporaryString = null;
                        while ((temporaryString =
                                bufferedReader.readLine()) != null) {
                            // Apply regex on temporaryString and build output
                            result = result + temporaryString;
                        }
                        //replaceAll("[\\x00-\\x09\\x11\\x12\\x14-\\x1F\\x7F]", "");
                        //replaceAll("[\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F]", "");
                        result = result.replaceAll(
                        "[" + this.extraCharacters + "]", "");

                        in = new ByteArrayInputStream(result.getBytes());
                    } else {
                        System.out.println("no control characters to replace.");
                    }
                    XMLEventReader eventReader =
                            inputFactory.createXMLEventReader(in, 
                                    fileEncoding
                            );
                    
                    RSSMessage rssMessage = null;
                    // Read the XML document
                    while (eventReader.hasNext()) {
                        XMLEvent event = eventReader.nextEvent();
                        if (event.isStartElement()) {
                                String localPart =
                                        event.asStartElement().getName()
                                                .getLocalPart();
                                //System.out.println(localPart);
                                switch (localPart) {
                                case ITEM:
                                        if (isRSSMessageHeader) {
                                             isRSSMessageHeader = false;
                                             rssMessage = 
                                                     new RSSMessage(
                                                             title, link,
                                                     description,
                                                     language,
                                                     copyright, pubdate);
                                        }
                                        event = eventReader.nextEvent();
                                        break;
                                case TITLE:
                                        title = getCharacterData(
                                                event, eventReader);
                                        if(rssMessage != null) 
                                            rssMessage.setTitle(title);
                                        break;
                                case DESCRIPTION:
                                        description = getCharacterData(
                                                event, eventReader);
                                        if(rssMessage != null) 
                                            rssMessage.setDescription(
                                                    description);
                                        break;
                                case LINK:
                                        link = getCharacterData(
                                                event, eventReader);
                                        if(rssMessage != null) 
                                            rssMessage.setLink(link);
                                        break;
                                case GUID:
                                        guid = getCharacterData(
                                                event, eventReader);
                                        if(rssMessage != null) 
                                            rssMessage.setGuidd(guid);
                                        break;
                                case LANGUAGE:
                                        language = getCharacterData(
                                                event, eventReader);
                                        if(rssMessage != null) 
                                            rssMessage.setLanguage(
                                                    language);
                                        break;
                                case AUTHOR:
                                        author = getCharacterData(
                                                event, eventReader);
                                        if(rssMessage != null) 
                                            rssMessage.setAuthor(author);
                                        break;
                                case PUB_DATE:
                                        pubdate = getCharacterData(
                                                event, eventReader);
                                        //System.out.println(pubdate);
                                        if(rssMessage != null) 
                                            rssMessage.setPubDate(
                                                pubdate);
                                        break;
                                case COPYRIGHT:
                                        copyright = getCharacterData(
                                                event, eventReader);
                                        if(rssMessage != null) 
                                            rssMessage.setCopyright(
                                                    copyright);
                                        break;
                                }
                        } else if (event.isEndElement()) {
                                if (event.asEndElement()
                                        .getName().getLocalPart() 
                                        == (ITEM)) {
                                        RSSMessage message = 
                                                new RSSMessage(title,
                                                link, description,
                                                language,
                                                copyright, pubdate);
                                        rssMessage.setDescription(
                                                description);
                                            message.setTitle(title);
                                            message.setLink(link);
                                            message.setLanguage(
                                                    language);
                                            message.setCopyright(
                                                    copyright);
                                            message.setAuthor(author);
                                            message.setPubDate(pubdate);
                                            message.setGuidd(guid);
                                            rssMessages.add(message);
                                        //rssMessage.getMessages()
                                            //.add(message);
                                        event = eventReader.nextEvent();
                                        continue;
                                }
                        }
                    }
                    try {
                        in.close();
                    } catch (IOException ex) {
                        Logger.getLogger(RSSXMLMessageParser.class
                                .getName()).log(Level.SEVERE, null, ex);
                    }
                    if(rssMessage != null) {
                        rssMessage.setDescription(description);
                        rssMessage.setTitle(title);
                        rssMessage.setLink(link);
                        rssMessage.setLanguage(language);
                        rssMessage.setCopyright(copyright);
                        rssMessage.setAuthor(author);
                        rssMessage.setPubDate(pubdate);
                        rssMessage.setGuidd(guid);
                        rssMessages.add(rssMessage);
                    }
            } catch (XMLStreamException e) {
                    throw new RuntimeException(e);
            }
            return rssMessages;
    }

    private String getCharacterData(/*non final*/ XMLEvent event,
            final XMLEventReader eventReader)
                    throws XMLStreamException {
            String result = "";
            event = eventReader .nextEvent();
            if (event instanceof Characters) {
                    result = event.asCharacters().getData();
            }
            return result;
    }

    private InputStream read() {
            try {
                HttpURLConnection conn =
                        (HttpURLConnection) url.openConnection();
                conn.setRequestProperty("Accept-Encoding", "gzip");
                try {
                    conn.connect();
                } catch (IOException ex) {
                    Logger.getLogger(RSSXMLMessageParser.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
                String contentEncoding = conn.getContentEncoding();
                boolean isGzip = contentEncoding != null
                        && contentEncoding.contains("gzip");
                InputStream in = !isGzip ? conn.getInputStream()
                        : new GZIPInputStream(conn.getInputStream());
                return in;
            } catch (IOException e) {
                    throw new RuntimeException(e);
            }
    }
}



/*
 * Stores an RSS rss_message
CREATE TABLE `rss_message` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `author` text DEFAULT NULL,
  `copyright` text DEFAULT NULL,
  `description` text DEFAULT NULL,
  `guidd` text DEFAULT NULL,
  `language` text DEFAULT NULL,
  `link` text DEFAULT NULL,
  `pub_date` text DEFAULT NULL,
  `title` text DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
 */
public class RSSMessage {

    String title;
    String link;
    String description;
        String author;
    String language;
    String copyright;
        String pubDate;
        String guidd;

    public RSSMessage(String title, String link, String description,
                        String language,
            String copyright, String pubDate) {
        this.title = title;
        this.link = link;
        this.description = description;
        this.language = language;
        this.copyright = copyright;
        this.pubDate = pubDate;
    }

    public String getTitle() {
        return title;
    }

    public String getLink() {
        return link;
    }

    public String getDescription() {
        return description;
    }

    public String getLanguage() {
        return language;
    }

    public String getCopyright() {
        return copyright;
    }

    public String getPubDate() {
        return pubDate;
    }

    @Override
    public String toString() {
        return "rss_message [copyright=" + copyright +
                        ", description=" + description
                + ", language=" + language +
                        ", link=" + link + ", pubDate="
                + pubDate + ", title=" + title + "]";
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setLink(String link) {
        this.link = link;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public void setCopyright(String copyright) {
        this.copyright = copyright;
    }

    public void setPubDate(String pubDate) {
        this.pubDate = pubDate;
    }

    public String getGuidd() {
        return guidd;
    }

    public void setGuidd(String guidd) {
        this.guidd = guidd;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

The update from 2020-08-18.

In case the building, that room has its own computer device with internet connectivity, by using the code above that computer can connect for example to the utility service providers (including the internet providers) media services of those companies, in case such companies are providing such media services, and that computer can notify on its own from the building, the room point of view to those who may consume that message about, for example, maintenance pauses, pauses becauses of renovations, and other event from those companies' sides after once the setup is in provision.

Such approach reminds a bit that case, when conventional objects receive their computers for their own purposes as for roads.

The main difference from other approaches is, that the open source and private source are in use in this approach for RSS client and as long as RSS client only makes informational requests for past information, which is controlable by those companies, the hacking chances are pretty low.

Unless when the RSS server has such a quirky configuration, that the information request from RSS client initiates a purposeful three dimesional building or room printing disrupting the conventional RSS informational request purpose. Then such hacking chances are higher for misuse.

A quirky configuration is a tryout for a mediocre joke, thus recalling that HTTP is a protocol and as long as RSS is also a data format, the weak argument is, that during the development of HTTP the text and other content are transferrable via that protocol. So its scope has a showcase evitable or inevitable extension. The same can happen for RSS, because RSS is a web feed or a news feed, it is configurable for more uses, because an event for printing a house or a room three dimensionally is also news from some point of view. Either it is private or public news has relation with authentication protocol where RSS data format is in use.

In case when I measure (automatic meter measures) and send the measurement results as data to computer first(for duplication and extra reservation of data, especially when the automatic meter does not reserve them) or directly to server with the environment data in order to support high quality of service provision by registering or monitoring or else http://51.15.247.86/measurement/title/temperature/in/the/boiler/address/Street/Street/1111/date/2020/08/18/11/11/AM/EEST/11/11/value/high/unit/Celsius and receive, for example:


<rss>
<channel>
  <item>
    <!--id>166</id-->
    <title>Temperature in the boiler</title>
    <address>Street Street 1111</address>
    <date>2020-08-18 11:11 AM EEST 11:11</date>
    <value>high</value>
    <unit>Celsius</unit>
  </item>
</channel>
</rss>

The update from 2020-11-08.

In order to improve I consider either connecting it with https://www.rabbitmq.com/getstarted.html system or adding several agents as classes for filtering, topicing, sending.

The update from 2020-12-28.


    get_internet_news.abc
    get_not_internet_news_in_internet.abc

Інший RSS стрічковий клієнт з можливістю збереження до бази даних.

Оновлення від 2020-08-18.

У випадку наявності у будинку, кімнаті їх власного обчислювального пристрою з інтернет підключенням, використовуючи той код зверху той обчислювальний пристрій може під'єднуватися наприклад до постачальників послуг корисностей (включаючи інтернет постачальників) до засобів масової інформації тих компаній, у випадку наявності надання подібніми компаніями подібніх послуг засобів масової інформації, і той обчислювач може повідомляти самостійно з боку будинку, кімнати, тим, хто може спожити таке повідомлення про, наприклад, паузи обслуговування, паузи з-за оновлень, і інші події з боку тих компаній після того як налаштування для обчислювача встановлені одного разу.

Подібний спосіб нагадує дещо той випадок, коли узгоджені об'єкти отримують їх власні обчислювальні пристрої для їх власних цілей як для шляхів.

Головним відрізненням від інших способів є те, що відкритий і власний код є може бути у використанні цим способом для RSS стрічкового клієнту і настільки довго як RSS стрічковий клієнт запитує лише по інформаційних запитах по попередню інформацію, яка є контрольованою тими компаніями, вирогідність хакінг зламу недоцільно низькі.

Допоки RSS стрічковий обслуговувач не має такого незграбного конфігураційного налаштування, завдяки якому інформаційний запит від RSS стрічковий клієнт починає цільовий тривимірний друк будинка чи кімнати, перериваючи узгоджений RSS інформаційно запитову ціль. Тоді така вирогідність хакінг зламу є вищою для недоцільного використання.

Незграбне конфігураційне налаштування є спробою посереднього жарту, таким чином згадуючи що HTTP ГТТП є протоколом і настільки довго як RSS ДПО є також форматом даних, слабкий аргумент, що протягом розвитку HTTP ГТТП текст і інший вміст є переміщуваними за допомогою того протоколу. Так його обсяг має показ минучого чи неминучого розширення. Те саме може трапитися для RSS ДПО, тому що RSS ДПО є веб стрічкою чи стрічкою новин, він є налаштовуваним для більшої кількості використань, тому що подія друку будинку чи кімнати тривимірно є теж новиною з якоїсь точки зору. Чи приватно зачинено чи публічно відчинено, у новини є взаємозв'язок з автентифікаційним протоколом, порядком процедури встановлення належності користувачеві інформації в системі пред'явленого ним визначника де RSS ДПО використовується як формат даних.

У випадку коли я вимірюю (автоматичний датчик вимірює) і надсилає результат вимірювання як дані до обчислювача спочатку(для дублювання і додаткового повторного збереження даних, особливо якщо автоматичний датчик їх не зберігає) чи спрямовано до обробника з даними середовища для того щоб підтримати високу якість надання послуги реєстрацією чи спостереженням чи чимось ще http://51.15.247.86/вимірювання/назва/температура/у/нагрівачі/адреса/Вулиця/Вулиця/1111/дата/2020/08/18/11/11/після/світанку/СЄСЧ/11/11/значення/висока/одиниця/Цельсія і отримує, наприклад:


<ДПО>
<канал>
  <штука>
    <!--id>166</id-->
    <назва>температура у нагрівачі</назва>
    <адреса>Вулиця Вулиця 1111</адреса>
    <дата>2020-08-18 11:11 AM EEST 11:11</дата>
    <значення>висока</значення>
    <одиниця>Цельсія</одиниця>
  </штука>
</канал>
</ДПО>

Оновлення від 2020-11-08.

Для того щоб покращити я вважаю чи під'єднання тих класів до https://www.rabbitmq.com/getstarted.html системи чи додавання декількох агентів як класи для фільрування, тематизування, надсилання.

Оновлення від 2020-12-28.


    отримати_інтернет_новини_в_інтернеті.абв
    отримати_не_інтернет_новини_в_інтернеті.абв

    отримати_інтернет_новини_в_інтернеті.звуковий_абв
    отримати_не_інтернет_новини_в_інтернеті.звуковий_абв

    отримати_інтернет_новини_в_інтернеті.візуальний_абв
    отримати_не_інтернет_новини_в_інтернеті.візуальний_абв

    //..//

    отримати_інтернет_новини_в_інтернеті_у_формі_абв.абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_абв.абв

    отримати_інтернет_новини_в_інтернеті_у_формі_абв.звуковий_абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_абв.звуковий_абв

    отримати_інтернет_новини_в_інтернеті_у_формі_абв.візуальний_абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_абв.візуальний_абв

    отримати_інтернет_новини_в_інтернеті_у_формі_звука.абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_звука.абв

    отримати_інтернет_новини_в_інтернеті_у_формі_звука.звуковий_абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_звука.звуковий_абв

    отримати_інтернет_новини_в_інтернеті_у_формі_звука.візуальний_абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_звука.візуальний_абв

    отримати_інтернет_новини_в_інтернеті_у_формі_візуальній.абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_візуальній.абв

    отримати_інтернет_новини_в_інтернеті_у_формі_візуальній.звуковий_абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_візуальній.звуковий_абв

    отримати_інтернет_новини_в_інтернеті_у_формі_візуальній.візуальний_абв
    отримати_не_інтернет_новини_в_інтернеті_у_формі_візуальній.візуальний_абв

    отримати_новини.абв --які_саме х --у_якій_формі y --у_якому_місці з
    отримати_новини.звуковий_абв --які_саме х --у_якій_формі y --у_якому_місці з
    отримати_новини.візуальний_абв --які_саме х --у_якій_формі y --у_якому_місці з

    отримати.абв --що_саме x --які_саме у --у_якій_формі з --у_якому_місці д
    отримати.звуковий_абв --що_саме x --які_саме у --у_якій_формі з --у_якому_місці д
    отримати.візуальний_абв --що_саме x --які_саме у --у_якій_формі з --у_якому_місці д

    отримати --яким_абв_отримати x --що_саме у --які_саме з --у_якій_формі д --у_якому_місці г

Оновлення від 2021-05-27.

Update as of 2021-05-27.

This RSS client does not support some previous SSL certificates.

Цей RSS стрічковий клієнт не підтримує деякі попередні есесель SSL БРШ сертифікати.

Оновлення від 2022-01-29.

Update as of 2022-01-29.

Через роки а деякі низькорівневе ПЗ для баз даних досі стало виконують свої методи. І можливо вимагають підвищенної точності їх застосування. І це навіть не про відсутність питання Ви впевнені наприклад перед деякими операціями і не про Зберегти додаткову копію даних наприклад перед деякими операціями. Хоча це і інтерактивно але введення паролів перед деякими операціями теж інтерактивно у них. Мабуть це один з недоліків принципа одиничної розширюваності. І адже наступна міграція RDBMS, зміна RDBMS чи повторний запис даних буде або вдалою або ні це досі стосовно одне до одного. Незважаючи щодо ймовірної присутності баз даних з більш ніж ТБайт обсягами і можливих невідомих мені надбудов іншого ПЗ над цими низькорівневими ПЗ у випадку втрати даних досі залишається можливість для них бути зразком особистого типу бути забутими. Однак тоді не треба забувати і про декілька аспектів таких випадків як то перший що за їх присутності і невиконнаня обох залишається можливість посилатися на потребу знати про необхідність створення копій даних самотужки як про такий існуючий процес що не запобігає подібним описаним випадкам через роки їх застосування; другий це те що саме такі методи тренують щонайменш особисту точність протягом їх застосування навіть якщо не покращують особисту пам'ять про ту необхідність щоразу краще до наступного моменту особистого типу бути забутими про такі втрати даних; і третій що наприклад гіт git саме додається у середину процесу але не процесу RDBMS і усуває подібні випадки частково з єдиним відрізненням що це є переважно для коду хоча там можливо присутні і такі копії даних теж тому що обидва про файли; і четвертий про можливість створення такого ПЗ для такого інтерактивного автоматизованного процесу самотужки повторюючи що разу індивідуально для кожного ПЗ яке використовує такі деякі RDBMS .

І хоча ймовірно існує подібний параметр чи аргумент для усунення цього інтерактивно чи інакше але його необов'язковість замість обов'язковості або навпаки у інших випадках викликала би багатомільйонні зміни після впровадження такої зміни для попередження подібних втрат даних у існуючих базах даних що викликало би несумісніть але при незмінності це підтримує повторення подібних ситуацій про втрати даних раз за разом за недотримання одного з аспектів через роки або би повторенно наполягало до його застосування як ППІ чи інакше щоби уминути подібних ситуацій що безперечно повертало би до одного з вищезазначених аспектів.

І хоча такий випадок про обов'язковість чи необов'язковість для такого аргумента чи такого параметра можливо вгадати протягом дизайна і архітектури або навіть виконання такого ПЗ чим більш застосовуємим стає подібне ПЗ після його запуска тим складнішою стає подальша подібна зміна навіть із застосуванням зібраних статистистичних даних якщо такі збиралися і що є більш складнішим за умови незбирання статистичних даних про це про що все ж таки можливо пізніше знайти наприклад у відгуках навіть якщо запити туди неможливі.

https://www.palletsprojects.com/p/click/.